
현재 학교 내 노트북 수리 요청 및 사용자 관리 시스템을 개발 중입니다.
Spring Boot와 Spring Security를 이용해 로컬 로그인과 카카오/구글 OAuth 로그인을 모두 지원합니다.
사용자 역할(Role)에 따라
상단 메뉴바에 현재 로그인 중인 사용자 정보를 표시합니다. 이때 관리자 계정으로 로그인이 되어있기 때문에 TOP_ADMIN으로 표시되어야하나, 역할이 ANONYMOUS(손님)으로 잘못 표시되는 문제가 발생했습니다.
👉 문제는 게시글 상세 페이지(
/posts/{id})에서만 발생했어요.
다른 페이지에서는 정상적으로 TOP_ADMIN | 관리자로 표시되었죠.

원인을 파악하기 위해 게시글 상세 페이지(/posts/{postId})와 관련된 컨트롤러에서 viewPost()메서드를 분석했습니다.
// 게시글 상세
@GetMapping("/{postId}")
public String viewPost(@PathVariable String postId,
Model model,
HttpServletRequest request) {
postService.incrementViewCount(postId);
Post post = postService.getPost(postId);
model.addAttribute("post", post);
model.addAttribute("comments", commentService.getCommentsByPostId(postId));
// 현재 로그인한 사용자 정보를 가져오기 위한 인증 객체 획득
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 인증된 사용자의 경우
if (authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal();
if (principal instanceof CustomOAuth2User user) {
model.addAttribute("currentUserEmail", user.getEmail());
model.addAttribute("userRole", user.getRole().name());
} else if (principal instanceof org.springframework.security.core.userdetails.User user) {
// 로컬 유저의 경우 DB에서 이메일/역할 가져오기 (‼️문제 발생 의심 지점‼️)
System.out.println("✅ 로컬사용자"); //출력 ❌
String email = user.getUsername(); // email이 username에 담김
String role = postService.findRoleByEmail(email); // PostService에서 사용자 role 조회하는 메서드 만들기
model.addAttribute("currentUserEmail", email);
model.addAttribute("userRole", role);
} else if (principal instanceof org.springframework.security.core.userdetails.User user) {
String email = user.getUsername();
String role = postService.findRoleByEmail(email);
model.addAttribute("currentUserEmail", email);
model.addAttribute("userRole", role);
} else if (principal instanceof String email) {
model.addAttribute("currentUserEmail", email);
model.addAttribute("userRole", "USER");
} else {
model.addAttribute("currentUserEmail", null);
model.addAttribute("userRole", "ANONYMOUS");
}
} else {
model.addAttribute("currentUserEmail", null);
model.addAttribute("userRole", "ANONYMOUS");
}
// CSRF
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
model.addAttribute("_csrf", csrfToken);
return "post/view";
}
콘솔 출력 결과 authentication != null && authentication.isAuthenticated()조건은 통과하지만 ✅ 로컬 사용자가 출력되지 않았습니다. principal instanceof org.springframework.security.core.userdetails.User user조건이 false가 되는 것이 원인이었죠.
SecurityContextHolder.getContext().getAuthentication().getPrincipal()을 통해 로그인 정보를 가져오는데, principal 객체 타입이 잘못되어 발생한 문제였습니다.
| 로그인 방식 | principal 타입 |
|---|---|
| OAuth 로그인(구글, 카카오) | CustomOAuth2User |
| 로컬 로그인 | CustomUserDetails |
👉 그런데 저는 컨트롤러에서 CustomOAuth2User만 체크하고, CustomUserDetails는 체크하지 않아
userRole = ANONYMOUS로 떨어졌던 겁니다.
viewPost() 메서드에서 principal의 타입을 명확히 분기했습니다.
if (principal instanceof CustomOAuth2User user) {
// OAuth 사용자 처리
...
} else if (principal instanceof CustomUserDetails userDetails) {
// 로컬 로그인 사용자 처리
...
}

이로써 로컬 로그인 사용자도 userRole, username이 정확하게 나왔답니다!!👏👏👏