Skip to content

Conversation

@hyerinhwang-sailin
Copy link
Collaborator

@hyerinhwang-sailin hyerinhwang-sailin commented Sep 21, 2025

Related issue 🛠

Work Description ✏️

작업 내용 요약

  • Feign 파라미터 포맷 수정으로 Platform 유저 조회 500 이슈 해결
  • Slack 로깅 중 발생하던 ClassCastException 제거(로깅 안전화)
  • 콕찌르기 응답의 userId 표기 오류 수정 및 에지케이스 하드닝

배경 / 현상

  • Platform 유저 조회 실패(Feign 500) : GET /api/v1/users 호출 시 Required request parameter 'userIds' ... is not present로 500 발생.
  • Slack 로깅 중 500(ClassCastException) : @AuthenticationPrincipal Long을 쓰는 컨트롤러에서, AOP가 principal을 User로 캐스팅하며 ClassCastException.
  • 콕찌르기 응답에서 userId가 “내 ID”로 표기 : 상대 프로필 DTO 구성 시 ID 세팅 오류.
  • 빈 리스트에서 get(0) 사용으로 NPE 위험 : "누가 나를 찔렀어요" 조회 경로 등 일부 스트림 처리 구간.
  • 플랫폼에만 존재하고 로컬 DB엔 없는 유저 찌르기 시 404 : 사전 검증/에러 메시지 정제 필요.
  • 에지케이스에서 500 가능성 : (1) 상호 친구 ID가 비어있을 때 외부 호출, (2) 추천할 친구가 없을 때 NPE, (3) 빈 IN 조건 조회, (4) 삭제 쿼리 트랜잭션 경계 등.

원인 분석

  1. userIds 쿼리 포맷 불일치
    서버 명세는 userIds=1,2,3 CSV 1개 키를 요구. 기존 코드는
    Map<String, Collection>로 userIds 키를 여러 번 넣어 실제로는 서버가 파라미터 미존재로 인식.
  2. SlackLoggerAspect의 고정 캐스팅
    전역적으로 @AuthenticationPrincipal Long을 사용하는데 AOP에서 (User) principal 캐스팅을 시도해 예외.
  3. 상대/나 ID 혼용
    PokeFacade#getFriendUserInfo()에서 PokedUserInfo.userId에 userId(나)를 넣고 있었음.
  4. 빈 리스트에 대한 안전장치 부족
    .get(0)로 첫 요소 접근, 빈 컬렉션에 대한 외부 호출, 빈 IN 쿼리 등.
  5. 플랫폼-only 유저
    로컬 User 미존재 케이스가 자연스럽게 NotFound로 떨어지지 않거나 메시지가 불명확.

변경 사항 (Fixes)

Platform 연동

  • GET 쿼리 파라미터 포맷 수정
    • PlatformService#createQueryParams(List) → Map<String, String> 반환으로 변경.
    • userIds를 1,2,3 CSV 단일 키로 구성.
    • 빈 리스트 요청 시 BadRequestException(ErrorCode.INVALID_PARAMETER)로 조기 차단.
  • 헤더 키 통일
    • X-Api-Key, X-Service-Name로 일관화(HTTP 헤더는 대소문자 무시지만 팀 컨벤션에 맞춤).
  • Null/Empty 응답 방어
    • PlatformUserInfoWrapper.data()가 null/empty면 BadRequestException(ErrorCode.PLATFORM_USER_NOT_EXISTS).
  • Internal POST 유저 조회 추가 + 자동 전환(길이 우회)
    • PlatformClient에 POST /api/v1/users 메서드 추가
    • 많은 수의 userIds로 요청할 때 414(URI Too Long) 회피를 위한 POST 대체 경로
    • 스마트 라우팅: CSV 길이가 임계값을 넘으면 자동으로 POST로 전환
      • 입력 ID 중복 제거 후 CSV 생성, 길이 임계치(URL_QUERY_LENGTH_THRESHOLD = 1200) 초과 시 POST로 자동 전환.
      • 임계치 이하이면 기존 GET(CSV) 사용.

바디 스펙: {"userIds":[1,2,3]}

Slack 로깅

  • Aspect 하드닝
    • resolveUserIdSafely() 추가: Long, User, UserDetails(username), String, Authentication#getName()까지 폭넓게 해석.
    • 전체를 try/catch로 감싸 로거 자체가 장애를 유발하지 않도록 처리.
    • 잘못 붙은 포인트컷(파라미터 1개 Exception 아님)인 경우 WARN 로그만 남기고. 패스.

콕찌르기 도메인

  • 상대 ID 세팅 버그 수정
    • PokeFacade#getFriendUserInfo(...)에서 PokedUserInfo.userId = friendUserId로 수정.
  • 빈 리스트 안전화 및 외부 호출 가드
    • getMostRecentPokeMeHistory, getAllPokeMeHistory, 우정도별 조회 등에서 get(0) 제거 → findFirst().orElse(null) + null 필터.
    • createMutualFriendNames(...): 상호친구 ID가 비어있으면 외부 API(platform) 호출 스킵하고 즉시 문구 생성.
    • getFriend(...): 추천할 친구 ID가 null이거나 로컬 미존재면 빈 리스트 반환.
    • PokeHistoryService#getAllLatestPokeHistoryIn(...): 빈 IN이면 Page.empty(pageable) 즉시 반환.
    • PokeHistoryService#handleUserWithdrawEvent(...): @transactional 추가해 삭제 쿼리의 트랜잭션 보장.
  • 에러 메시지 정제 및 사전 검증
    • 자기 자신 찌르기 차단: SELF_POKE_NOT_ALLOWED
    • 로컬 DB 미존재 유저 찌르기 차단: USER_NOT_FOUND (플랫폼-only 유저 온보딩 전까지 명확한 응답)

리팩토링/기타

  • 중복 정렬 제거
    • PokeHistoryService#getAllOfPokeBetween(...)에서 DB 정렬을 그대로 사용하도록 스트림 정렬 제거.

Trouble Shooting ⚽️

Related ScreenShot 📷

Uncompleted Tasks 😅

To Reviewers 📢

@hyerinhwang-sailin hyerinhwang-sailin self-assigned this Sep 21, 2025
@hyerinhwang-sailin hyerinhwang-sailin added the 🛠️ BugFix 버그 해결 label Sep 21, 2025
@hyerinhwang-sailin hyerinhwang-sailin linked an issue Sep 21, 2025 that may be closed by this pull request
1 task
@height
Copy link

height bot commented Sep 21, 2025

Link Height tasks by mentioning a task ID in the pull request title or commit messages, or description and comments with the keyword link (e.g. "Link T-123").

💡Tip: You can also use "Close T-X" to automatically close a task when the pull request is merged.

@hyerinhwang-sailin hyerinhwang-sailin merged commit 9288b18 into dev Sep 21, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 콕찌르기 이슈 해결

1 participant