기본 콘텐츠로 건너뛰기

라벨이 Spring인 게시물 표시

스프링에서 `@ControllerAdvice`를 언제 쓰고 어떻게 구성해야 할까

스프링에서 @ControllerAdvice 를 언제 쓰고 어떻게 구성해야 할까 목차 왜 @ControllerAdvice 가 필요한가 @ControllerAdvice 와 @RestControllerAdvice 의 차이 스프링 MVC에서 전역 처리 로직은 어떻게 적용될까 적용 범위는 반드시 좁혀서 시작하는 것이 좋다 실전 예시: 공통 에러 응답과 전역 예외 처리기 @InitBinder 와 @ModelAttribute 는 언제 쓸까 에러 응답 설계에서 자주 놓치는 기준 기대대로 동작하지 않을 때 확인할 것 운영 가능한 구조로 정리하는 방법 빠른 답 여러 컨트롤러에서 반복되는 예외 처리 로직은 @ControllerAdvice로 모으는 것이 기본입니다. JSON 에러 응답이 목적이라면 보통 @RestControllerAdvice를 먼저 검토하면 됩니다. 적용 범위는 패키지나 애너테이션 기준으로 좁힐 수 있어 전역 남용을 막을 수 있습니다. 핸들러가 기대대로 동작하지 않으면 예외 타입, 우선순위, 응답 본문 생성 방식을 먼저 확인해야 합니다. 빠른 답 여러 컨트롤러에서 반복되는 예외 처리, 바인딩, 공통 모델 설정은 @ControllerAdvice 로 모으는 것이 기본입니다. REST API에서 JSON 에러 응답을 일관되게 내려야 한다면 보통 @RestControllerAdvice 를 먼저 선택합니다. 적용 범위는 basePackages , assignableTypes , annotations 로 좁혀야 전역 남용과 예상치 못한 충돌을 줄일 수 있습니다. 동작이 기대와 다르면 예외가 발생한 위치, 예외 타입 매칭, 여러 어드바이스의 우선순위와 응답 직렬화 방식을 먼저 확인해야 합니다. 컨트롤러 코드가 늘어나기 시작하면 비슷한 로직이 반복됩니다. 입력 검증 실패를 400으로 바꾸는 코드, 특정 비즈니스 예외를 404나 409로 바꾸는 코드, 날짜 문자열을 공통 형식으로 파싱하는 코드가 대표적입니다. 처음에는 각 컨트롤러에서 직접 처리해도 큰 문...

스프링에서 `@Controller`와 `@RestController`를 언제 어떻게 구분할까

스프링에서 @Controller 와 @RestController 를 언제 어떻게 구분할까 목차 왜 두 어노테이션이 나뉘었을까 반환값은 어디로 가는가: 뷰 이름과 응답 본문 @ResponseBody 로 이해하는 핵심 차이 Spring Boot에서 화면용과 API용을 나누는 방법 같은 기능을 두 방식으로 구현해보기 브라우저와 curl 로 바로 확인하는 방법 자주 발생하는 실수와 디버깅 포인트 빠른 답 HTML 화면을 내려주면 보통 @Controller, JSON API를 만들면 보통 @RestController를 사용합니다. @RestController는 사실상 @Controller와 @ResponseBody를 함께 적용한 형태입니다. 문자열 반환값이 뷰 이름인지 응답 본문인지 헷갈릴 때는 어노테이션과 @ResponseBody 유무를 먼저 확인하면 됩니다. 응답 JSON 변환은 HttpMessageConverter가 담당하므로 헤더와 직렬화 설정도 함께 봐야 합니다. 빠른 답 HTML 화면을 렌더링해 내려주면 보통 @Controller 를, JSON 같은 API 응답을 내려주면 보통 @RestController 를 사용합니다. @RestController 는 사실상 @Controller 와 @ResponseBody 를 합친 형태라서 반환값이 뷰 이름이 아니라 HTTP 응답 본문으로 처리됩니다. String 을 반환했는데 동작이 기대와 다르면 먼저 @ResponseBody 유무와 클래스의 어노테이션 종류를 확인하면 됩니다. JSON 응답은 HttpMessageConverter 가 직렬화하므로 Content-Type , DTO 구조, Jackson 설정까지 함께 봐야 정확히 이해할 수 있습니다. 왜 두 어노테이션이 나뉘었을까 스프링 MVC의 출발점은 서버가 HTML을 만들어 브라우저에 내려주는 구조였습니다. 이 흐름에서 컨트롤러는 요청을 받고, 필요한 데이터를 준비한 뒤, 어떤 화면을 렌더링할지 결정합니다. 그래서 @Controller ...

스프링 MVC에서 Filter와 Interceptor를 언제 어떻게 나눠 써야 할까

