Skip to content

Feature: [Task-219] 미연동 API 화면 연동 - #45

Merged
KimSungBeen merged 14 commits into
mainfrom
feature/Task-219-api-integration
Aug 17, 2026
Merged

Feature: [Task-219] 미연동 API 화면 연동#45
KimSungBeen merged 14 commits into
mainfrom
feature/Task-219-api-integration

Conversation

@KimSungBeen

Copy link
Copy Markdown
Collaborator

Description

data에 구현만 되어 있고 화면에서 쓰이지 않던 API 11개를 전부 연동했습니다. 더미 데이터를 제거하고 UseCase → ViewModel → 기존 화면으로 배선했으며, 회원 큐레이션은 별도 작업(#44)에서 이미 연동되어 범위에서 제외했습니다.

# 커밋 API → 화면
1 마이 화면에 회원 프로필 조회 연동 GET /members/me → 마이
2 프로젝트 리스트·홈에 목록 조회 연동 GET /projects → 리스트·홈 카드
3 프로젝트 상세에 상세 조회 연동 GET /projects/{id} → 상세
4 프로젝트 삭제 API 연동 DELETE /projects/{id} → 리스트 모달·상세 메뉴
5 문제 풀이에 학습 세트 조회 연동 GET …/sets/{setId} → 풀이 (N문제 순회로 일반화)
6 4지선다 답변 제출 연동 POST …/answers/choice → 서버 채점 반영
7 서술형 답변 제출 연동 POST …/answers/essay → 채점 기준 표시
8 북마크 목록 조회 연동 GET /projects/bookmarks → 저장 화면 + 필터 재조회
9 문제 북마크 연동 POST …/bookmark → 풀이·저장 화면 토글
10 설정에 개발 분야 변경 연동 POST /members/me/position + 선택 화면 신설
11 설정에 개발 수준 변경 연동 POST /members/me/career-level + 선택 화면 신설

커밋은 연동 하나당 1커밋이며, 각 커밋 시점에서 ktlintCheck + 관련 모듈 테스트가 통과합니다.

새 화면 (Figma 시안 그대로)

설정의 개발 분야 선택(node 1535-18281)·개발 수준 선택(node 1535-18378) 화면 2개만 신설했습니다.

  • 새 컴포넌트 없이 디자인시스템 GitItSelectCard·GitItTopBar(LargeTitle)를 재사용했고, 썸네일은 시안의 플레이스홀더 이미지를 온보딩 리소스에서 복사했습니다.
  • 디자인 주석("저장 및 이전 페이지로 이동")대로 카드 탭은 선택만 하고, 뒤로가기에서 저장 후 이동합니다. 선택이 안 바뀌면 요청을 보내지 않습니다.
  • 설정 루트의 분야/수준 하드코딩 값은 프로필 조회 값으로 바뀌고, 선택 화면에서 돌아오면 재조회합니다.

설계 판단

  • 문제 풀이 흐름 일반화 — 고정 2문제 샘플 흐름을 세트의 문제 목록(개수·형식 가변)을 순서대로 진행하도록 바꿨습니다. 기존 객관식/서술형 화면 컴포넌트를 그대로 재사용했고 새 UI는 없습니다. 모르는 문제 형식은 표시할 화면이 없어 걸러냅니다.
  • 세트 자동 선택 — 세트 지정 없이 풀이에 진입하면(홈/리스트 재생 버튼) 프로젝트 상세의 진행률로 "아직 다 풀지 않은 첫 세트"를 이어 풉니다. 세트 라벨과 출처 저장소 이름도 상세에서 가져옵니다.
  • 채점 결과는 서버가 정본 — 4지선다는 서버 정답·해설을 반영하고, 서술형은 채점 기준의 만점 예시를 모범 답안으로 표시합니다. 북마크도 요청 값이 아니라 서버가 적용한 상태를 화면에 반영합니다.
  • 실패 처리 — 조회 실패는 이전(또는 빈) 상태 유지 + 로그, 제출 실패는 재시도 가능한 상태 유지. 에러 안내 UI는 디자인에 없어 추가하지 않았습니다.
  • answeredAt은 ISO-8601 문자열 유지 — 날짜 타입은 라이브러리 추가(kotlinx-datetime) 또는 디슈가링(minSdk 24)이 필요해 보류했습니다.

Notes

  • main(Feature: [Task-127] 프로젝트 등록 기반 문제 생성 흐름 추가 #41~Feature: [Task-210] 스플래시 분기처리 추가 및 온보딩 API 연동 #44)을 rebase로 반영했습니다. 충돌은 Di.kt 등록 블록 하나였고(스플래시 등록 vs 신규 등록), 병합 트리에서 전체 빌드·테스트로 검증한 해결안을 적용했습니다.
  • main에서 온 feature/quiz create 테스트 페이크 2개가 커진 ProjectRepository를 구현하지 않아 컴파일이 깨져 있던 것을 커밋 5에서 함께 고쳤습니다.
  • 화면이 있는 feature 모듈들이 domain에 의존하지 않던 상태라 my·home·bookmark·projectlist·projectdetaildomain·logging·koin 의존을 추가했습니다. ViewModel 생성은 기존 projectdetail 패턴대로 shared Di.kt에 등록했습니다.

검증

./gradlew ktlintCheck --continue                              BUILD SUCCESSFUL
feature 6개 jvmTest + :domain:test + :data:test + :core:network:test   130개 전부 통과
./gradlew :shared:jvmTest :shared:testAndroidHostTest         BUILD SUCCESSFUL
./gradlew :androidApp:compileDebugKotlin :desktopApp:compileKotlin     BUILD SUCCESSFUL

체크리스트

  • 영향을 받는 플랫폼을 확인했습니다.
  • 관련 없는 변경 사항을 제거했습니다.

🤖 Generated with Claude Code

- GET /api/v1/members/me를 GetMemberProfileUseCase로 노출하고 MyViewModel이 진입 시 조회한다
- 더미 상태를 제거하고 프로필·학습 통계·주간 차트를 서버 값으로 채운다
- Position·CareerLevel 표기 라벨 매핑을 feature 모듈에 두고, 큐레이션 전(null)은 빈 라벨로 둔다
- 조회 실패 시 빈 상태를 유지하고 로그만 남긴다. 에러 화면 디자인이 아직 없다
- ktlintCheck, :feature:my:allTests, :domain:test, :shared:jvmTest 통과
- GET /api/v1/projects를 GetProjectsUseCase로 노출하고 두 화면이 진입 시 조회한다
- 더미 목록을 제거하고 저장소 이름·기술 스택·현재 세트·진행률을 서버 값으로 채운다
- 홈 Refresh 인텐트가 목록을 다시 조회하도록 연결했다
- 페이지 크기는 서버 기본값(10)을 쓴다. 무한 스크롤은 화면 디자인이 없어 다루지 않았다
- ktlintCheck, :feature:projectlist:jvmTest, :feature:home:jvmTest, :domain:test, :shared:jvmTest 통과
- GET /api/v1/projects/{projectId}를 GetProjectDetailUseCase로 노출하고 진입 시 조회한다
- 더미 상태를 제거하고 저장소 정보·학습 세트·전체 진행률을 서버 값으로 채운다
- 스타 수는 기존 카드 표기(3.6k)에 맞춰 소수 한 자리 k 표기로 축약한다
- 세트 진행률은 completedCount/problemCount로 계산하고 프로그레스 칸 수는 문제 수를 쓴다
- ktlintCheck, :feature:projectdetail:jvmTest, :domain:test, :shared:jvmTest 통과
- DELETE /api/v1/projects/{projectId}를 DeleteProjectUseCase로 노출한다
- 리스트 삭제 모달 확정 시 로컬 필터 대신 서버 삭제를 호출하고, 성공했을 때만 목록에서 제거한다
- 상세 더보기 삭제도 서버 삭제 성공 시에만 홈으로 이동한다
- 실패 시 목록·화면을 유지하고 로그만 남긴다. 실패 안내 UI는 디자인에 없어 추가하지 않았다
- ktlintCheck, :feature:projectlist:jvmTest, :feature:projectdetail:jvmTest, :domain:test, :shared:jvmTest 통과
- GET /api/v1/projects/{projectId}/sets/{setId}를 GetLearningSetUseCase로 노출한다
- 고정 2문제 샘플 흐름을 세트의 문제 목록을 순서대로 진행하는 구조로 일반화했다
  기존 객관식·서술형 화면 컴포넌트를 그대로 재사용하고 새 UI는 만들지 않았다
- 세트 식별자가 없으면 프로젝트 상세로 아직 다 풀지 않은 첫 세트를 골라 이어 푼다
  세트 라벨과 출처 저장소 이름도 상세에서 가져온다
- 클라이언트가 모르는 문제 형식은 표시할 화면이 없어 걸러낸다
- 정답·해설은 제출 응답에만 있으므로 채점 반영은 다음 커밋의 제출 연동에서 다룬다
- main에서 온 quiz create 테스트 페이크가 커진 ProjectRepository를 구현하지 않아
  컴파일이 깨져 있던 것을 함께 고쳤다
- ktlintCheck, :feature:quiz:jvmTest, :domain:test, :shared:jvmTest, :androidApp:compileDebugKotlin 통과
- POST /api/v1/projects/{projectId}/questions/{questionId}/answers/choice를
  SubmitChoiceAnswerUseCase로 노출하고 정답 확인 시 서버에 제출한다
- 로컬 채점을 제거하고 서버가 준 정답 번호·해설을 현재 문제에 반영한다
  선택한 답과 정답을 함께 펼쳐 기존 결과 화면 규칙을 그대로 따른다
- 제출이 실패하면 미제출 상태를 유지해 같은 답으로 다시 시도할 수 있다
- ktlintCheck, :feature:quiz:jvmTest, :domain:test, :shared:jvmTest 통과
- POST /api/v1/projects/{projectId}/questions/{questionId}/answers/essay를
  SubmitEssayAnswerUseCase로 노출하고 정답 확인 시 서버에 제출한다
- 채점 기준의 만점 답안 예시를 결과 화면의 모범 답안으로 표시한다
- 빈 답안은 서버가 400으로 거부하므로 제출하지 않는다
- 제출이 실패하면 작성 중 상태를 유지해 다시 시도할 수 있다
- ktlintCheck, :feature:quiz:jvmTest, :domain:test, :shared:jvmTest 통과
- GET /api/v1/projects/bookmarks를 GetBookmarkedQuestionsUseCase로 노출하고 진입 시 조회한다
- 더미 목록을 제거하고 전체 필터 뒤에 북마크가 있는 프로젝트 필터를 서버 값으로 잇는다
- 필터를 선택하면 projectId 조건으로 서버에 다시 조회한다
- 카드 메타는 서버 값으로 "프로젝트 · 세트 · 문제 N" 형식을 유지한다
- ktlintCheck, :feature🔖jvmTest, :domain:test, :shared:jvmTest 통과
- POST /api/v1/projects/{projectId}/questions/{questionId}/bookmark를
  BookmarkQuestionUseCase로 노출한다
- 문제 풀이·저장한 문제 화면의 로컬 토글을 서버 설정으로 바꾸고,
  요청 값 대신 서버가 적용한 상태를 화면에 반영한다
- 설정이 실패하면 표시 상태를 유지하고 로그만 남긴다
- ktlintCheck, :feature🔖jvmTest, :feature:quiz:jvmTest, :domain:test, :shared:jvmTest 통과
- POST /api/v1/members/me/position을 UpdatePositionUseCase로 노출한다
- Figma 시안대로 개발 분야 선택 화면을 추가한다 (node 1535-18281)
  디자인시스템 GitItSelectCard·GitItTopBar를 재사용하고 새 컴포넌트는 만들지 않았다
- 디자인 주석대로 카드 선택은 화면 안에서만 반영하고, 뒤로가기에서 저장 후 이전 화면으로 이동한다
  선택이 그대로면 저장 요청을 보내지 않고, 저장이 실패해도 이동하며 로그만 남긴다
- 설정 화면의 분야·수준 하드코딩 값을 프로필 조회 값으로 바꾸고,
  선택 화면에서 돌아올 때 다시 조회해 최신 값을 표시한다
- 썸네일은 시안의 플레이스홀더 이미지를 온보딩 리소스에서 복사해 사용한다
- ktlintCheck, :feature:my:jvmTest, :domain:test, :shared:jvmTest, :androidApp:compileDebugKotlin 통과
- POST /api/v1/members/me/career-level을 UpdateCareerLevelUseCase로 노출한다
- Figma 시안대로 개발 수준 선택 화면을 추가한다 (node 1535-18378)
  개발 분야와 같은 SettingsSelectionScreen을 쓰고 수준별 설명 문구는 시안 그대로 담았다
- 디자인 주석대로 카드 선택은 화면 안에서만 반영하고, 뒤로가기에서 저장 후 이전 화면으로 이동한다
- 설정 화면의 개발 수준 행을 선택 화면으로 연결한다
- ktlintCheck, :feature:my:jvmTest, :domain:test, :shared:jvmTest,
  :shared:testAndroidHostTest, :androidApp:compileDebugKotlin 통과
- 홈 헤더의 이름·역할이 더미 기본값(김이박·Junior Developer)으로 남아 있어
  서버 프로필이 화면에 노출되지 않던 것을 연동한다
- 역할 표기는 시안의 Junior Developer 패턴을 개발 수준별로 잇는다
  (Entry·Junior·Middle·Senior Developer). 큐레이션 전이면 빈 문자열이다
- Refresh 인텐트가 프로필도 함께 다시 조회한다
- ktlintCheck, :feature:home:jvmTest, :shared:jvmTest, :androidApp:compileDebugKotlin 통과
- 참고한 Git-it-Server 저장소가 배포본(git-it.kr)보다 낡아 필드명이 어긋나 있었다
  live OpenAPI 응답 예시와 대조해 세 곳을 고친다
- 프로젝트 목록: nextProblemId -> nextSetId + nextQuestionId
  기존 이름으로는 항상 null이라 이어 풀 문제를 알 수 없었다
- 문제 북마크 응답: isBookmarked -> bookmarked
  기존 이름으로는 서버가 적용한 상태가 항상 false로 읽혔다
- 북마크 목록: 응답에 있는 setId를 도메인까지 전달한다
- ktlintCheck, 전 모듈 테스트 131개 통과
@KimSungBeen KimSungBeen self-assigned this Aug 17, 2026
@KimSungBeen KimSungBeen added this to the v1 개발 milestone Aug 17, 2026
- API 연동 과정에서 마이·홈·저장한 문제 화면의 표시 문구가 Kotlin 코드에
  하드코딩돼 있던 것을 각 모듈 strings.xml로 옮긴다
- 문구 해석은 Composable에서만 한다. Compose Resources의 getString은
  데스크톱에서 skiko 네이티브를 요구해 ViewModel에서 부르면 jvmTest가 깨진다
- 그래서 UiState는 완성된 문구 대신 값을 담는다
  MyProfile.position/careerLevel, MyStudyStat(type, count),
  SettingsUiState(position, careerLevel), HomeUiState.careerLevel,
  BookmarkedQuestion(projectName, setLabel, problemNumber)
- BookmarkFilter.label은 전체 필터일 때 null이고 화면이 고정 문구를 넣는다
- 개발 분야·수준 라벨은 toDisplayLabelResource() 한 곳에만 두어
  마이·설정·선택 화면이 같은 문구를 공유한다
- 구분자(" · "), 스타 수 k 표기, 문제 출처 라벨, 로그 메시지, 프리뷰 더미는
  번역 대상이 아니라 그대로 둔다
- ktlintCheck, :feature:my/home/bookmark:allTests, :shared:jvmTest,
  :androidApp:compileDebugKotlin, :desktopApp:compileKotlin 통과

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@KimSungBeen
KimSungBeen merged commit 1ba2048 into main Aug 17, 2026
1 check passed
@KimSungBeen
KimSungBeen deleted the feature/Task-219-api-integration branch August 17, 2026 08:30
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