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