Tokenization
이 글은 2026년 06월 05일 작성된 글입니다.
오늘은 API Key 기반 인증을 쿠키 기반 인증으로 확장하고, JWT(JSON Web Token)를 이용한 Access Token 구조를 학습했다. 또한 OpenAPI와 Postman에서 인증을 처리하는 방법, 인증(Authentication)과 인가(Authorization)의 흐름을 정리했다.
1. API Key 쿠키 자동 전송
모든 요청에서 apiKey 쿠키가 자동으로 전송되도록 리팩토링했다.
핵심
- 인증 정보 전달 코드 중복 제거
- Rq 클래스로 쿠키 처리 로직 이동
- 모든 요청에 apiKey 쿠키 자동 포함
2. Cookie 기반 인증 추가
기존 Authorization 헤더 인증 외에 Cookie 기반 인증도 지원하도록 개선했다.
.cookie(new Cookie("apiKey", apiKey))
핵심
- Authorization 헤더 인증 지원
- Cookie 인증 지원
- 인증 방식 다중화
3. getActor 리팩토링
인증 정보 조회 로직을 정리하여 가독성과 재사용성을 높였다.
핵심
- 인증 관련 코드 분리
- 중복 제거
- 유지보수성 향상
4. Rq 클래스 개선
공통 요청 처리 기능을 Rq 클래스로 이동했다.
private String getHeader(String name, String defaultValue) {
return Optional
.ofNullable(req.getHeader(name))
.filter(headerValue -> !headerValue.isBlank())
.orElse(defaultValue);
}
핵심
- getHeader 추가
- getCookieValue 추가
- Optional 활용
- null 처리 개선
5. Rq 클래스와 쿠키 정리
Rq 클래스
- 컨트롤러 공통 로직 담당
- HttpServletRequest 래핑
- HttpServletResponse 래핑
- HttpSession 래핑
- 파사드(Facade) 패턴 적용
쿠키 특징
- 쿠키 관리는 브라우저가 담당
- 서버는 Set-Cookie 응답만 전달
- 브라우저가 쿠키를 저장
- 이후 요청 시 자동 전송
- 동일 도메인에서만 사용 가능
6. 개발 환경용 API Key 설정
개발 편의를 위해 샘플 회원의 apiKey와 username을 동일하게 설정했다.
핵심
- 개발환경(dev) 전용 적용
- 운영환경(prod) 제외
- 테스트 편의성 향상
7. static 필드 의존성 주입
Spring은 static 필드 직접 주입을 지원하지 않는다.
해결 방법
- setter 메서드 생성
- @Autowired 적용
- setter 내부에서 static 필드 초기화
AppConfig 활용
AppConfig.isDev()
핵심
- Environment 직접 주입 불필요
- 가독성 향상
- 편리한 환경 체크
8. 로그아웃 구현
HttpOnly 쿠키를 삭제하는 로그아웃 기능을 구현했다.
assertThat(apiKeyCookie.getMaxAge()).isEqualTo(0);
핵심
- DELETE 요청 사용
- Set-Cookie 응답 전송
- Max-Age=0 설정
- 브라우저가 자동 삭제
9. OpenAPI에서 로그인/로그아웃
Swagger(OpenAPI) 환경에서도 로그인과 로그아웃이 가능하도록 설정했다.
핵심
- 로그인 시 apiKey 쿠키 생성
- API 테스트 가능
- 로그아웃 시 쿠키 삭제
10. @SecurityScheme 적용
OpenAPI에서 Authorization 헤더를 직접 입력할 수 있도록 설정했다.
@SecurityScheme
핵심
- Swagger 인증 지원
- Bearer Token 입력 가능
- API 테스트 편의성 향상
11. 인증 흐름 정리
인증 정보 우선순위
- Authorization 헤더
- Cookie(apiKey)
핵심
- 헤더 인증 우선
- 쿠키 인증 보조
- 둘 다 없으면 인증 실패
12. JWT 기반 Access Token 도입
기존 apiKey 방식의 단점을 해결하기 위해 JWT 기반 Access Token을 도입한다.
기존 방식
SELECT * FROM member WHERE apiKey = ?
문제점
13. Access Token과 Refresh Token
| 구분 | Access Token | Refresh Token |
|---|
| 수명 | 짧음 | 김 |
| DB 조회 | 없음 | 있음 |
| 폐기 | 어려움 | 가능 |
| 목적 | API 인증 | 토큰 재발급 |
핵심
- JWT = Access Token
- apiKey = Refresh Token
- 인증 성능 향상
14. JWT 특징
JWT(JSON Web Token)는 인증 정보를 담은 토큰이다.
JWT 구성 요소
- Header
- Payload(Claims)
- Signature
핵심
- 서버 저장 불필요
- Stateless 인증
- DB 조회 없음
- 빠른 인증 처리
15. JWT 라이브러리 추가
implementation("io.jsonwebtoken:jjwt-api:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6")
핵심
16. JWT 생성 테스트
JWT를 생성하고 디코딩하여 내부 데이터를 확인했다.
JWT에 포함되는 정보
- 사용자 정보
- 발급 시간(iat)
- 만료 시간(exp)
- 기타 Claims
주의사항
JWT는 암호화가 아니다.
JWT는 Base64 인코딩이므로 누구나 내용을 확인할 수 있다.
따라서 비밀번호와 같은 민감 정보는 절대 저장하면 안 된다.
✅ 정리
- API Key 인증을 Cookie 기반 인증으로 확장하였다.
- Authorization 헤더와 Cookie 인증을 모두 지원하도록 개선하였다.
- Rq 클래스로 요청 처리 공통 로직을 분리하였다.
- OpenAPI에서도 로그인과 로그아웃을 수행할 수 있도록 설정하였다.
- JWT 기반 Access Token 구조를 도입하기 위한 기반 작업을 진행하였다.
- JWT는 서버 저장 없이 검증 가능한 Stateless 인증 방식이다.
- 기존 apiKey는 Refresh Token 역할로 활용할 예정이다.