- 서버 어플리케이션은 최소 2개이상의 환경(개발 환경, 실제 배포 환경)에서 동작해야한다.
- 이에 환경변수를 설정하여 애플리케이션 외부에서 환경 정보를 주입하여 적절하게 구동 할 수 있다.
웹 어플리케이션 기본 설정
- 스프링부트에서는 @EnableWebMvc 애너테이션을 명시적으로 선언하지 않아도, 의존성에 spring-boot-starter-web이 추가되어 있으면 웹 어플리케이션 기본 설정을 진행 할 수 있다.
가. WebMvcConfigurer를 사용한 설정
- WebMvcConfigurer 인터페이스에는 여러가지 default 메서드들이 선언되어 있다.
- 메서드의 이름은 머리말과 기능으로 조합되어있다. 머리말은 add, extend로 시작하는 확장기능 그리고 configure로 시작하는 교체기능이 있다.
1. configurePathMatch()
- DispatchServlet은 사용자 요청을 컨트롤러에 매핑하기 위하여 HandlerMapping 컴포넌트에 의존한다.
- configurePathMath()는 PathMatchConfigurer를 인자로 받는데 이는 사용자 요청을 매핑하는 세부 설정을 할 수 있는 메서드를 제공한다.
@Configuration
public class WebServerConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(true)
.addPathPrefix("/v2", HandlerTypePredicate.forAnnotation(RestController.class, Controller.class))
.setPathMatcher(new AntPathMatcher())
.setUrlPathHelper(new UrlPathHelper());
}
}
- setUserTrailingSlashMatch : /v2/hotels/ 처럼 '/'로 끝나는 url을 /v2/hotels 와 똑같이 처리하게 해준다.
- addPathPrefix : uri의 머리말 (/v2)를 설정할 수 있게 해준다.
인자를 2개 받는데 첫번째 인자는 머리말을 설정하며, 두번째 인자는 머리말을 선정할 대상을 정한다.
위 예에서는 머리말을 "/v2"로, 대상을 @RestController와 @Controller 로 정의된 모든 컨트롤러에 일괄 적용한다.
2. configureContentNegotiation()
- 스프링에서 데이터를 표현하는 기능을 뷰(View)라 하며 ViewResolver 구현체에 따라 데이터를 HTML, JSON, XML 등 다양한 형태로 표현할 수 있다.
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.parameterName("contentType")
.ignoreAcceptHeader(true)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
}
- URI 파라미터로 contentType을 받아와 해당하는 미디어타입으로 응답하게 해준다.
3. configureAsyncSupport()
- 비동기 서블릿 기능을 설정 할 때 사용한다.
- 전통적인 동기식 서블릿은 사용자의 요청을 받아 처리하고 응답하는 과정을 하나의 스레드에서 처리하지만,
비동기 서블릿은 별도의 스레드 풀을 사용하는 구조를 가진다.
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setThreadNamePrefix("Async-Executor");
taskExecutor.setCorePoolSize(50);
taskExecutor.setMaxPoolSize(100);
taskExecutor.setQueueCapacity(300);
taskExecutor.initialize();
configurer.setTaskExecutor(taskExecutor);
configurer.setDefaultTimeout(10_000L);
}
4. configureDefaultServletHandling()
- 사용자 요청을 매핑할 적합한 서블릿 설정이 없으면 기본 서블릿을 사용해 요청을 매핑하여 처리할 수 있다.
- DefaultServletHandlerConfigurer 인자를 받아, 이 클래스에서 제공하는 enable() 메서드를 사용하면 기본 서블릿이 동작한다.
5. addInterceptors()
- 사용자의 요청과 응답을 가로채 추가적인 작업을 할 수 있도록 해준다.
6. addResourceHandlers()
- 정적파일이 저장되는 resources 폴더와 사용자가 요청하는 디렉터리의 구조가 다를 때 이 메서드를 사용하여 경로를 변경할 수 있다.
7. addCorsMappings()
- CORS(Cross Origin Resource Sharing) 설정을 할 수 있다.
- CORS : 출처가 다른 리소스들을 공유하는 것
8. addViewControllers()
- 컨트롤러 클래스 없이 해당 설정만으로도 사용자의 요청과 뷰 이름을 매핑 할 수있다.
9. configureHandlerExceptionResolvers, extendsHandlerExceptionResolvers
- HandlerExceptionResolver를 통해 서블릿에서 발생한 모든 예외에 대한 처리를 할 수 있다.
10. addFormatters()
- 데이터를 변환하여 특정 대상 객체에 할당하는 데이터 바인딩 기능을 확장 할 수 있게 해준다. (ex. @PathVariable, @RequestParam ...)
11. addArgumentResolvers()
- 사용자의 HTTP 요청에서 필요한 정보를 뽑아 특정 대상 객체로 변환할 수 있게 해준다.
12. addReturnValueHandlers()
- 컨트롤러가 리턴하는 객체를 변환할 수 있게 해준다.
13. configureMessageConverter(), extendMessageConverters()
- @ResponseBody와 @RequestBody 애너테이션에 적용된 대상을 특정 포맷으로 변경해준다.
나. DispatcherServlet 설정
- DispatcherServlet은 사용자의 요청을 적절한 핸들러 메서드에 매핑시켜주는 역할이다.
- 스프링의 IoC컨테이너에 의해 빈들을 의존받으려며 DispatcherServlet 또한 빈으로 생성되어야 하지만 DispatcherServlet은 어떠한 스테레오 타입 애너테이션도포함하지 않는다.
- DispatcherServlet은 ApplicationContext를 직접 주입받아 getBean 메서드를 통하여 스프링 빈을 가져온다.
- 다음은 DispatcherServlet에서 제공하는 설정가능한 기능들이다.
1. MultipartResolver
- HTTP를 통하여 클라이언트가 서버로 바이너리 파일을 전송할 때 multipart 타입으로 보낸다. 이 Resolver는 이러한 멀티 파트 요청을 처리하는 기능이 정의되어있다.
2. ThemeResolver
- 스프링 웹 MVC 프레임워크의 뷰를 사용 할 때 테마에 따라 지정된 기준으로 사용자에게 화면을 보여줄 수 있도록 테마를 처리하는 기능이 정의되어있다.
3. LocaleResolver
- 자바는 언어와 위치 정보를 표현하는 java.util.Locale 클래스를 제공하는데, 이 Resolver는 국제화 기능을 사용하기 위해 Locale 정보를 처리할 수 있는 기능이 정의되어있다.
HttpMessageConverter와 REST-API 설정
- @ResponseBody나 @RequestBody 애터네이션이 선언된 대상은 HttpMessageConvert가 마셜링/언마셜링(전송에 적합한 데이터 형식으로 Encode/Decode 하는 행위) 실행한다.
1. HttpMessageConverter 설정
- 클라이언트의 AcceptHeader 값이 'application/json'이면 JSON 형식으로, 'application/xml'이면 CML 형태로 메세지를 응답해야한다.
- 변화에 유연한 애플리케이션이 되기 위해, 비즈니스 로직에 변경없이 사용자의 요청에 따라 다양하게 응답할 수 있어야 한다.
- WebMvcConfigurer의 HttpMessageConvert 설정을 통해 이러한 처리를 할 수 있다.
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(new MappingJackson2XmlHttpMessageConverter());
}
- 프레임워크에서 기본 지원하는 List<HttpMessageConverter>에 사용자가 직접 위와 같은 처리를 진행하는 메세지 컨버터들을 추가할 수 있다.
2. ObjectMapper와 스프링 빈을 이용한 애플리케이션 설정
- ObjectMapper 클래스는 역직렬화할수 있는 readValue(), 직렬화할 수 있는 writeValue() 메서드들을 제공한다.
- 위의 HttpMessageConverter 클래스 내부에는 ObjectMapper 객체들이 포함되어 있는데, 이 객체는 직렬화/역직렬화 과정에서 DTO객체의 속성에 따라 제외하거나 포함하는 여러가지 설정 옵션을 제공한다.
- 하지만, 스프링부트에서는 ObjectMapper 설정을 자동으로 해주는 JacksonAutoConfiguration을 제공하기에 사용자가 이러한 속성을 변경하려면 빈을 따로 등록해 주어야 한다.
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
return objectMapper;
}
- 이후 실행 결과의 차이를 확인해보자.
## ObjcetMapper 설정 전
{
"originalPrice": "130.00",
"hotelRoomType": "double",
"roomNumber": {
"buildingCode": "ocaen",
"roomNumber": 1234
},
"reservations": [],
"id": "16716072471964678"
}
## ObjcetMapper 설정 후
{
"originalPrice": "130.00",
"hotelRoomType": "double",
"roomNumber": {
"buildingCode": "ocaen",
"roomNumber": 1234
},
"id": "16716070107881747"
}
- NON_EMPTY 속성을 주입한 결과, 빈 리스트였던 reservations이 빠진 것을 확인 할 수 있었다.
'공부 > Spring Boot' 카테고리의 다른 글
[Spring Batch] 01. Spring Batch 기본 개념 (0) | 2024.11.13 |
---|---|
[스프링 부트 공부 일지] 4. 웹 어플리케이션 서버 구축하기 (2) (0) | 2022.12.22 |
[스프링 부트 공부 일지] 3. 스프링에서 REST API 개발하기 (3) (0) | 2022.12.17 |
[스프링 부트 공부 일지] 3. 스프링에서 REST API 개발하기 (2) (0) | 2022.12.16 |
[스프링 부트 공부 일지] 3. 스프링에서 REST API 개발하기 (1) (0) | 2022.12.16 |