코드 리뷰 → 지라 티켓 초안

신규 백엔드 시니어 코드 리뷰 공유 기반 · 총 5건 (티켓 5는 app/admin 분담)

P1 보안 P2 버그 P3 개선 부채/리팩터 전제
📋 발행 순서
1 버그 2 토큰 3 Response 4 안전망 5 리팩터
1·2·3 은 독립 → 아무 순서로 발행 OK.
4(테스트 안전망) 를 5 보다 먼저 발행 — 5 리팩터는 4 없이는 착수 불가라, 지라에서 티켓 5 → "is blocked by" → 티켓 4 링크 연결.
티켓 5 내부 작업 순서: app setPriceData → admin MemberService.
티켓 1

[버그] 엑셀 업로드 비동기 — 지정 스레드풀 미사용

P2

[요청 내용] 필수

채널톡 엑셀 업로드(POST /api/channeltalk/excel/upload)용으로 excelTaskExecutor 스레드풀(core 5 / max 10 / queue 500)을 설정해 두었으나 실제로는 사용되지 않음. ChannelTalkFacadeService.uploadExcel()에서 @Async 스레드가 한 일은 supplyAsync 호출로 future를 만들고 즉시 반납하는 것뿐이며, supplyAsync에 executor를 넘기지 않아 실제 처리는 JVM 공용 ForkJoinPool.commonPool()에서 실행됨. 설정한 풀이 죽어 있는 상태.

[처리 기준] 필수

  • 실제 처리가 excelTaskExecutor에서 실행되도록 통일. A/B 중 택1
    • A) @Async("excelTaskExecutor")만 사용, 본문에서 직접 처리 후 completedFuture 반환
    • B) @Async 제거, supplyAsync(task, excelTaskExecutor)로 풀 명시
  • 반환 타입 제네릭 명시(CompletableFuture<String>)
  • 동시 다건 시 지정 풀에서 실행되는지 로그(스레드명 ExcelUpload-)로 확인

[기대효과] 선택

엑셀 업로드가 commonPool을 잠식해 JVM 전역 병렬 작업을 느리게 만드는 문제 제거. 큐/스레드 상한이 실제로 적용됨.

[논의사항] 옵션

A안(코드 단순) 권장. 실패 시 재시도 정책도 이 참에 정리할지 논의.

티켓 2

[보안] access 토큰 만료 6개월 → 단축 + refresh 도입

P1

[요청 내용] 필수

현재 로그인(access) 토큰 만료가 발급일로부터 6개월로 설정되어 있음. 토큰 탈취 시 최대 6개월간 무효화 없이 재사용 가능. 카드/PII 등 민감정보를 다루는 서비스 특성상 노출 리스크가 큼.

[처리 기준] 필수

  • access 토큰 만료를 단기(예: 30~60분)로 단축
  • refresh 토큰 발급·회전(rotation) 흐름 도입 → access 만료 시 재로그인 없이 갱신
  • refresh 없이 만료만 줄이면 사장님 앱에서 잦은 재로그인 발생 → 반드시 refresh와 세트로 처리
  • 만료·갱신 시나리오(정상 갱신 / refresh 만료 / 강제 로그아웃) 동작 확인

[기대효과] 선택

탈취 토큰의 유효 창을 6개월 → 수십 분으로 축소. 로그인 UX 회귀 없이 세션 보안 강화.

[논의사항] 옵션

  • 문서상 "6개월 = access"로 파악됨. 실제 발급부 코드에서 access/refresh 중 어느 값이 6개월인지 1차 확인 필요
  • refresh 저장 위치(모바일 secure storage / 서버 화이트리스트) 및 로그아웃 시 무효화 정책 결정

[산출물] 옵션

토큰 만료·갱신 정책 정리, 발급부 코드 변경분

티켓 3

[개선] Response<?> 와일드카드 → 구체 응답 타입 명시

P3

[요청 내용] 필수

일부 컨트롤러 응답 타입이 Response<?> 와일드카드로 되어 있어(예: GET /api/point/main) Swagger 문서에서 data가 비어 보임. 프론트가 응답 구조를 코드를 직접 열어봐야 알 수 있어 협업 비용 발생.

[처리 기준] 필수

  • 전면 일괄 교체가 아니라 2단계로 진행
    • 신규/수정 API는 구체 타입(Response<List<GradeResponse>> 등) 명시를 PR 리뷰 룰로 합의
    • 현재 프론트가 실제로 막혀 있는 엔드포인트를 우선 조사·수정
  • 수정 엔드포인트는 Swagger에서 data 필드가 펼쳐지는지 확인

[기대효과] 선택

프론트가 API 호출 전에 응답 구조 파악 가능 → 코드 열람/문의 감소.

[논의사항] 옵션

와일드카드 사용 엔드포인트 전수 목록화 후 우선순위 산정. 79개 전면 교체는 지양.

티켓 4

[테스트] 실 DB 기반 테스트 컨벤션 + 리팩터 대상 안전망

티켓 5 전제
✅ 리팩터 트랙에서 먼저 발행 · 티켓 5를 block

[요청 내용] 필수

현재 테스트에 세 패턴이 관찰됨: (1) 저장 후 로직 없이 바로 조회하는 트리비얼 테스트, (2) 서비스 내부 식을 테스트에 복붙해 로직이 두 곳(서비스+테스트 복제본)에 존재, (3) 서비스 테스트에서 레파지토리를 mock/stub 처리해 여러 레파지토리가 엮인 실제 케이스를 놓침. 이 상태에서는 회귀를 못 잡아 God class 리팩터(티켓 5)의 안전망 역할을 못 함.

[처리 기준] 필수

  • 개별 "테스트 전부 고치기"가 아님 → 컨벤션 합의 + PR 리뷰 룰로 처리
    • 서비스 로직은 테스트에 복붙하지 않고, 실제 로직(헬퍼/클래스)을 호출해 검증
    • 서비스 테스트는 stub 대신 @SpringBootTest + @Transactional(롤백)로 실 insert 후 호출
    • JPA 쿼리 메서드(findBy...) 검증 테스트는 유지 OK
  • 선행 작업: 티켓 5 대상 모듈(setPriceData / modifyMemberInformation)에 한해 실 DB 기반 characterization test 우선 확보

[기대효과] 선택

여러 레파지토리 조합 케이스를 잡는 테스트 확보 → 리팩터 시 회귀 조기 발견. 로직 이중 관리 제거.

[논의사항] 옵션

  • 실 DB 기반 테스트의 CI 실행 시간/전용 DB 준비 방식 결정 필요
  • 트리비얼 getter/생성자 테스트는 신규 작성 지양으로 합의할지
티켓 5

[리팩터] God class 분해 (1개 티켓 · 처리기준을 app/admin으로 분담)

부채

전 구간 백엔드 작업. 담당은 처리 기준 안에서 app-api / admin-api로 갈림.

🔒 is blocked by 티켓 4 (테스트 안전망 먼저)

[요청 내용] 필수

핵심 서비스 클래스가 한 메서드/한 클래스에 너무 많은 책임을 담고 있어 변경·리뷰·테스트가 어려움. 방향은 "서비스 = 동작 단위 / 헬퍼 = 기능 단위"로 분해. 대상은 app-api OrderService.setPriceData()(결제 금액 산출)와 admin-api MemberService(79 메서드·46 의존성, modifyMemberInformation() 154줄). 회귀 위험이 크므로 각 파트는 테스트 안전망(티켓 4) 확보 후 착수.

[처리 기준] 필수

app-apiOrderService.setPriceData() 분해 · 담당: app 백엔드

  • 선행(필수): characterization test 확보(쿠폰 3타입 × 면세 유무 × 프랜차이즈 유무 조합) — 안전망 없이 코드 이동 금지
  • 기능 단위 분리: 쿠폰 검증 / 면세 할인 배분(CART·SELLER·PRODUCT) / 마진·단가 계산 / 최소주문금액 검증
  • 분해 전후 동일 입력 → 동일 금액(1원도 차이 없음) 회귀 검증
  • 범위는 "구조 분리"로 한정 — 면세 CART 잔여 배정 등 로직 개선은 별도 티켓

admin-apiMemberService 분해 · 담당: admin 백엔드

  • 선행: modifyMemberInformation 동작 보존 테스트 확보(할인/마진/프랜차이즈 = 돈 분기 포함)
  • 서비스=동작 / 헬퍼=기능으로 분해 (예: ModifyMemberInfoService + MemberPasswordHelper / RecommenderHelper / MemberDiscountHelper / FranchiseMappingHelper / MinOrderAmountHelper / MemberInfoSlackHelper)
  • 흩어진 회원 조회+예외를 MemberSearchHelper.getOrThrow()로 통일(예외 타입·메시지 표준화)
  • modifyMemberInformation 한 흐름부터 파일럿 후 확장(전체 일괄 분해 지양)

[논의사항] 옵션

  • 착수 순서: setPriceData(app, 돈 사고 리스크) → MemberService(admin, 구조 부채)
  • 예외 메시지 통일 시 기존 응답이 API 계약(프론트 의존)에 노출되는지 확인 — 영향 있으면 별도 항목으로 분리