Skip to content

feat(S15P11A705-200): 마이페이지 요약 조회 구현 - #128

Merged
cherry-go-round merged 4 commits into
devfrom
feat/S15P11A705-200-me-summary
Jul 31, 2026
Merged

feat(S15P11A705-200): 마이페이지 요약 조회 구현#128
cherry-go-round merged 4 commits into
devfrom
feat/S15P11A705-200-me-summary

Conversation

@cherry-go-round

Copy link
Copy Markdown
Contributor

요약

GET /api/core/v1/me/summary를 구현한다. 프론트의 프로필 화면이 요구한 두 기능(내 프로필, 팔로잉·팔로워 수)이 이 엔드포인트 하나로 해결된다 — 명세 §3.5가 계정 정보와 카운트 넷을 한 응답에 담아 뒀다.

명세를 구현과 대조해 보니 미구현이 둘뿐이었다. 이것과 GET /feed/collections/{id}/shelf(#85)이고 나머지는 전부 있었다.

Jira (필수)

관련 GitHub Issue (선택)

변경 사항

  • MeSummaryResponse · MemberSummaryService · MeController.summary()
  • 집계 메서드 4개 — RecordRepository.countByMemberId, CollectionRepository.countByMemberId, FollowRepository.countByFolloweeMemberId·countByFollowerMemberId
  • 기록 — BI-30, WORKLOG 1줄
  • 리팩터 — 통합 테스트 픽스처를 support/CoreApiFixtures로 올림(별도 커밋)

테스트 / 검증

  • ./gradlew clean check --no-daemon417개 통과, 실패 0, 오류 0
  • DB 변경 시 PostgreSQL 통합 테스트 (신규 8건 전부)
  • migration 변경 시 빈 DB 테스트 — 해당 없음(스키마 변경 없음)
  • API 계약 변경 시 문서 갱신 — 해당 없음(계약은 §3.5에 이미 있고 구현이 따라간 것)

RED — 7건 실패. 미인증 401만 이미 통과했다(anyRequest().authenticated()가 담당).

GREEN — 8건. 완료 조건 대응은 이렇다.

완료 조건 테스트
§3.5의 여섯 필드 returnsAccountInfoAndFourCounts
소프트 삭제된 record·collection 제외 softDeletedRecordsAndCollectionsAreExcluded
소프트 삭제된 follow 양쪽 제외 softDeletedFollowsAreExcluded
같은 작성자 여러 Collection → 팔로워 1 followerCountCountsTheFollowerOncePerOwner
memberId 미포함 doesNotExposeMemberId
미인증 401 unauthenticatedRequestIs401

추가로 데이터 없는 회원의 0 집계, 타인 데이터 미포함을 더 넣었다.

열려 있던 질문에 답이 나왔다 — @SQLRestriction은 count 쿼리에도 적용된다

MemberRepository.isActive의 javadoc이 S15P11A705-147부터 이 질문을 미결로 남겨 뒀다.

existsById가 아니라 findById를 쓰는 것은 기존 세 경로와 같은 조회를 유지하려는 것이다. 바꾸면 @SQLRestriction이 count 쿼리에도 적용되는지가 별개의 질문이 되고, 그것은 중복 제거인 이 변경의 범위가 아니다.

활성 기준 집계가 넷 필요해지며 처음 답이 필요해졌고, 파생 countBy...만으로 성립한다.

뮤테이션으로 확인했다. countByMemberId를 조건 없는 native 쿼리로 바꿨을 때:

@Query(value = "SELECT count(*) FROM core.record WHERE member_id = :memberId", nativeQuery = true)
마이페이지 요약 > 소프트 삭제된 Record·Collection은 카운트에서 빠진다  FAILED
8 tests completed, 1 failed

그 1건만 실패한다. 조건을 명시하려다 빠뜨리는 쪽이 오히려 위험하다는 것도 같은 실험이 보여 준다. 결론을 RecordRepository와 원래 질문을 남긴 MemberRepository 양쪽 javadoc에 적었다.

리뷰 포인트

① 카운트 쿼리를 넷으로 나눴다. 한 번의 조인으로 묶으면 카운트가 곱해진다 — Record 3건과 Collection 2건을 조인하면 6이다. count(DISTINCT ...)로 피할 수 있으나, 화면 진입당 1회 호출되는 경로에서 PK·FK 인덱스를 타는 count 넷이 그 복잡도를 살 이유가 되지 않는다고 봤다.

② 팔로워 수에 DISTINCT를 쓰지 않았다. 유니크가 (followee_member_id, follower_member_id) 활성 기준이라(V3__core_domain.sql:125) 한 사람이 그 작성자의 Collection을 여러 개 팔로우해도 행이 하나이고, 두 번째 시도는 409 DUPLICATE_FOLLOW로 거절된다. 즉 팔로우 단위가 Collection이 아니라 작성자다. 계약이 "팔로워 수"라고만 적어 단위가 드러나지 않으므로 그 성질을 테스트로 고정했다.

③ 소셜 계정이 없으면 IllegalStateException이다. 가입이 회원과 소셜 계정을 한 트랜잭션에서 만들어(SocialLoginService.signUp) 정상 상태에서는 없는 경우다. 조용히 빈 값을 내보내면 *"email은 항상 있다"*는 계약(§3.5)이 깨진 채 프론트로 나간다 — 프론트가 값 없음 대비를 하지 않기로 한 근거가 그 문장이다.

④ 리팩터를 같은 PR에 넣었다. 픽스처가 클래스마다 복사돼 있어 support/CoreApiFixtures로 올렸다(별도 커밋, 두 파일에서 −177줄). AiDerivedDataInvalidationTests는 같은 픽스처를 갖지만 AI 파트 소유 파일(S15P11A705-124)이라 건드리지 않았다 — 필요할 때 그쪽이 상속하면 된다.

미결 / 후속

  • 함께 요청된 "내 기록 조회"는 계약에 없다. 기록 장(§5)의 조회는 지도 마커·상세·장소별 셋뿐이고 목록 엔드포인트가 없다. 이번에는 불필요하다는 확인을 받아 범위에서 뺐고, 필요해지면 docs 개정이 선행이다(CLAUDE.md 9번).
  • 응답에 provider가 하나뿐이다. 계정당 소셜 계정이 하나인 것은 계정 연결 흐름이 없기 때문이고 그 전제가 타입에는 없다. findByMemberId가 목록을 반환하므로 첫 행을 쓴다 — 연결 기능이 생기면 여기가 먼저 깨진다.
  • 집계가 실시간 count다. 캐시·비정규화가 없어 회원 데이터가 커지면 비용도 커진다. 화면 진입당 1회라 지금 규모에서는 문제가 아니다.

@cherry-go-round cherry-go-round linked an issue Jul 31, 2026 that may be closed by this pull request
12 tasks
@minyongP

Copy link
Copy Markdown
Contributor

Claude Code 자동 리뷰입니다. 판정은 항상 comment이며, 승인·변경 요청은 @minyongP가 직접 남깁니다.

필수 변경 1건

  • src/test/java/com/pinlog/pinlogback/domain/member/MeSummaryApiTests.java:174 — 응답 전문에 memberId 문자열이 없는지 보는 단언인데, 성공 envelope는 success/data뿐이라(ApiResponse) 본문에 남는 숫자가 카운트 넷의 0과 이메일 리터럴의 6밖에 없습니다. 시퀀스가 이 테스트에 memberId=6을 주는 회차에서는 실증하려는 것과 무관하게 실패하는데, 공유 컨테이너라 앞선 클래스가 시퀀스를 얼마나 밀었는지에 달려 있어 회차마다 갈립니다. 이메일에서 숫자를 빼거나(summary-six@kakao.com) 단언을 /data의 키 집합에 걸면 의도는 그대로 두고 우연 일치만 없앨 수 있습니다.

@SQLRestriction이 count에도 적용되는지를 주장이 아니라 뮤테이션으로 확인하고, 그 답을 원래 질문이 남아 있던 MemberRepository javadoc까지 되돌려 적은 점이 좋았습니다.

nit 수준 제안은 내지 않습니다.

cherry-go-round added a commit that referenced this pull request Jul 31, 2026
#128 리뷰 반영(@minyongP). 회차마다 갈리는 flaky 테스트였다.

doesNotExposeMemberId가 본문 전문에서 id 문자열을 찾는데, 픽스처 이메일이
summary6@kakao.com이라 본문에 6이 들어 있었다. 성공 envelope는 success/data뿐이고 나머지
수는 카운트 넷의 0이므로, 시퀀스가 이 테스트에 memberId=6을 주는 회차에서는 실증하려는 것과
무관하게 실패한다. 공유 컨테이너라 앞선 클래스가 시퀀스를 얼마나 밀었는지에 달려 회차마다
갈린다.

기전을 재현해 확인했다. 이메일을 그대로 두고 단언을 doesNotContain("6")으로 바꾸면 그 1건이
실패한다.

이메일에서 숫자를 뺐다(summary-six@kakao.com). 남는 수는 카운트 넷의 0뿐이고 id는 1부터라
우연 일치가 성립하지 않는다.

단언도 강화했다. /data의 필드 집합을 그대로 고정하므로 memberId가 다른 이름으로 새는 경우까지
걸린다 — 원래 단언은 그 이름만 봤다.

	assertThat(...at("/data").propertyNames())
		.containsExactlyInAnyOrder("provider", "email",
			"recordCount", "collectionCount", "followerCount", "followingCount");

이유를 테스트 javadoc에 남겼다. 다음에 픽스처 이메일에 숫자를 넣으면 같은 함정이 돌아온다.

clean check 417개 통과, 실패 0

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cherry-go-round

Copy link
Copy Markdown
Contributor Author

리뷰 감사합니다. 맞는 지적이고 실제 flaky였습니다. b48fd96으로 고쳤습니다.

기전을 재현해 확인했습니다

이메일은 그대로 두고 단언만 doesNotContain("6")으로 바꿔 memberId=6인 회차를 가장했습니다.

마이페이지 요약 > memberId를 반환하지 않는다  FAILED
8 tests completed, 1 failed

말씀하신 그대로입니다 — 성공 envelope는 success/data뿐이고 나머지 수는 카운트 넷의 0이라, 본문에 남는 유일한 다른 숫자가 **픽스처 이메일의 6**이었습니다.

고친 방식 — 제안하신 둘을 함께 했습니다

① 이메일에서 숫자를 뺐습니다(summary-six@kakao.com). 남는 수는 0뿐이고 id는 1부터라 우연 일치가 성립하지 않습니다.

② 단언을 필드 집합으로 바꿨습니다.

assertThat(jsonMapper.readTree(body).at("/data").propertyNames())
    .containsExactlyInAnyOrder("provider", "email",
        "recordCount", "collectionCount", "followerCount", "followingCount");

원래 단언(has("memberId"))은 그 이름만 봤습니다. 집합으로 고정하면 memberIdid·userId 같은 다른 이름으로 새는 경우까지 걸립니다 — 지적의 부수 효과로 단언이 더 강해졌습니다.

본문 전문 검사는 남겼습니다. 숫자를 뺀 뒤에는 안전하고, 그것이 잡는 것(/data 밖으로 새는 경우)이 집합 단언과 다릅니다.

함정이 돌아오지 않게 이유를 테스트 javadoc에 적었습니다 — 다음에 누가 픽스처 이메일에 숫자를 넣으면 같은 문제가 재발하고, 그때 이 주석이 원인을 가리킵니다.

검증

./gradlew clean check --no-daemon417개 통과, 실패 0.

@minyongP

Copy link
Copy Markdown
Contributor

Claude Code 자동 리뷰입니다. 판정은 항상 comment이며, 승인·변경 요청은 @minyongP가 직접 남깁니다.

재리뷰입니다 — 4b2dd4e..b48fd96 구간의 변경을 봤습니다.

필수 변경은 없습니다.

이전 지적(MeSummaryApiTests.java:174의 우연 일치)이 이번 커밋에서 반영됐습니다 — 이메일에서 숫자를 빼고 /data의 필드 집합을 containsExactlyInAnyOrder로 고정해, memberId가 다른 이름으로 새는 경우까지 잡습니다. 재발 방지 근거를 javadoc으로 남긴 점이 좋았습니다.

@cherry-go-round
cherry-go-round force-pushed the feat/S15P11A705-200-me-summary branch from b48fd96 to 7ae57f5 Compare July 31, 2026 04:43
cherry-go-round added a commit that referenced this pull request Jul 31, 2026
#128 리뷰 반영(@minyongP). 회차마다 갈리는 flaky 테스트였다.

doesNotExposeMemberId가 본문 전문에서 id 문자열을 찾는데, 픽스처 이메일이
summary6@kakao.com이라 본문에 6이 들어 있었다. 성공 envelope는 success/data뿐이고 나머지
수는 카운트 넷의 0이므로, 시퀀스가 이 테스트에 memberId=6을 주는 회차에서는 실증하려는 것과
무관하게 실패한다. 공유 컨테이너라 앞선 클래스가 시퀀스를 얼마나 밀었는지에 달려 회차마다
갈린다.

기전을 재현해 확인했다. 이메일을 그대로 두고 단언을 doesNotContain("6")으로 바꾸면 그 1건이
실패한다.

이메일에서 숫자를 뺐다(summary-six@kakao.com). 남는 수는 카운트 넷의 0뿐이고 id는 1부터라
우연 일치가 성립하지 않는다.

단언도 강화했다. /data의 필드 집합을 그대로 고정하므로 memberId가 다른 이름으로 새는 경우까지
걸린다 — 원래 단언은 그 이름만 봤다.

	assertThat(...at("/data").propertyNames())
		.containsExactlyInAnyOrder("provider", "email",
			"recordCount", "collectionCount", "followerCount", "followingCount");

이유를 테스트 javadoc에 남겼다. 다음에 픽스처 이메일에 숫자를 넣으면 같은 함정이 돌아온다.

clean check 417개 통과, 실패 0

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cherry-go-round and others added 3 commits July 31, 2026 13:44
GET /v1/me/summary. 계정 정보(provider·email)와 활성 기준 카운트 넷을 한 응답에 담는다
(08 §3.5).

명세를 구현과 대조해 보니 미구현이 둘뿐이었다 — 이것과 /feed/collections/{id}/shelf(#85).
프론트가 요구한 두 기능(내 프로필, 팔로잉·팔로워 수)이 이 엔드포인트 하나로 해결된다.

함께 요청된 "내 기록 조회"는 계약에 없어 범위에서 뺐다. 기록 장(§5)의 조회는 지도 마커·
상세·장소별 셋뿐이고 목록 엔드포인트가 없다 — 필요해지면 docs 개정이 선행이다.

RED 7건(미인증 401만 이미 통과) → GREEN 8건

- MeSummaryResponse, MemberSummaryService
- 집계 메서드 4개: record·collection 각 countByMemberId, follow 양방향 count
- MeController에 @GetMapping("/summary")

열려 있던 질문에 답이 나왔다 — @SQLRestriction은 count 쿼리에도 적용된다

MemberRepository.isActive의 javadoc이 "바꾸면 @SQLRestriction이 count 쿼리에도 적용되는지가
별개의 질문이 되고, 그것은 이 변경의 범위가 아니다(S15P11A705-147)"로 남겨 뒀던 것이다.
활성 기준 집계가 넷 필요해지며 처음 답이 필요해졌고, 파생 countBy...만으로 성립한다.

뮤테이션으로 확인했다. countByMemberId를 조건 없는 native 쿼리로 바꾸면 소프트 삭제 제외
테스트 1건만 실패한다. 조건을 명시하려다 빠뜨리는 쪽이 오히려 위험하다는 것도 같은 실험이
보여 준다. 결론을 RecordRepository와 MemberRepository 양쪽 javadoc에 적었다.

설계 판단 셋

- 카운트를 넷으로 나눴다. 조인으로 묶으면 카운트가 곱해진다(Record 3 × Collection 2 = 6).
  count(DISTINCT ...)로 피할 수 있으나 화면 진입당 1회 호출이라 그 복잡도를 살 이유가 없다
- 팔로워 수에 DISTINCT가 불필요하다. 유니크가 (followee, follower) 활성 기준이라 한 사람이
  여러 Collection을 팔로우해도 행이 하나이고 두 번째 시도는 409다. 팔로우 단위가 Collection이
  아니라 작성자라는 뜻이고, 계약이 "팔로워 수"라고만 적어 단위가 드러나지 않으므로 테스트로
  고정했다
- 소셜 계정이 없으면 IllegalStateException. 조용히 빈 값을 내보내면 "email은 항상 있다"는
  계약이 깨진 채 프론트로 나간다

드러난 것

- 픽스처 계산을 틀렸고 테스트가 잡았다. collectionCount를 3으로 기대했는데 2였다 — 세 번째는
  남의 소유다. 구현이 아니라 기대값이 틀린 경우였고 픽스처에 소유자를 주석으로 명시했다
- 소프트 삭제를 삭제 API가 아니라 JdbcTemplate으로 만들었다. 삭제 API는 연쇄 삭제까지 해서
  세려는 대상이 함께 사라지고, 그러면 검증 대상이 "카운트가 활성만 세는가"에서 "연쇄 삭제가
  무엇을 지웠는가"로 옮겨간다

clean check 417개 통과, 실패 0

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
createRecord·createCollection·follow 같은 픽스처가 클래스마다 복사돼 있었다.
support/CoreApiFixtures로 올리고 member 도메인 두 테스트가 상속하게 했다 — 두 파일에서
177줄이 사라졌다.

support에 둔 이유는 도메인을 가로지르기 때문이다. Record·Collection·Follow를 함께 쓰는
픽스처라 어느 한 도메인 패키지에 두면 그 도메인이 아닌 테스트가 남의 패키지를 참조하게 된다.
한 도메인만 쓰는 픽스처는 계속 그 도메인 안에 둔다 — FeedFixtures가 그 경우이고, 이 클래스는
그 구조(추상 클래스 + IntegrationContainerSupport 상속 + protected 필드)를 그대로 따랐다.

AiDerivedDataInvalidationTests는 옮기지 않았다. 같은 픽스처가 그쪽에도 있지만 AI 파트 소유
파일(S15P11A705-124)이라 이 PR에서 건드리지 않는다. 필요할 때 그쪽이 상속하면 된다.

MemberWithdrawalApiTests에는 givenSocialAccount 3인자 오버로드를 남겨 공용의 4인자 버전에
위임한다. 그 클래스는 provider를 가리지 않아 Google로 고정되어 있고, 호출부 11곳을 건드리지
않으려는 선택이다.

옮기다 두 번 과하게 지웠다 — 남은 테스트가 쓰는 Member와 Collectors import를 함께 지워
컴파일이 깨졌고 되돌렸다. 헬퍼를 지울 때 그 파일의 다른 테스트가 같은 타입을 쓰는지 함께
봐야 한다.

clean check 417개 통과, 실패 0 — 리팩터 전후 같은 수치다

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#128 리뷰 반영(@minyongP). 회차마다 갈리는 flaky 테스트였다.

doesNotExposeMemberId가 본문 전문에서 id 문자열을 찾는데, 픽스처 이메일이
summary6@kakao.com이라 본문에 6이 들어 있었다. 성공 envelope는 success/data뿐이고 나머지
수는 카운트 넷의 0이므로, 시퀀스가 이 테스트에 memberId=6을 주는 회차에서는 실증하려는 것과
무관하게 실패한다. 공유 컨테이너라 앞선 클래스가 시퀀스를 얼마나 밀었는지에 달려 회차마다
갈린다.

기전을 재현해 확인했다. 이메일을 그대로 두고 단언을 doesNotContain("6")으로 바꾸면 그 1건이
실패한다.

이메일에서 숫자를 뺐다(summary-six@kakao.com). 남는 수는 카운트 넷의 0뿐이고 id는 1부터라
우연 일치가 성립하지 않는다.

단언도 강화했다. /data의 필드 집합을 그대로 고정하므로 memberId가 다른 이름으로 새는 경우까지
걸린다 — 원래 단언은 그 이름만 봤다.

	assertThat(...at("/data").propertyNames())
		.containsExactlyInAnyOrder("provider", "email",
			"recordCount", "collectionCount", "followerCount", "followingCount");

이유를 테스트 javadoc에 남겼다. 다음에 픽스처 이메일에 숫자를 넣으면 같은 함정이 돌아온다.

clean check 417개 통과, 실패 0

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cherry-go-round
cherry-go-round force-pushed the feat/S15P11A705-200-me-summary branch from 7ae57f5 to f706029 Compare July 31, 2026 04:46
@cherry-go-round
cherry-go-round merged commit e9bb1ab into dev Jul 31, 2026
2 checks passed
@cherry-go-round
cherry-go-round deleted the feat/S15P11A705-200-me-summary branch July 31, 2026 04:55
@cherry-go-round cherry-go-round self-assigned this Jul 31, 2026
minyongP added a commit that referenced this pull request Aug 1, 2026
리베이스로 들어온 GET /v1/me/summary(#128)를 시나리오에 더하고, 그 검사가 드러낸
하네스 한계를 고쳤다 — SQL로 회원 행만 만들면 '소셜 계정 없는 활성 회원'이라는
API로 도달 불가능한 상태가 되고 summarize가 계약대로 500을 던진다. setup이 소셜
계정까지 만들어 실제 가입 결과와 같은 모양을 갖춘다. 전체 파이프라인 138/138, exit 0.
minyongP added a commit that referenced this pull request Aug 1, 2026
* test(S15P11A705-192): 검증용 RS256 토큰 발급기를 추가한다

* fix(S15P11A705-192): member_id 검증을 추가해 JSON 깨짐을 방지한다

* fix(S15P11A705-192): 출력 블록 전에 member_id를 검증해 JSON 손상을 방지한다

* test(S15P11A705-192): 전용 테스트 회원 생성·정리 SQL을 추가한다

* fix(S15P11A705-192): setup 출력을 한 줄로 고정하고 social_account 정리를 더한다

* test(S15P11A705-192): k6 공용 라이브러리(설정·HTTP·기록기)를 추가한다

* fix(S15P11A705-192): CSRF 토큰을 캐시하지 않고 항아리에서 매번 읽는다

* test(S15P11A705-192): 읽기 9개와 인증·소유권 부정 계약 시나리오를 추가한다

* fix(S15P11A705-192): 골든 장소 id를 실제 시드 값으로 맞춘다

* fix(S15P11A705-192): size 상한 검사가 깨진 엔벨로프에서도 소리 내게 한다

* test(S15P11A705-192): Record·Context 쓰기 시나리오와 BD-07·BD-12 계약 검사를 추가한다

* test(S15P11A705-192): Collection 쓰기와 BD-11 삭제 확인 흐름 검사를 추가한다

* test(S15P11A705-192): Follow·Feed·Search·Auth 시나리오로 27개 전수를 채운다

* test(S15P11A705-192): k6가 만진 id를 지목 검증하는 SQL을 추가한다

* test(S15P11A705-192): DB 전역 불변식 검증 SQL을 추가한다

* test(S15P11A705-192): 전 과정 오케스트레이터와 하네스 문서를 추가한다

* fix(S15P11A705-192): 삭제된 Collection을 BD-20 지목 검증 대상에서 뺀다

run.sh로 처음 전 과정을 실제로 돌려보니 k6 시나리오가 force 연쇄로 Collection을
지운 뒤 그 record_count를 지목 검증하면서 매번 거짓 위반이 났다 — 삭제된 행은
record_count가 더 갱신되지 않으므로 활성 연결 수(0)와 항상 어긋난다.

* fix(S15P11A705-192): 정리 트랩을 앞당기고 표식 추출을 JSON 디코더로 바꾼다

* test(S15P11A705-192): 회원 탈퇴 엔드포인트를 더해 28개 전수를 맞춘다

* docs(S15P11A705-192): 종단 검증 하네스 구현 보고서와 시드 원인 삼분류를 남긴다

* fix(S15P11A705-192): FAIL 단언·미호출·스윕 오류·골든 훼손이 종료 코드에 반영되게 한다

* test(S15P11A705-192): dev 전진분 me/summary를 더해 29개 전수를 맞춘다

리베이스로 들어온 GET /v1/me/summary(#128)를 시나리오에 더하고, 그 검사가 드러낸
하네스 한계를 고쳤다 — SQL로 회원 행만 만들면 '소셜 계정 없는 활성 회원'이라는
API로 도달 불가능한 상태가 되고 summarize가 계약대로 500을 던진다. setup이 소셜
계정까지 만들어 실제 가입 결과와 같은 모양을 갖춘다. 전체 파이프라인 138/138, exit 0.

* docs(S15P11A705-192): dev가 선점한 BI-32를 피해 BI-33으로 재번호한다
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.

feat(S15P11A705-200): 마이페이지 요약 조회 API 구현

2 participants