기본 콘텐츠로 건너뛰기

라벨이 Spring Boot인 게시물 표시

스프링 부트 AutoConfiguration은 어떻게 필요한 빈만 자동 등록할까

스프링 부트 AutoConfiguration은 어떻게 필요한 빈만 자동 등록할까 빠른 답 AutoConfiguration의 출발점은 @SpringBootApplication 내부의 @EnableAutoConfiguration이다. AutoConfigurationImportSelector가 후보 설정을 수집하고 조건에 맞는 클래스만 남긴다. 원하지 않는 자동 설정은 exclude, excludeName, spring.autoconfigure.exclude로 제거할 수 있다. 빈 등록 결과가 예상과 다르면 --debug와 Condition Evaluation Report부터 확인하는 것이 가장 빠르다. 목차 흐름으로 보기 왜 AutoConfiguration이 필요한가: 반복 설정을 줄이는 기본 전략 @SpringBootApplication 에서 시작되는 자동 설정 진입점 AutoConfigurationImportSelector 는 어떤 순서로 후보를 고를까 조건부 자동 설정은 어떻게 읽어야 할까 실전 예시: spring-boot-starter-web 을 추가하면 무엇이 일어날까 자동 설정을 끄거나 바꾸는 실전 설정 방법 디버깅: 왜 어떤 빈은 등록되고 어떤 빈은 빠질까 실무에서 자주 하는 오해와 주의점 정리 흐름으로 보기 핵심은 단순합니다. 스프링 부트가 "마법처럼 아무 빈이나 등록하는 것"이 아니라, 자동 설정 후보를 먼저 모으고, 애플리케이션 상태를 보고, 조건을 통과한 설정만 적용하는 구조입니다. 그래서 AutoConfiguration은 감으로 이해하기보다 "후보 수집 -> 조건 평가 -> 빈 등록"의 흐름으로 보는 편이 훨씬 정확합니다. 왜 AutoConfiguration이 필요한가: 반복 설정을 줄이는 기본 전략 순수 스프링만 사용할 때는 웹 서버, JSON 직렬화기, 메시지 컨버터, 데이터소스, 트랜잭션 매니저 같은 인프라 빈을 직접 등록하는 경우가 많았습니다. 문제는 이런 설정이 프로...

스프링에서 `@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 ...

스프링 `@Value`가 기대대로 주입되지 않는 이유와 안전하게 사용하는 방법

스프링 @Value 가 기대대로 주입되지 않는 이유와 안전하게 사용하는 방법 스프링 부트에서 설정값을 읽을 때 가장 먼저 떠오르는 도구가 @Value("${...}") 입니다. 문법이 짧고 바로 쓸 수 있어서 편하지만, 동작 원리를 모른 채 남용하면 의외로 자주 문제를 만납니다. 어떤 클래스에서는 값이 잘 들어오는데 다른 곳에서는 null 처럼 보이거나, 애플리케이션 시작 시점에 Could not resolve placeholder 예외가 터지는 식입니다. 핵심은 하나입니다. @Value 는 임의의 객체에 값을 꽂아 넣는 기능이 아니라, 스프링 컨테이너가 관리하는 빈에 대해 정해진 생명주기 안에서 실행되는 주입 메커니즘입니다. 이 전제를 이해하면 @Value 가 잘 맞는 범위, 피해야 할 패턴, 그리고 언제 @ConfigurationProperties 로 넘어가야 하는지가 한 번에 정리됩니다. @Value 는 어떤 문제를 풀고, 어디까지 써야 할까 @Value 는 외부 설정에서 단일 값을 읽어올 때 가장 간단합니다. 예를 들어 API 기본 URL, 타임아웃, 기능 플래그처럼 "몇 개 안 되는 설정"을 빠르게 주입하는 데 적합합니다. application.yml , application.properties , 환경 변수, JVM 옵션, 커맨드라인 인자처럼 스프링 Environment 에 올라온 값이라면 대부분 읽을 수 있습니다. 반대로 관련 설정이 여러 개로 늘어나기 시작하면 @Value 의 약점이 드러납니다. 문자열 키가 서비스 클래스 곳곳에 흩어지고, 리스트나 중첩 구조를 다루려면 표현식이 복잡해지며, 설정 검증도 분산됩니다. 그래서 실무에서는 보통 다음 기준으로 나눕니다. 설정 1~2개를 빠르게 읽는다: @Value 하나의 도메인 설정을 묶어서 다룬다: @ConfigurationProperties 중요한 점은 @Value 가 "간단해서 무조건 좋은 방식"은 아니라는 것입니다. 단순한 ...

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

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