Skip to content

Create Week10 Mission 1, 2, senior#46

Open
0Whitebird0 wants to merge 2 commits into
mainfrom
Week10/OneStone
Open

Create Week10 Mission 1, 2, senior#46
0Whitebird0 wants to merge 2 commits into
mainfrom
Week10/OneStone

Conversation

@0Whitebird0
Copy link
Copy Markdown
Contributor

📝 미션 번호

10주차 Misson 1, 2, senior

📋 구현 사항

  • aab 파일 생성 : C:\Users\sshhs\StudioProjects\Android\Week10\OneStone\app\release
  • codex.md 파일 생성 후 규칙 부여
  • hilt기반으로 코드 일부 변경

📎 스크린샷

✅ 체크리스트

  • [v] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • [v] 에뮬레이터 또는 실제 기기에서 정상 동작하나요?
  • [v] 불필요한 주석 및 Log가 제거되었나요?

🤔 질문 사항

@0Whitebird0 0Whitebird0 requested a review from Dawon-Y May 31, 2026 07:15
@0Whitebird0 0Whitebird0 self-assigned this May 31, 2026
@Dawon-Y
Copy link
Copy Markdown
Contributor

Dawon-Y commented Jun 2, 2026

안녕하세요! 10주차 과제 진행하시느라 고생 많으셨습니다💚


0) 제출 체크(요구사항 관점에서 먼저)

AAB 경로 PR에 업로드

  • 문서가 아직 RELEASE.md/README.md/CLAUDE.md 형태로는 안 보이고, 대신 codex.md가 존재합니다.
  • AAB 출력 경로는 표준 Gradle 기준으로 아래가 맞습니다:
    • app/build/outputs/bundle/release/app-release.aab
  • PR 본문에 이 경로를 명시하면 1번은 충족됩니다.

CLAUDE.md “프로젝트 루트”에 없음

  • 폴더 루트(Week10/OneStone/)에는 CLAUDE.md가 없고 codex.md만 있습니다.
  • 과제 요구가 “CLAUDE.md 파일 작성”이므로 codex.md를 CLAUDE.md로 대체/복제하는 형태가 필요합니다.

Claude Code로 리뷰 받고 개선했다는 “증빙 문서”가 부족

  • CLAUDE.md 안에 ‘리뷰 결과 요약 + 반영 내용(파일/항목)’을 한 섹션으로 넣는 걸 추천합니다.

1) CLAUDE.md 작성 가이드 & 현재 codex.md 리뷰

codex.md는 내용 퀄리티가 꽤 좋음

  • 인코딩 규칙(UTF-8 BOM 금지) 명시: 실무에서도 유효
  • MVI 규칙/단방향 흐름/상태 immutable 지향
  • 네이밍/상수/Compose 구조 원칙
  • 함수 주석 규칙(한글 설명)까지 있음

다만 과제 요구 “CLAUDE.md”로는 부족한 부분

  • 기술 스택이 너무 일반적(Compose/Coroutines까지만)이고, 실제 프로젝트에는 Hilt/Retrofit/OkHttp/Coil/Navigation SafeArgs/Datastore 등이 들어가 있음 → 이걸 문서에 적어야 “프로젝트 루트 가이드”가 됩니다.
  • “배포(AAB)/서명/키 관리 주의사항”이 codex.md에는 없음

권장

  • codex.md를 기반으로 루트에 CLAUDE.md 생성하고 다음 섹션을 추가하면 좋습니다:
    1. 아키텍처 구조(패키지 구조 기준)
    2. 기술 스택(실제 사용 라이브러리)
    3. 코드 컨벤션(현재 codex.md 내용 대부분 재사용 가능)
    4. 주의사항(서명파일/키/로그/릴리즈 빌드)
    5. AAB 빌드 명령 + 출력 경로
    6. Claude Code 사용 예시 + 리뷰 반영 내역(짧은 bullet)

2) 빌드/배포(AAB) 관점 리뷰 (app/build.gradle.kts)

좋은 점

  • 의존성 구성은 과제 범위엔 충분(Compose + Retrofit + OkHttp + Hilt + Coil3)
  • release { isMinifyEnabled = false }는 과제 제출용으로 빌드 안정성↑

시니어 관점 핵심 이슈 2개

  1. minSdk = 33 (Line 25)

    • 과제/동아리 앱이면 보통 24~26 정도로 잡는데, 33이면 사용자 풀이 확 줄어듭니다.
    • “의도적으로 최신만”이 목적이 아니라면 24~26 권장.
  2. compileSdk/targetSdk 36

    • 팀/채점 환경이 최신 SDK(36) 아닐 경우 빌드가 막힐 수 있습니다.
    • 제출 안정성이 중요하면 34/35로 맞추는 게 안전(가이드가 36을 요구하면 유지).