스프링 MVC에서 Filter와 Interceptor를 언제 어떻게 나눠 써야 할까 목차 왜 둘이 자꾸 헷갈릴까 요청이 들어왔을 때 실제로 어떤 순서로 실행될까 어떤 경우에 Filter를 써야 할까 어떤 경우에 Interceptor를 써야 할까 Spring Boot에서 함께 등록하는 방법 실전 코드로 보기: 로깅은 Filter, 핸들러 기반 인증은 Interceptor curl과 로그로 실행 순서를 검증하는 방법 자주 생기는 실수와 선택 기준 빠른 답 서블릿 단위 공통 처리라면 Filter, 컨트롤러 전후 제어라면 Interceptor가 먼저 후보입니다. 요청 본문/응답 자체를 직접 다뤄야 하면 Filter가 더 유연합니다. 핸들러 정보나 애노테이션 기반 분기가 필요하면 Interceptor가 더 적합합니다. 순서 문제와 중복 실행은 실제 장애로 이어지기 쉬우니 등록 위치와 실행 로그를 함께 확인해야 합니다. 빠른 답 서블릿 레벨에서 모든 요청과 응답을 공통 처리해야 하면 Filter , 컨트롤러 실행 전후를 제어해야 하면 Interceptor 가 먼저 후보입니다. 헤더, 인코딩, CORS, 요청 본문, 응답 감싸기처럼 HTTP 자체를 다뤄야 하면 Filter 가 더 맞습니다. 어떤 컨트롤러 메서드가 호출되는지, 특정 애노테이션이 붙었는지 보고 분기해야 하면 Interceptor 가 더 적합합니다. 스프링 시큐리티를 쓰는 프로젝트라면 인증과 인가의 중심은 보통 시큐리티 필터 체인에 두고, Filter 와 Interceptor 는 보조 역할로 좁히는 편이 안전합니다. 왜 둘이 자꾸 헷갈릴까 Filter 와 Interceptor 는 둘 다 "공통 로직을 한곳에 모아 넣는다"는 점에서 비슷합니다. 그래서 로깅, 인증, 권한 확인, 성능 측정 같은 요구가 나오면 둘 중 어디에 넣어도 될 것처럼 보입니다. 하지만 둘은 동작하는 계층이 다릅니다. Filter 는 서블릿 컨테이너 쪽에서 동작하고, Interceptor 는 스...

스프링 `@Value`를 안전하게 쓰는 방법: 주입 시점부터 설정 바인딩 선택 기준까지

스프링 @Value 를 안전하게 쓰는 방법: 주입 시점부터 설정 바인딩 선택 기준까지 스프링 부트에서 설정값을 코드 밖으로 빼는 일은 거의 필수에 가깝습니다. 외부 API 주소, 타임아웃, 토큰, 기능 플래그처럼 환경마다 달라지는 값을 소스 코드에 직접 넣어두면 배포와 운영이 빠르게 꼬입니다. 이때 가장 먼저 떠올리기 쉬운 도구가 @Value 입니다. 문제는 @Value 가 간단해 보인다는 점입니다. 한 줄로 값을 넣을 수 있다 보니 동작 조건과 주입 시점을 놓치기 쉽고, 설정이 커졌을 때도 계속 같은 방식으로 밀어붙이기 쉽습니다. @Value 는 분명 유용하지만, 어디까지가 적절한 사용 범위인지 알아두지 않으면 디버깅 비용이 커집니다. @Value 는 어떤 문제를 해결할까 @Value 는 외부 설정값 하나를 스프링 빈에 주입할 때 가장 빠르게 적용할 수 있는 방법입니다. 예를 들어 base-url , timeout , enabled 같은 단일 값을 서비스나 컴포넌트 안으로 가져와야 할 때 코드 양이 적고 이해하기 쉽습니다. 핵심은 @Value 가 “설정 한두 개를 직접 꺼내 쓰는 도구”라는 점입니다. 값이 적고 맥락이 단순하면 충분히 좋은 선택입니다. 반대로 같은 접두사 아래에 여러 설정이 묶여 있고, 그 설정들이 하나의 의미 있는 그룹을 이룬다면 @Value 보다 @ConfigurationProperties 가 더 자연스럽습니다. @Value 가 동작하는 조건과 주입 시점 가장 먼저 기억해야 할 사실은 @Value 가 스프링이 관리하는 객체에서만 동작한다는 점입니다. @Component , @Service , @Configuration 이 붙어 있거나 @Bean 으로 등록된 객체여야 합니다. 직접 new 로 생성한 객체에서는 스프링이 개입하지 않으므로 @Value 도 작동하지 않습니다. 주입 시점도 중요합니다. 생성자 파라미터에 붙인 @Value 는 객체를 만들기 전에 해석되어 전달됩니다. 반면 필드 주입과 세터 주입은 객체 생성 이후에 적...