📓뉴스피드 API Github
JWT 기능 분리
초기 설계
JwtTokenProvider 클래스 하나에서 JWT 관련 모든 로직을 처리하도록 설계하였다.
- 주요 역할:
- 토큰 생성 및 파싱
- 유효성 검사
- 쿠키 및 헤더에서의 추출/저장
SecurityContextHolder를 통한 인증 정보 저장
→ 하나의 클래스에 책임이 과도하게 집중되어 있어 유지보수에 불편함이 발생했다.
문제점
- 단일 책임 원칙 위배 (SRP)
- 클래스가 토큰 생성, 인증 정보 설정, 요청·응답 처리 등 다양한 책임을 동시에 지고 있었다.
- 결과적으로 클래스가 비대해지고, 각 기능의 경계가 불분명해졌다.
- 구조 복잡도 증가
- 여러 책임이 섞이면서 메서드를 파악하거나 수정하기 어렵다.
- 테스트 작성 시에도 의존성이 커지고 조합이 복잡해짐.
해결 방법
클래스를 역할에 따라 기능을 아래와 같이 명확히 분리했다:
JwtAuthenticationProvider
- 인증 정보(SecurityContext) 설정 및 삭제를 담당
UserDetails 객체를 생성하고, SecurityContextHolder에 저장하거나 제거하는 역할
- JWT → 인증 컨텍스트로 전환하는 책임을 명확히 담당
JwtTokenUtils
- JWT 생성, 파싱, 검증 등 토큰 자체를 다루는 핵심 로직을 담당
- 서명 키, 만료 시간, 클레임 추출 등 JWT의 표준 규격 처리
- 다른 모듈에서도 직접 토큰을 다루고자 할 때 재사용 가능
JwtTokenProvider
- 외부에서 JWT 관련 기능을 사용할 수 있도록 통합된 인터페이스 역할
- 내부적으로
JwtTokenUtils를 호출해 필요한 기능을 수행
- 클라이언트 코드에서는 이 클래스를 통해 간접적으로 JWT 기능을 사용하게 하여 캡슐화 강화
TokenCookieUtils
- 쿠키에 토큰을 저장하거나 삭제하는 책임을 담당
- 주로 Refresh 토큰을 쿠키에 저장하며,
ServletResponse를 다루는 기능 포함
HttpServletResponse에 대한 의존성이 있으므로 컨트롤러에서만 사용
TokenExtractor
- 요청 객체(HttpServletRequest)로부터 토큰을 추출하는 기능을 담당
- 쿠키 또는 Authorization 헤더에서 토큰을 파싱하여 반환
HttpServletRequest 기반으로 동작하므로 컨트롤러 또는 필터에서 사용
개선 효과
- 각 클래스가 명확한 책임만을 가지도록 분리되어 SRP 원칙을 충실히 따르게 됨
- 클래스 간 결합도가 낮아져 재사용성 증가, 테스트 용이성 향상
- 변경 사항이 생겨도 해당 책임을 가진 클래스만 수정하면 되므로 유지보수 효율성 증가
- 전체 JWT 구조가 계층적이고 직관적으로 정리되어 가독성과 확장성이 높아짐