리팩토링을 진행하던 도중, 이름 정보를 매번 DB에서 조회하는 대신 JWT 토큰에 함께 담아두는 방법을 고민해보게 되었다.
이 방법의 장점은 반복적인 DB 조회를 피할 수 있어 성능을 향상시킬 수 있다는 점입니다.
하지만 그만큼 토큰의 크기가 커질 수 있다는 단점도 존재한다.
이렇게 개발을 하다 보면 항상 장단점이 공존하는 것을 느끼게 된다
이번 포스트에서는 이러한 장단점을 고려하면서도 새로운 접근법을 시도를 해보고자한다.
토큰에 사용자 이름을 포함해 인증 후 바로 접근할 수 있도록 개선한 과정을 적어봐야겠다
JWT 토큰 내 사용자 정보 개선하기
- 기존 코드의 문제점
// 변경 전
public String createAccessToken(String username, Role role, Long expiredMs) {
return Jwts.builder()
.claim("username", username)
.claim("role", role.name())
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expiredMs))
.signWith(secretKey)
.compact();
}
- JWT 토큰에 username과 role만 포함
- 사용자 이름(name) 조회 시마다 DB 접근 필요
- 개선된 코드
// JWTUtil: 토큰 생성 시 name 추가
public String createAccessToken(String username, String name, Role role, Long expiredMs) {
return Jwts.builder()
.claim("username", username)
.claim("role", role.name())
.claim("name", name)// name 정보 추가
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expiredMs))
.signWith(secretKey)
.compact();
}
// CustomSuccessHandler: 로그인 성공 시 name 포함하여 토큰 생성
public void onAuthenticationSuccess(...) {
CustomOAuth2User customUserDetails = (CustomOAuth2User) authentication.getPrincipal();
String username = customUserDetails.getUsername();
String name = customUserDetails.getName();
String accessToken = jwtUtil.createAccessToken(username, name, Role.TEACHER, accessTokenExpiration);
...
}
// UserService: SecurityContextHolder에서 바로 정보 조회
public UserInfoResponseDTO getUserInfo() {
String name = getCustomOAuth2User();
return UserInfoResponseDTO.builder()
.name(name)
.build();
}
private static String getCustomOAuth2User() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) return null;
Object principal = authentication.getPrincipal();
if (!(principal instanceof CustomOAuth2User customOAuth2User)) {
return null;
}
return customOAuth2User.getName();
}
- Paper 서비스와의 차이점 설명
- Paper 서비스는 Student와 연관관계가 있는 엔티티
- Paper 조회 시 이미 Student 정보가 함께 로딩됨
- 따라서 student.getName()은 추가 DB 조회 없이 가능
- 이런 경우는 토큰에 정보를 담아둘 필요가 없음
- 개선 효과
- JWT 토큰에 필요한 정보(name)를 미리 포함
- SecurityContextHolder를 통한 즉시 정보 조회
- 불필요한 DB 조회 제거
- null 상황에 대한 안전한 처리
- 더 간결하고 명확한 코드 구조
- 선생님 로그인의 경우
1. 소셜 로그인 → JWT 토큰 발급
2. /user/info API 호출 시
- 필요한 정보: email, name
- 이 정보들은 이미 로그인 할 때 알고 있는 정보
- 따라서 토큰에 넣어두고 바로 쓰면 됨!
- Student 페이퍼 입장의 경우
1. 이름 + 학급코드 입력 → Student 생성/확인 → 입장
2. Paper 작성/조회 시
- 필요한 정보: student의 이름, 학급 정보 등
- 이 정보들은 이미 Paper 테이블에 Student와 연결되어 저장
- Paper-Student가 DB에서 연결된 관계라 따로 조회 필요 없음
🙇♂️ 마무리
개발엔 정답이 없다. 풋살할 때 나는 개발이 아니긴하다.. 왜냐면 나는 고수기 때뭄ㄴ이다.. 개발은 초보다 ..
오늘은 조금 피곤하므로 빠른 마무리 해야겠다..

'Project > Sparkle-Note' 카테고리의 다른 글
| [Project] Sparkle Note / Paper 서비스의 선생님 작성 권한 추가 과정 (1) | 2024.11.13 |
|---|---|
| [Project] Sparkle Note / 사용자 인증 정보 구분하기 (1) | 2024.11.12 |
| [Project] Sparkle Note / JWT 토큰 전달 (0) | 2024.11.02 |
| [Project] Sparkle-Note / 데일리로그 (0) | 2024.10.25 |
| [Project] Sparkle-Note / 데일리로그 (1) | 2024.10.14 |