[버티] 프로젝트 개발 중 마주한 사소한 이슈들
버티 프로젝트 개발 중 마주한 사소한 이슈들 정리
이 문서는 “버티” 프로젝트를 개발하면서 마주쳤던 비교적 사소하지만, 실제 구현 과정에서는 꽤나 시간을 잡아먹거나 시행착오를 유발했던 문제들을 기록해두는 공간입니다.
단순한 에러라기보다는 “한 번쯤은 헷갈릴 수 있는 포인트들”을 중심으로 정리하여, 나중에 유지보수하거나 다른 프로젝트에서 재사용할 때 참고할 수 있도록 작성합니다.
1. JJWT 라이브러리 버전에 따른 변경 사항
JJWT 라이브러리의 업데이트로 인해 토큰 생성 및 파싱 방식이 크게 변경되었습니다. 기존 방식으로 작성된 코드는 더 이상 컴파일되지 않거나 실행 시 에러가 발생할 수 있습니다.
🔧 기존 코드 (구버전 JJWT)
String secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
Claims claims = Jwts.claims().setSubject(user.getNickname());
String accessToken = Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLISECOND))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
Claims parsedClaims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(accessToken).getBody();
✅ 변경 코드 (최신 JJWT)
SecretKey secretKey = Keys.hmacShaKeyFor(secretKeyStr.getBytes());
Claims claims = Jwts.claims().subject(user.getNickname()).build();
String accessToken = Jwts.builder()
.claims(claims)
.header()
.type("JWT")
.and()
.issuedAt(now)
.expiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLISECOND))
.signWith(secretKey, Jwts.SIG.HS256)
.compact();
Claims parsedClaims = Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(accessToken)
.getPayload();
참고 :
2. 카카오 소셜 로그인 이메일 누락 문제
🧩 문제 상황
카카오 로그인 시 사용자 이메일이 제공되지 않아 InternalAuthenticationServiceException
이 발생하는 문제가 있었습니다.
✅ 해결 방법
카카오 계정에 이메일 정보가 없을 경우 자동으로 생성된 이메일을 부여하도록 로직을 보완했습니다.
// KakaoOAuth2UserInfo 클래스
@Override
public String getEmail() {
if (attributes.containsKey("kakao_account")) {
Map<String, Object> kakaoAccount = (Map<String, Object>) attributes.get("kakao_account");
if (kakaoAccount != null && kakaoAccount.containsKey("email")) {
return (String) kakaoAccount.get("email");
}
}
return null; // 상위 메소드에서 처리
}
// OAuth2UserService 클래스
private OAuth2User processOAuth2User(...) {
String email = oAuth2UserInfo.getEmail();
if (email == null || email.isEmpty()) {
email = registrationId + "_" + oAuth2UserInfo.getId() + "@example.com";
log.debug("이메일 정보가 없어 생성된 이메일: {}", email);
}
// 나머지 사용자 생성/업데이트 로직
...
}
3. OAuth2 인증 요청 정보 손실 문제
🧩 문제 상황
로그인 시 다음과 같은 오류가 발생했습니다:
oauth2LoginException: authorization_request_not_found
이유는 Security 설정에서 다음과 같이 세션 생성을 완전히 차단했기 때문입니다:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
OAuth2 로그인 과정은 내부적으로 세션에 인증 요청 정보를 저장하여 인증을 이어가는데, 해당 설정으로 인해 정보가 손실되었습니다.
✅ 해결 방법
개발 초기에는 단순화를 위해 다음과 같이 설정을 변경했습니다:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
이를 통해 OAuth2 인증 플로우 중 세션을 사용할 수 있도록 하여 문제를 해결했습니다.
💡 추가 구현: 리프레시 토큰
보안성과 사용자 경험을 위해 리프레시 토큰도 함께 구현했습니다.
RefreshToken
엔티티 및 리포지토리 생성- 토큰 갱신 서비스 및 API 엔드포인트 구현
- 액세스 토큰과 리프레시 토큰을 분리 관리하여 보안성 강화