Skip to content

T-18 트랙 멤버 배정 - #72

Open
ff1451 wants to merge 1 commit into
feat/t17-image-uploadfrom
feat/t18-track-members
Open

T-18 트랙 멤버 배정#72
ff1451 wants to merge 1 commit into
feat/t17-image-uploadfrom
feat/t18-track-members

Conversation

@ff1451

@ff1451 ff1451 commented Aug 20, 2026

Copy link
Copy Markdown

요약

  • V10__add_member_profile_image_url.sql: member.profile_image_url 컬럼 추가. 홈페이지 "함께 할 멤버들"에 필요하지만 현재 스키마에 없던 컬럼. 컬럼과 읽기만 추가하고 쓰기 API는 만들지 않는다(INV-13, ADR-012) — Member 엔티티에 getter만 노출, setter/빌더 파라미터 없음.
  • 트랙 멤버 배정 API(/v1/admin/track-pages/{id}/members): POST(배정) / DELETE /{memberId}(해제) / PATCH /{memberId}/visibility(숨김) / PATCH /order(순서). study-points/tech-stacks의 전체 교체 패턴과 다르게, 스펙이 명시한 개별 CRUD를 그대로 따랐다 — 대상이 3~5개로 고정되지 않고 트랙마다 수십 명일 수 있어서다.
  • 공개 트랙 상세(GET /v1/tracks/{slug})에 members 필드를 추가했다. 숨김(is_visible=false)과 status != ACTIVE인 부원은 제외한다(INV-11).

설계 메모

  • INV-8(같은 트랙에 같은 부원 중복 배정 금지)은 DB unique(track_page_id, member_id)에 더해 애플리케이션에서도 배정 전에 검사해 409로 응답한다. 같은 요청의 memberIds 안에 중복이 있는 경우도 같은 예외로 막는다(그냥 두면 DB 제약 위반으로 500이 났을 것).
  • 명부는 포트 추상화 없이 MemberRepository를 직접 조회한다(ADR-012 — 명부가 이미 구현되어 외부 일정 의존이 해소됨).
  • 공개 조회는 홈페이지 빌드가 매번 호출하는 경로라 CurriculumQueryService와 같은 이유로 N+1을 피한다: 배정 목록 1쿼리 + 부원 IN절 배치 조회 1쿼리.
  • 관리자 배정 목록(GET .../members)은 저트래픽 편집 화면이라 부원 조회의 N+1을 감수한다(T-11 관리자 커리큘럼 트리와 같은 이유).

검증

  • 로컬 Postgres에 V10 적용 후 부팅 성공(Flyway validate, Hibernate 스키마 검증 통과) — 로그 확인함.
  • ./gradlew test 전체 통과, 3회 연속.
  • INV-8(중복 배정 409), 배정/해제/순서변경/숨김전환, 공개 상세의 숨김·비활성 부원 제외 — 통합 테스트로 커버. INV-13(명부 필드 쓰기 엔드포인트 없음)은 구조적으로 보장된다(그런 컨트롤러 메서드 자체가 없음).

남은 항목

  • T-19(기술스택 아이콘 S3 업로드)부터는 T-17의 이미지 API를 실제로 쓴다.
  • 시드 데이터(T-20)에서 이 API로 실제 부원을 배정하게 된다.

Refs #30 (프로젝트), 브랜치는 feat/t17-image-upload(#71) 위에 스택 — T-14~T-17까지 포함된 상태입니다.

머지하지 않습니다. 부원 리뷰 후 직접 머지 예정입니다.

- member.profile_image_url 컬럼 추가(V10) — 홈페이지 "함께 할 멤버들"에 필요하지만
  현재 스키마에 없던 컬럼. 컬럼과 읽기만 추가하고 쓰기 API는 만들지 않는다(INV-13,
  ADR-012) — Member 엔티티에 setter 없이 getter만 노출.
- 트랙 멤버 배정 API: POST(배정)/DELETE(해제)/PATCH .../visibility(숨김)/PATCH
  .../order(순서) — study-points/tech-stacks의 전체 교체 패턴과 달리 스펙이 명시한
  개별 CRUD를 그대로 따랐다(대상이 3~5개로 고정되지 않고 트랙마다 수십 명일 수 있어서).
- INV-8(같은 트랙에 같은 부원 중복 배정 금지)은 DB unique 제약(uk_track_page_member)
  더해 애플리케이션에서도 배정 전에 검사해 깔끔한 409로 응답한다. 같은 요청 안에
  memberIds가 중복된 경우도 같은 예외로 막는다.
- 명부는 포트 추상화 없이 MemberRepository를 직접 조회한다(ADR-012, 외부 일정 의존
  해소됨).
- 공개 트랙 상세(GET /v1/tracks/{slug})에 members 필드를 추가했다 — 숨김(is_visible=false)
  과 status != ACTIVE인 부원은 제외한다(INV-11). CurriculumQueryService와 같은 이유로
  N+1을 피한다: 배정 목록 1쿼리 + 부원 IN절 배치 조회 1쿼리.
- 관리자 배정 목록(GET .../members)은 저트래픽 편집 화면이라 부원 조회의 N+1을
  감수한다(T-11 관리자 커리큘럼 트리와 같은 이유).

검증: 로컬 Postgres에 V10 적용 후 부팅 성공(Flyway validate, Hibernate 스키마 검증
통과). ./gradlew test 전체 통과, 3회 연속.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e19bb744-a639-4b55-ac4e-b76532245358

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ff1451

ff1451 commented Aug 20, 2026

Copy link
Copy Markdown
Author

Refs #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.

1 participant