accessToken의 만료 여부를 어떻게 확인 할 수 있을까
문제 개요
오류 상황과 영향 범위 (예: 특정 코드 실행 시 발생, 특정 라이브러리 버전 호환 문제 등) 발생 배경 (예: 코드 테스트 중, 배포 중 문제 발견 등)
- JWT 기반 인증 시스템에서 accessToken은 10분의 만료시간을 가지며, 해당 토큰은 클라이언트의 HttpOnly Cookie에 저장됨.
- accessToken 만료 시 클라이언트 쿠키에서도 사라지게 되어, 만료 여부를 클라이언트에서 인지할 수 없음.
- 이로 인해 서버는 accessToken이 누락된 요청에 대해 "로그인 상태가 아닙니다" 라는 응답만을 보내게 되어, 토큰 만료 사유를 구체적으로 전달하지 못함.
오류 메시지 및 원인 분석
오류 코드, 오류 메시지 포함 HTTP 상태 코드, 애플리케이션 로그, 서버 로그 등 구체적인 오류 정보 정리 및 로그 메시지를 통한 분석 제공 문제 발생 원인에 대한 심층 분석
- 서버 응답
{
"code": "401",
"message": "로그인 상태가 아닙니다."
}
- 기대 응답
{
"code": "401",
"message": "만료된 토큰입니다."
}
- 로그 메시지 분석
- 필터에서 ExpiredJwtException을 캐치하기 전에 accessToken 자체가 쿠키에서 제거되어, 해당 예외가 발생하지 않고 AuthenticationEntryPoint가 처리된다.
- 원인
- accessToken 쿠키의 maxAge가 JWT 토큰의 만료 시간과 동일하게 설정되어 있어, 토큰이 만료되면 브라우저가 먼저 쿠키를 제거한다. 따라서 accessToken 유무조차 확인할 수 없게 된다.
해결 및 고민 과정
처음 문제를 접했을 때 고려했던 대안들과 선택하지 않은 이유 실험적으로 적용한 방법이 실패한 사례와 그 이유 여러 해결책 중 최적의 방안을 선택한 과정
- token이 null 일 경우에 예외 응답을 리턴 시키는 방법
if (token == null) {
setErrorResponse(response, HttpStatus.UNAUTHORIZED.value(), "AccessToken이 존재하지 않습니다.");
return;
}
해당 방식을 jwt 필터에 적용하게 될 경우, 엔드 포인트 접근시 반드시 token값이 필요하게 된다는 문제가 발생하게 됨
- token은 null이고 refreshToken은 null이 아닐 경우 예외 응답 리턴 시키는 방법
if (token == null && refreshToken != null) {
throw new CustomAuthException(CustomAuthException.AuthErrorType.MISSING_TOKEN);
}
해당 방식을 통해 해결하고자 하였지만, 결국 로그인&로그아웃을 통해서 refreshToken이 존재해야만 하는 문제가 여전히 남아있음
최종 해결책 및 구현
문제 해결을 위한 단계별 조치 방법과 코드 예시 (예: 특정 애노테이션 추가, 라이브러리 버전 조정, 설정 변경 등) 참고 자료 (관련 공식 문서, 개발자 커뮤니티 게시물 등)
- 쿠키의 만료시간과 JWT 토큰의 만료시간이 동일하여 토큰 만료와 동시에 쿠키값이 사라지기 때문에 만료 여부를 확인하기 위해서 쿠키의 maxAge를 토큰 만료시간보다 더 길게 설정
- 이 경우, 클라이언트는 만료된 accessToken을 그대로 가지고 있으며, 서버는 이 토큰을 받아 ExpiredJwtException을 통해 만료 여부를 감지하고 적절한 메시지를 반환 할 수 있게 된다.
ResponseCookie cookie = ResponseCookie.from("accessToken", token)
.httpOnly(true)
.secure(true)
.path("/")
.sameSite("None")
.maxAge(Duration.ofMinutes(15)) // JWT보다 더 긴 쿠키 만료시간 설정
.build();
결과 및 성능 분석
개선 후 응답 속도, DB 부하 감소 수치 등 구체적인 데이터 포함 문제 해결 전/후 성능 비교 그래프나 로그 분석 내용 포함 이슈 트래킹 및 자동화 방안 추가 (내부 개발자가 반복적인 문제 해결을 효율적으로 관리할 수 있도록 가이드 제공)
- accessToken 만료 시, 필터 내에서 ExpiredJwtException 발생시 → 서버가 “만료된 토큰입니다.”라는 메시지를 정상적으로 반환하게 된다.
- 프론트는 이 메시지를 토대로 자동으로 refresh 요청을 보내는 로직을 구현할 수 있게 된다.
추가 개선점
유사한 문제를 방지하기 위한 주의할 점 (예: 애노테이션 명시 여부, 프레임워크 업데이트 주기 확인 등) 문제 해결 과정에서 배운 점 및 중요한 교훈 공유 보안 고려 사항 추가 (해결 과정에서 발생할 수 있는 보안 리스크 및 예방 조치 포함)
- 백엔드에서 토큰 재발급(Refresh)로직 연계 자동화 고려
- 쿠키에 만료된 토큰을 남겨두는 방식이므로, 보안 민감 환경에서 엄격한 만료 관리가 필요하다.