스프링 하면서 필수로 알아야하는 지식
개인적으로 스프링이라는 프레임워크를 배우면서 느낀 "아 이건 필수적으로 알아야 겠다."를 정리해 봤습니다.
스프링의 철학과 왜 스프링을 쓸까?
우리는 스프링을 쓰면서 왜 스프링을 쓸까요? 단순히 대한민국에서 제일 많이 쓰이니깐? 그게 아마 맞겠죠.
스프링은 참 편리한 기능을 많이 제공해 줍니다. 그 중에서도 스프링의 핵심 철학은 바로
- DI (Dependency Injection, 의존성 주입): 객체 간의 의존 관계를 개발자가 아닌 스프링이 주입해줌으로써 결합도를 낮추고 유연성을 높입니다. XML 또는 어노테이션을 통해 설정할 수 있습니다.
- IoC (Inversion of Control, 제어의 역전): 객체의 생성과 생명 주기를 개발자가 아닌 스프링 컨테이너가 관리합니다. IoC를 통해 코드가 더욱 모듈화되고 테스트하기 쉬워집니다.
위의 두가지를 예로 들 수 있습니다. 생성자 주입을 봐보죠
@Service
public class UserController {
private final UserService userService;
// 생성자를 통해 UserService 의존성을 주입받음
public UserController(UserService userService) {
this.userService = userService;
}
public void processUser(String name) {
userService.createUser(name);
}
}
이런 식으로 생성자에 userService를 넣어주기만 해도 스프링이 알아서 의존 관계를 설정해 줍니다.
이것이 얼마나 편리한 기능인가요?
예외 처리 로직
스프링의 예외 처리
서블릿은 다음 2가지 방식으로 예외 처리를 지원합니다.
- Exception
- response.sendError(HTTP 상태 코드, 오류 메시지)
sendError
오류가 발생했을 때 'HttpServletResponse' 가 제공하는 'sendError' 라는 메서드를 사용해도 됩니다.
이것을 호출한다고 당장 예외가 발생하는 것은 아니지만, 서블릿 컨테이너에게 오류가 발생했다는 점을 전달할 수 있습니다.
이 메서드를 사용하면 HTTP 상태 코드와 오류 메시지도 추가할 수 있습니다.


서블릿 컨테이너가 뭐인 지 모르시는 분들도 계실 수 있다. 그런분들은 아래 글을 확인해 주세요.
[spring mvc] 서블릿 컨테이너 너는 누구냐
서블릿 컨테이너는 대체 뭐하는 것일까서블릿 컨테이너의 동작 방식서블릿 컨테이너(Servlet Container)는 Java 웹 애플리케이션에서 서블릿(Servlet)을 관리하고 실행하는 역할을 하는 소프트웨어입니
gotobill.tistory.com
Exception
코드를 작성하면서 예외가 발생했을 때, json으로 프론트한테 전해주는 경우 에러를 담아서 response에 담아서 줍니다.
그렇다면 내부에서 처리하려면 어떻게 해야할까요? 단순히 try-catch로 잡을 수도 있을 겁니다.
애플리케이션에서 예외를 못 잡고 서블릿 밖으로 나간다면 어떻게 될까요?
이것을 확인하기 위해서 스프링에서 기본으로 제공하는 예외를 꺼야합니다.

@Controller
public class ServletExController {
@GetMapping("/error-ex")
public void errorEx() {
throw new RuntimeException("예외 발생!");
}
}
이런 식으로 오류를 만들었을 경우, 스프링에서 기본으로 제공하는 예외를 끈 경우 tomcat이 기본 페이지를 제공한다.
그러나 이러한 기본 제공 페이지는 이쁘지 않습니다.
서블릿의 에러 페이지
서블릿 컨테이너가 제공하는 기본 예외 처리 화면은 고객 친화적이지 않습니다..
서블릿이 제공하는 오류 화면 기능을 사용해 봅시다.
서블릿은 Exception(예외)가 발생해서 서블릿 밖으로 전달되거나 또는 response.sendError()가 호출 되었을 때 각각의 상황에 맞춘 오류 처리 기능을 제공합니다.
@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");
ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/error-page/500");
factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
}
}
이렇게 에러 페이지를 설정할 수 있습니다.
-> 404(NOT FOUND)인 경우에는 /error-page/404를 호출한다는 로직입니다.!
에러 페이지를 호출을 했으면 다시 controller에서 잡아줘야겠죠?
@Controller
public class ErrorPageController {
@RequestMapping("/error-page/404")
public String errorPage404(HttpServletRequest request, HttpServletResponse response) {
return "error-page/404";
}
}
이런 식으로 위에서 설정해준 페이지를 이렇게 컨트롤러에서 잡아서 내가 원하는 페이지를 보여주게 할 수 있습니다.
여기까지의 내용을 정리해 볼까요?
WAS는 오류가 발생하면 해당 오류에 대한 정보를 바탕으로 사전에 설정된 오류 페이지를 찾습니다.
예를 들어, RuntimeException이 발생했을 때, WAS는 new ErrorPage(RuntimeException.class, "/error-page/500")와 같이 등록된 정보를 확인합니다.
설정된 오류 페이지 경로가 /error-page/500이라면, WAS는 해당 경로를 다시 요청하여 오류 페이지를 출력합니다.
에러가 난 경우

에러 페이지 처리

여기서 중요한 키 포인트는 클라이언트는 이러한 에러 로직을 모르고 서버 내부에서만 이러한 에러 처리를 하기 위해 추가적인 호출을 한다는 것입니다.
'개발' 카테고리의 다른 글
[Spring] Spring Security, OAuth 2.0, JWT로 카카오 로그인 구현하기 (0) | 2024.11.22 |
---|---|
[배포] Docker, spring을 통한 무중단 배포 구현 (2) | 2024.10.16 |
[java] JVM 개념 및 기능 : 왜 쓰는 걸까? (3) | 2024.10.10 |
[배포] github actions, EC2, nginx를 통한 무중단 배포 (3) | 2024.10.09 |
[spring] spring security 완전 정복 (4) | 2024.10.09 |