3) 네트워크/보안(가장 중요): NetworkModule.kt 하드코딩 키 (치명)

private const val REQ_RES_API_KEY = "reqres_3eb039d9ecd24873b53b35fb4d3ad155"
...
.addHeader("x-api-key", REQ_RES_API_KEY)

이건 **“절대 하면 안 되는 패턴”**입니다. (과제 요구도 “로컬/환경변수로 분리”)

왜 문제냐

  • 키가 Git에 영구히 남습니다(레포 공개/공유 시 바로 유출)
  • 회수/교체 어려움
  • 릴리즈 빌드/디버그 빌드의 키 전략도 분리 불가

권장 해결책(실무형, 과제에도 잘 맞음)

  • local.propertiesBuildConfig.REQRES_API_KEY로 주입하고,
  • NetworkModuleBuildConfig.REQRES_API_KEY를 읽어 header 추가.
  • 키가 비어있으면(설정 누락) 개발 단계에서 명확히 실패시키거나 토스트 안내.

LinLin/Deku가 이미 이런 패턴을 적용했었고, OneStone도 동일하게 맞추는 게 베스트입니다.


4) ReqRes API 설계 문제: getMissingUser() 타입 불일치 (Week09 때와 동일하게 남아있음)

@GET("api/users/23")
suspend fun getMissingUser(): ReqResUsersResponse
  • GET /api/users/23Single User 응답인데, 반환 타입이 “UsersResponse(List)”면 파싱 크래시 가능성이 큽니다.
  • “일부러 404/에러 확인용”이라도, 타입/엔드포인트는 정확해야 합니다.

권장

  • 필요 없으면 삭제.
  • 유지하려면 Response<SingleUserResponse> 형태로 분리해서 code 체크.

5) 디버그 유틸: ReqResDebugConfig / ReqResLoggingInterceptor 리뷰

좋은 점

  • API key를 마스킹하여 로그 노출 방지: 매우 좋음
  • forceHttpErrorCode로 강제 실패 시나리오 테스트: 학습/디버그 목적에 좋음

개선 포인트

  • ReqResDebugConfig.forceHttpErrorCode빌드 타입에 따라 동작해야 합니다.
    • 지금은 null/400/500 수동 변경이지만, 실수로 release에서 켜질 수 있습니다.
    • 최소한 if (!BuildConfig.DEBUG) ignore 같은 가드가 필요합니다.
  • forced response가 body만 바꾸고 있는데, 실제 서버 에러 형태와 달라 UI 처리 테스트가 왜곡될 수 있습니다(선택).

6) Profile UI/VM 리뷰 (ProfileScreen, ProfileViewModel, ProfileFragment)

좋은 점

  • Compose 화면에서 HorizontalPager + “선택 시 Dialog” 패턴으로 요구사항 흐름 자체는 잘 잡혀있음
  • Pinch zoom을 위한 gesture/graphicsLayer를 넣은 흔적이 보임(구현 의도 좋음)

시니어 개선 포인트

  1. Toast를 state로 트리거 (LaunchedEffect(uiState.errorMessage))

    • errorMessage가 상태에 남아있으면 재진입/재구성 시 반복 노출 가능
    • 이벤트는 SharedFlow/Channel 또는 “consume 후 null로 초기화” 패턴이 안전
  2. collectAsState()collectAsStateWithLifecycle() 권장

    • 컴포즈 lifecycle 연동이 더 안정적입니다.
  3. ProfileFragmentView(requireContext())만 반환

    • 네비 그래프에 남아있다면 “하얀 화면” 버그가 됩니다.
    • 정말 Compose만 쓸 거면 destination 제거 or 최소 안내 화면을 보여주는 게 맞습니다.
  4. ProfileViewModel.loadUserProfile()에서 “성공 시 state 통째 교체” 혼용

    • setState { loadedState }로 전체 갈아끼우는 방식도 동작은 하지만,
    • setState { copy(...) } 컨벤션을 유지하는 편이 예측 가능성이 큽니다.

7) 결론

반드시 고쳐야 하는 것(우선순위 TOP)

  1. NetworkModule API Key 하드코딩 제거 (local.properties/BuildConfig로 이동)
  2. ReqResApiService.getMissingUser() 반환 타입/용도 정리(삭제 or 타입 분리)
  3. 루트에 CLAUDE.md 작성(현재 codex.md 기반으로 확장) + “AAB 경로/Claude 리뷰 반영 내역” 섹션 포함

있으면 더 좋은 것

  • BuildConfig.DEBUG로 DebugConfig 기능을 release에서 비활성화
  • Profile의 에러 메시지를 1회성 이벤트로 처리
  • collectAsStateWithLifecycle()로 변경

워크북 진행하시느라 수고하셨습니다! 궁금한 점 있으시면 언제든 말씀해 주세요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants