기존에 @RequestHeader("X-User-Id")로 userId를 받던 방식을 공통 모듈 0.0.4 업데이트로 AuthContext로 교체했다.
1. 기존 방식의 문제
// 기존 - 모든 API마다 헤더 파라미터 선언
@GetMapping("/{paymentId}")
public ResponseEntity<ApiResponse<PaymentResponse>> getPayment(
@PathVariable UUID paymentId,
@RequestHeader("X-User-Id") UUID userId) { // 매번 선언해야 함
모든 API마다 @RequestHeader("X-User-Id") UUID userId를 선언해야 했다. 파라미터가 늘어나고 코드가 지저분해졌다.
2. common 0.0.4 - AuthContext
공통 모듈 0.0.4에 AuthContext가 추가됐다.
import com.firstticket.common.web.AuthContext;
UUID userId = AuthContext.getUserId(); // X-User-Id → UUID
String role = AuthContext.getRole(); // X-User-Role → String
Gateway가 JWT에서 추출한 X-User-Id, X-User-Role 헤더를 정적 메서드로 가져올 수 있다.
컨트롤러 파라미터 선언 없이 필요한 시점에 어디서든 호출 가능하다.
3. PaymentController 교체
// 변경 후 - 파라미터 제거, 필요한 시점에 호출
@GetMapping("/{paymentId}")
public ResponseEntity<ApiResponse<PaymentResponse>> getPayment(
@PathVariable UUID paymentId) {
UUID userId = AuthContext.getUserId(); // 헤더에서 자동 추출
...
}
@GetMapping("/me")
public ResponseEntity<ApiResponse<List<PaymentResponse>>> getMyPayments() {
UUID userId = AuthContext.getUserId();
...
}
@PostMapping("/{paymentId}/refund")
public ResponseEntity<ApiResponse<PaymentResponse>> refundPayment(
@PathVariable UUID paymentId,
@RequestBody @Valid PaymentRefundRequest request) {
UUID userId = AuthContext.getUserId();
...
}
파라미터가 깔끔해졌다.
4. AuthContext를 각 메서드마다 호출하는 이유
처음에는 클래스 레벨에서 한 번만 뽑아두면 되지 않냐고 생각했다.
// 이렇게 하면 안 됨
private final UUID userId = AuthContext.getUserId(); // ❌
AuthContext.getUserId()는 HTTP 요청 스레드에서 헤더를 읽어오는 거라 요청마다 다른 값이 나온다. 클래스 레벨에서 한 번만 뽑아두면 첫 번째 요청의 userId가 고정되어버린다.
그래서 각 메서드 실행 시점에 호출해야 한다.
5. 코드래빗 리뷰 - Infrastructure 레이어 분리
코드래빗이 AuthContext를 Controller에서 직접 호출하지 말고 Infrastructure 레이어에서 래핑해서 사용하라고 지적했다.
// Infrastructure 레이어에서 래핑
@Component
public class AuthContextAdapter {
public UUID getCurrentUserId() {
return AuthContext.getUserId();
}
public String getCurrentUserRole() {
return AuthContext.getRole();
}
}
DDD 관점에서는 맞는 말이다. 외부 모듈 의존성을 Controller가 직접 알면 안 된다.
근데 AuthContext는 헤더에서 값만 읽어오는 단순 유틸리티라서 실용적으로는 Controller에서 직접 써도 문제없다고 판단했다. 추후 팀 논의 후 결정할 예정이다.
6. build.gradle 업데이트
// 변경 전
implementation 'com.first-ticket:common:0.0.3-SNAPSHOT'
// 변경 후
implementation 'com.first-ticket:common:0.0.4-SNAPSHOT'
마무리
AuthContext 하나로 모든 API에서 userId, role을 깔끔하게 추출할 수 있게 됐다.
MSA에서 공통 모듈을 잘 활용하면 각 서비스의 코드가 훨씬 간결해진다.
'Spring 개발일지' 카테고리의 다른 글
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 결제창 자동 실행 API 구현 (1) | 2026.05.14 |
|---|---|
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 전체 결제 목록 조회 API (ADMIN) (0) | 2026.05.13 |
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - X-User-Id 헤더 기반 사용자 인증 적용 (0) | 2026.05.11 |
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - 아웃박스 패턴 구현 (0) | 2026.05.08 |
| [팀프로젝트] MSA 기반 티켓팅 프로그램 - Config Server 연동 삽질기 (0) | 2026.05.07 |