Spring boot
3. 예외 처리 중앙 집중화
mynote6676
2025. 7. 14. 16:40
| 로그 레벨 설정 확인(-dev)
# 2칸 공백, 탭키 절대 사용 금지!
# 로그 설정 (개발환경용)
# 로그 레벨의 개념
# ERROR > WARN > INFO > DEBUG > TRACE
logging:
level:
root: INFO
com.tenco.blog: DEBUG # 개발 시 모든 로그 확인
#com.tenco.blog.user: INFO # User 패키지만 INFO (선택사항)
| 로그 레벨설정 확인(-prod)
# 2칸 공백, 탭키 절대 사용 금지!
# 로그 설정 (개발환경용)
# 로그 레벨의 개념
# ERROR > WARN > INFO > DEBUG > TRACE
logging:
level:
root: WARN
com.tenco.blog: INFO # 운영 시 중요한 로그만
log.debug("메서드 시작"); // 개발환경: 출력됨, 프로덕션: 출력안됨
log.info("게시글 저장 시작"); // 개발환경: 출력됨, 프로덕션: 출력안됨
log.warn("권한 없는 접근 시도"); // 개발환경: 출력됨, 프로덕션: 출력됨
log.error("심각한 오류 발생"); // 개발환경: 출력됨, 프로덕션: 출력됨
UserController - 코드 리팩토링
package com.tenco.blog.user; import com.tenco.blog._core.errors.exception.Exception400; import com.tenco.blog._core.errors.exception.Exception401; import com.tenco.blog.board.BoardController; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @RequiredArgsConstructor // DI 처리 @Controller public class UserController { private static final Logger log = LoggerFactory.getLogger(UserController.class); private final UserRepository userRepository; private final HttpSession httpSession; @GetMapping("/user/update-form") public String updateForm(HttpServletRequest request, HttpSession session) { log.info("회원 정보 수정 폼 요청"); User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) { throw new Exception401("로그인이 필요한 서비스 입니다"); } request.setAttribute("user", sessionUser); return "user/update-form"; } @PostMapping("/user/update") public String update(UserRequest.UpdateDTO reqDTO, HttpSession session, HttpServletRequest request) { log.info("회원정보 수정 요청"); User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) { throw new Exception401("로그인이 필요한 서비스 입니다"); } reqDTO.validate(); User updateUser = userRepository.updateById(sessionUser.getId(), reqDTO); session.setAttribute("sessionUser", updateUser); return "redirect:/user/update-form"; } @GetMapping("/join-form") public String joinForm() { log.info("회원 가입 요청 폼"); return "user/join-form"; } @PostMapping("/join") public String join(UserRequest.JoinDTO joinDTO, HttpServletRequest request) { log.info("회원 가입 기능 요청"); log.info("사용자 명 : {} ", joinDTO.getUsername()); log.info("사용자 이메일 : {} ", joinDTO.getEmail()); joinDTO.validate(); User existUser = userRepository.findByUsername(joinDTO.getUsername()); if (existUser != null) { throw new Exception401("이미 존재하는 사용자명 입니다 " + joinDTO.getUsername()); } User user = joinDTO.toEntity(); userRepository.save(user); return "redirect:/login-form"; } @GetMapping("/login-form") public String loginForm() { log.info("로그인 요청 폼"); return "user/login-form"; } @PostMapping("/login") public String login(UserRequest.LoginDTO loginDTO) { log.info("=== 로그인 시도 ==="); log.info("사용자명 : {} ", loginDTO.getUsername()); loginDTO.validate(); User user = userRepository.findByUsernameAndPassword(loginDTO.getUsername(), loginDTO.getPassword()); if (user == null) { throw new Exception400("사용자명 또는 비밀번호가 틀렸어"); } httpSession.setAttribute("sessionUser", user); return "redirect:/"; } @GetMapping("/logout") public String logout() { log.info("=== 로그아웃 ==="); httpSession.invalidate(); return "redirect:/"; } }
UserRepository - 코드 리팩토링
package com.tenco.blog.user; import com.tenco.blog._core.errors.exception.Exception400; import com.tenco.blog.board.BoardRepository; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor @Repository public class UserRepository { private static final Logger log = LoggerFactory.getLogger(BoardRepository.class); private final EntityManager em; @Transactional public User updateById(Long id, UserRequest.UpdateDTO reqDTO) { log.info("회원 정보 수정 - 시작 ID : {}", id); User user = findById(id); user.setPassword(reqDTO.getPassword()); return user; } public User findByUsernameAndPassword(String username, String password) { // 필요 하면 직접 예외 처리 설정 try { String jpql = " SELECT u FROM User u " + " WHERE u.username = :username AND u.password = :password "; TypedQuery typedQuery = em.createQuery(jpql, User.class); typedQuery.setParameter("username", username); typedQuery.setParameter("password", password); return (User) typedQuery.getSingleResult(); } catch (Exception e) { return null; } } @Transactional public User save(User user) { log.info("회원 정보 저장 시작"); em.persist(user); return user; } public User findByUsername(String username) { log.info("중복 사용자 이름 조회"); // 필요하다면 직접 예외 처리 try { String jqpl = " SELECT u FROM User u WHERE u.username = :username "; return em.createQuery(jqpl, User.class) .setParameter("username", username) .getSingleResult(); } catch (Exception e) { return null; } } public User findById(Long id) { log.info("사용자 조회 - ID : {}", id); User user = em.find(User.class, id); if (user == null) { throw new Exception400("사용자를 찾을 수 없습니다"); } return user; } }
Exception401 처리 수정
@ExceptionHandler(Exception401.class)
@ResponseBody // 데이터를 반환 함
public ResponseEntity<String> ex401ByData(Exception401 e, HttpServletRequest request) {
String script = "<script> alert('"+ e.getMessage() +"'); history.back(); </script>" ;
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.contentType(MediaType.TEXT_HTML)
.body(script);
}
728x90