FeGwan-Training / FeGwan

0 stars 0 forks source link

Chapter 4. 스프링 웹 MVC 개요 #37

Closed HoFe-U closed 1 year ago

HoFe-U commented 1 year ago

Discussed in https://github.com/FeGwan-Training/FeGwan/discussions/36

Originally posted by **HoFe-U** July 21, 2023 # Chapter 4. 스프링 웹 MVC 개요 ## 4.1 HTTP 프로토콜 > 모든 웹 애플리케이션은 HTTP(HyperText Tranfer Protocol) 을 사용하여 서비스를 제공하는데. 이를 먼저 알아보고 어떻게 Spring 에서 이루어지는지 알아보려고한다 > image 먼저 상단의 그림을 보면 데이터 혹은 기능을 요청하는 쪽이 클라이언트(사용자) 데이터를 제공하거나 기능을 처리하는 쪽을 서버라고 한다. 해당 client 와 서버에서의 데이터를 주고 받는 특정스팩중의 하나가 **HTTP** 인것이고 **http://httpbin.org/** --- 상단의 사이트를 통해 Request 를 보내게 되면 해당 요청은 아래와 같이 전송되게 된다. **Client Request** ``` curl -X GET "http://httpbin.org/get" -H "accept: application/json" ``` → 해당 내용은 Client 가 보내는 내용이 포함되어 있는것이다.(정확히 말하면 HTTP version 도 포함) 위의 내용도 크게 보면 **요청 라인** 과 **헤더** 2가지로 구분되어져 보내지는것을 알 수 있다. 그럼 해당 내용을 받는 클라이언트는 어떤 응답을 보내줄까?? **Server Response** 서버가 해당 응답 메세지를 반환하게 되면 **상태라인 , 헤더, 메시지 바디** 형태로 구분되어 출력된다. ``` **Response Body** { "args": {}, "headers": { "Accept": "application/json", "Accept-Encoding": "gzip, deflate", "Accept-Language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,th;q=0.6", "Host": "httpbin.org", "Referer": "http://httpbin.org/", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-64b64950-628d942a315340402ca029a9" }, "origin": "1.252.13.218", "url": "http://httpbin.org/get" } **Response Headers** access-control-allow-credentials: true access-control-allow-origin: * connection: keep-alive content-length: 524 content-type: application/json date: Tue, 18 Jul 2023 08:12:31 GMT server: gunicorn/19.9.0 **Code 200 OK** ``` 위의 내용을 보면 HTTP 메시지는 요청 메시지와 응답 메시지로 나눌 수 있는것을 알 수 있다. > 상단의 Client 와 Server 가 어떤식으로 요청과 응답을 받는지를 확인했는데 이제 이를 토대로 어떠한 메소드들이 있고 상태코드가 어떤식으로 이루어져 있는지 확인해 보려고한다. > HTTP 리소스는 HTTP 요청 대상을 의미하는데 이는 HTML 같은 문서나 이미지 같은 멀티미디어 파일이 될 수 도 있다. 각 리소스는 **URI(Uniform Resource Identifier)** 로 구분되어지고 해당 값에는 쿼리 스트링(Query String) 이 첨가 될 수있다. ### HTTP 상태 코드 해당 상태코드를 간략하게 표현한다면 아래와 같다. - 1xx : 임시 응답을 의미하는데 클라이언트의 요청은 성공적으로 받았고 서버의 프로세스는 계속해서 작업하는것을 의미한다. 응답 메시지는 메시지 바디없이 상태 라인과 헤더로만 구성되어 있다. - 2xx : 성공을 의미한다. 일반적으로 클라이언트 요청도 성공적으로 받았고 프로세스가 정상적으로 처리되었음을 의미한다. - 3xx : 클라이언트 요청을 완전히 처리하는데 추가적인 작업이 필요함을 의미한다. 일반적으로는 클라이언트가 요청한 리소스가 다른 위치로 옮겨져서 추가작업이 필요할때 쓰여진다. - 4xx : 클라이언트가 전송한 요청 메시지에 에러가 있음을 의미한다. 요청 메시지에 문법이 잘못되었거나(400 Bad Request), 인증 혹은 인가되지 않은 리소스에 요청하는 경우(401 Unauthorized, 403 Forbidden) 등이 있다. - 5xx : 클라이언트가 전송한 요청을 처리하는 도중 서버가 정상적으로 처리하지 못하고 에러를 발생할 때 사용하는 대분류 코드. **좀더 자세한 상태코드를 파악하고 싶으면 하단의 링크를 확인하기 바란다.** [[HTTP 상태 코드 - HTTP | MDN](https://developer.mozilla.org/ko/docs/Web/HTTP/Status)](https://developer.mozilla.org/ko/docs/Web/HTTP/Status) ### HTTP 특징 **version** - HTTP/1.0 : 가장 기본적으로 많이 사용되는 버전 - HTTP/1.1 : keep-alive 와 파이프 라이닝 기능을 제공하고, 청크(chunk) 응답을 제공한다. - HTTP/2.0 : 구글이 만든 SPDY 프로토콜을 정식으로 채용하여 적용 - SPDY 참고 [[SPDY는 무엇인가?](https://d2.naver.com/helloworld/140351)](https://d2.naver.com/helloworld/140351) **HTTP 2가지 특성** 1. 비연결성(Connectionless) - 비연결성이란 HTTP 프로토콜이 서버와 클라이언트 사이에 커넥션을 유지할 필요 없이 데이터를 송수신 할 수 있음을 의미합니다. 2. 무상태(Stateless) - 해당 프로토콜은 이전 요청에 의존하지 않는다. 즉 클라이언트가 서버에 여러 요청을 해도 각 요청은 각각 독립적으로 처리가 된다. 하지만 이것의 가장 큰 문제는 이전 상태를 기억해야 하는 **인증과 인가 기능**이다. 그래이 이를 기억하기 위해 쿠키나 세션에 대한 스펙을 제공한다. ## 4.2 Spring Web MVC Framework > Java EE 는 자바언어를 통해 엔터프라이즈 애플리케이션을 만들 수 있는 플랫폼인 동시에 표준 스펙의 집합인데 이는 serlvet 의 HTTP 프로토콜을 사용하여 서버용 스펙을 사용하고 있다. > 이에따라 Servlet 부터 하나씩 보고자 한다 ### Servlet Java 언어로 만들어진 웹 기술중 하나인데 Java EE 기반에서 동작을 한다. **version** - 서블릿 3.0 : 비동기(asynchronous) 서블릿 기능 지원 - 서블릿 3.1 : 비차단(non-blocking) 방식의 IO 기능 지원 - 서블릿 4.0 : HTTP 2.0 기반의 기능 지원 image - Servlet은 HTTP 프로토콜을 기반으로 동작하며, 클라이언트로부터 HTTP 요청 메시지를 받아들이고, 서버 측의 자바 코드를 실행하여 응답 결과를 생성합니다. - Servlet은 HttpServlet 클래스를 상속받아서 작성하며, HTTP 프로토콜에 맞는 처리를 할 수 있습니다. ### Servlet Container (WAS) Servlet 의 생명주기를 관리하는 역할을 한다. 대표적으로는 Tomcat 이 있다. **그럼 우리도 Servlet 으로 개발하나???** ⇒ 아니다 전통적인 서블릿 애플리케이션은 데이터를 다루는 로직과 HTML 코드까지 하나의 클래스에 서로 얽혀 있기때문에 개발자가 의도하지 않는 다른 변경이 일어날 수 있다. 이를 Spring Web MVC 는 효율적으로 웹 애플리케이션을 개발할 수 있는 방법을 제공한다. ### 4.2.1 MVC 패턴 > 스프링 웹 MVC 는 MVC 패턴으로 구현되는 프레임워크이다. 그래서 해당 프레임워크 이름도 MVC 패턴에서 따왔고 해당 역할을 Model , View , Controller 세 가지로 분류하여 처리를 한다. 이제 이를 세부적으로 분리해서 알아보고자 한다. > **MVC 의 의미** - Controller : 사용자의 요청을 받아 어떻게 처리할지 결정하는 역할로 사용자의 역할을 분석하는 역할을 맡는다. 데이터를 처리하는데 필요한 HTTP 쿼리 스트링이나 헤더, 바디 같은 정보를 HTTP 메세지에 파싱하여 추출하여적절한 Model 이나 요청에 적합한 View 에 전달하는 역할을 한다. - Model : 컨트롤러에 전달받은 사용자 요청 데이터를 가공하거나 데이터 저장소에서 데이터를 처리하는 작업을 담당한다.( 즉 비즈니스 로직을 처리하는 역할) - View : 사용자에게 응답하는 화면을 담당한다. 사용자가 요청한 Accept 헤더에 적합한 MIME 문서를 전달. - MIME : MIME는 전자 우편을 위한 인터넷 표준 포맷이다. 전자 우편은 7비트 ASCII 문자를 사용하여 전송되기 때문에 8비트 이상의 코드를 사용하는 문자나 이진 파일들은 MIME 포맷으로 변환되어 SMTP로 전송된다. **MVC 패턴이 적용된 서블릿의 구조는 아래와 같다.** image - 위와 같이 처리하면 기능에 따라 클래스는 분리했지만 클래스간의 의존성 문제는 여전하다. - new 키워드를 사용해서 객체를 직접 선언하여 클래스 사이에 강한 의존성이 생긴다. 이를 통한 문제도 Spring MVC 구조에서는 해결이 가능하다 **Spring MVC 를 적용시킨 구조는 아래와 같다** image - 위와 같이 처리하면 Spring 의 장점인 IoC Container 를 제공하여 내부에 스프링 코어 프로젝트와 스프링 컨테이너를 포함하므로 의존성 문제를 해결 할 수 있다. - 개발자가 스프링 빈을 설정하기위해서는 스테레오 타입을 적절하게 쓰면되는것이다. - 이것 외에도 MVC 프레임워크는 몇 가지 주요 컴포넌트를 제공하는데 제일 대표적인게 상단에 나와있는 DispatcherServlet 이다. - Front Controller Pattern 으로 하나의 Servlet 에서 전체기능을 제어하는 역할을 하는것이다. - 즉 Spring MVC 를 사용하면 직접적인 비즈니스로직개발과 @Controller 부분을 신경쓰면 된다 ( 보라색으로 칠해진 부분만 개발하면된다.) **진행순서** 1. DispatcherSerlvet(Front Controller) 가 우선적으로 모든 요청을 처리 2. HTTP 메시지의 요청 라인에 요청된 리소스에 따라 어떤 컨트롤러 스프링 빈이 처리할지 판단하고 적절한 컨트롤러 스프링 빈으로 사용자 요청을 전달 3. 컨트롤러 스프링 빈은 서비스 기능을 구현한 @Controller 를 제외한 스테레오 타입을 빈들을 호출한다. 4. 컨트롤러 클래스는 ModelAndView 객체를 이용하여 UI를 처리 할 수 있는 View 를 찾아서 3에서 리턴된 데이터와 함께 전달이 가능 5. 선택된 View 는 전달받는 데이터를 매핑하여 사용자가 요청한 대로 응답 데이터를 생성하여 해당 응답데이터를 DispatcherSerlvet 으로 다시 전달한다. **자 이제 우린 DispatcherSerlvet 이 얼마나 중요한 기능을 하는지 알 수 있다.** 아까 우리가 대표 컴포넌트가 DispatcherSerlvet 이 있다고 했는데 사실 이것 이외에도 - HanlderMapping, HandlerAdapter, ModelAndView, ViewResolver, DispatcherServlet 이 있다. 그런데 이중에서 가장 중요한게 DispatcherServlet 이 제일 핵심이되는 친구여서 이를 먼저 한번스근하게 보자. ### 4.2.2 DispatcherServlet > 앞서 말했다싶이 Front Controller Pattern 으로 디자인 되어 있는게 DispatcherServlet 인데 즉 문지기 역할을 한다고 보면되는데 이제 이를 새부적으로 하나씩 뜯어 보고자 한다. > **DispatcherServlet 의 동작순서를 보면 아래와 같다..** image 1. Client 의 요청은 HTTP 요청 메세지는 가장 먼저 `DispatcherServlet` 이 받아 처리한다. 2. `DispatcherSerlvet` 은 요청 메세지의 요청 라인과 헤더들을 파악한 후 어떤 컨트롤러 클래스의 어떤 메서드로 전달할건지를 `HanlderMapping` 컴포넌트의 메서드를 사용하여 파악. 3. `DispatcherServlet` 은 사용자 요청을 처리하기에 적합한 컨트롤러 클래스에 HTTP 요청을 전달하기위해 전달하는 역할을 하는 `HandlerAdapter` 에 전달 4. HTTP 요청을 받은 `HanlderAdapter` 가 해당 컨트롤러 클래스에 클라이언트 요청을 전달 - 컨트롤러 클래스에서 이제 비즈니스 로직등을 실행한다. 우리가 설정한 `@Service , @Component , @Repository` 등을 실행 5. 컨트롤러 클래스는 이 전달받은 데이터를 어떤 뷰로 전달할건지를 결정하여 뷰와 뷰에 매핑할 데이터를 `ModelAndView` 객체에 포함하여 `HandlerAdapter` 에서 `DispatcherServlet` 으로 보낸다. 6. `DispatcherServlet` 은 처리할 뷰 정보를 `ViewResolver` 에 확인한다. 7. `DispatcherServlet` 은 View 에 데이터를 전달하고, `View` 는 데이터를 `HTML,XML` 등 적합한 포멧으로 변경한다 그리고 다시 `DispatcherServlet` 으로 전달한다. 8. 이에대한 응답을 `DispatcherSerlvet` 이 클라이언트에게 전달한다. --- 위의 순서를 보게되면 DispatcherServlet 은 컴포넌트에 정보를 질의하거나 각자 역할을 담당하는 컴포넌트에 사용자 요청을 전달한다. 이렇게 보면 DispatcherServlet 확실히 요청에대한 중추의 역할을 DispatcherSerlevt 이하는것을 볼수있다. ### 4.2.3 서블릿 스택과 스레드 모델 > Spring Web Framework 는 servlet stack 과 리액트 모델을 적용한 reactive stack 이 있다. 이둘에 대해서 간단하게 살펴보려고한다. > **servlet stack vs. reactive stack** - 둘의 차이점은 동기식 프로그래밍과 비동기식 프로그래밍에 있는데 일반적으로 동기식 프로그래밍으로 애플리케이션을 개발하는 경우에는 서블릿 스택으로 구성하고, 비동기식 프로그래밍으로 개발하는 경우에는 리액티브 스택으로 구성. - 그래서 동기? 비동기? 가 뭔데 - 동기식 프로그래밍 ⇒ 기능(함수) 의 종료 시점을 정확하게 알 수 있는 방식을 동기식 프로그래밍이라고 한다. - 다른 객체의 메서드를 실행하고 그 결과를 받아 나머지 일을 처리할 수 있는 경우 동기식 프로그래밍 - 비동기식 프로그래밍 ⇒ 기능의 종료 시점을 알 수 없는 방식을 비동기식 프로그래밍이라고 한다. - 메서드의 종료시점을 알수 없기때문에 콜백 형태의 함수를 전달하는 방식으로 프로그래밍하는경우 실행한 메서드가 종료되면 전달된 콜백 함수를 전달하는 방식으로 프로그래밍된다. - 콜백함수에 대한 event 등을 queue 로 등록 해서 관리할 수 있다. **그럼 위의 Servlet Stack 에서의 Thread 관리를 Spring 은 어떻게 할까?** - WAS 가 스레드를 효율적으로 관리하고자 스레드들을 관리하는 스레드 풀에 포함한다. - 사용자가 요청부터 응답까지 하나의 스레드에서 모든 작업이 실행 - 사용자 요청과 스레드 생명주기가 일치하므로 쉽게 개발 및 운영할 수 있다. ⇒ 위의 글들을 하나씩 뜯어보자. 1. WAS 는 Thread Pool 을 관리한다. - 해당 Thread Pool 은 WAS 가 시작되면 초기화되고 종료될때 정리된다. - 사용자의 요청마다 스레드를 새로생성하는 방법은 비용이 비싸므로 미리 만들어진 스레드를 재사용하는 스레드 풀로 사용자의 요청들을 처리한다. - 하지만 위의 것들도 무적은 아니 요청이 너무많아져서 스레드가 고갈될경우 애플리케이션이 시간내에 응답을 하지못하거나 프로세스가 죽을수도 있다. 2. 클라이언트에서 HTTP 요청을 받고 HTTP 응답을 하는 일련의 주기가 스레드의 생명주기와 일치 - WAS 는 Thread Pool 을 제공하여 Thread Pool 에서 하나의 Thread 를 할당받아 요청을 처리 - 종료시 Thread 를 반납을하는데 이러한 방식을 **Thread Per Request** 모델이라고 한다. 3. 하나의 스레드에서 모든 객체의 메서드들이 실행되므로 멀티 스레드 프로그래밍을 하지 않아도 됨 - 즉, 개발자가 직접 Thread 를 다루지 않아도 된다. - 디버깅이 시워서 서비스의 운용이 편하다. ### 4.2.4 스프링 부트 설정 > 일단 Spring Boot FrameWork 에서는 내부에 embedded WAS 를 포함하고 있기 대문에 외부의 WAS 없이도 혼자서 실행이 가능하다. 종류는 Tomcat, Jetty, Undertow 가 포함되어 있다. 위와같이 내장되어있는것들을 제외하고도 설정을 그렇게 많이 하지않아도 된다. 이제 어떤 설정들을 하면 되는지 알아 보고자 한다. > 일단 Spring Boot 설정에서는 총 2가지만 진행하면 된다. 1. spring-boot-starter-web 의존성을 추가한다.(pom.xml) 2. [[application.properties](http://application.properties/)](http://application.properties) 에개발자가 필요한 설정을 하면된다. 위의 2가지만 지킨다면 spring boot 설정을 완료할 수 있다. --- **spring-boot-starter-web** ```xml org.springframework.boot spring-boot-starter-web ``` **위처럼 dependency 를 추가하게 된다면 무슨일이 일어날까?** - [`[**WebMvcAutoConfigure.java**](http://webmvcautoconfigure.java/)`](http://WebMvcAutoConfigure.java)가 실행되면서 자동으로 스프링 웹 애플리케이션의 주요 컴포넌트를 설정 우리가 SpringFramework 를 사용해서 개발했을때 **`@EnableWebMvc`** 의 설정도 포함되어있다고할 수있다. - 그럼 어떤 기능들을 제공할까?? 1. View Resolvers 설정: **`WebMvcAutoConfiguration`**은 기본적으로 Thymeleaf 또는 FreeMarker와 같은 템플릿 엔진을 사용하여 뷰를 해석하는 뷰 리졸버를 설정합니다. 2. 정적 리소스 처리: 정적 리소스(예: CSS, JavaScript, 이미지 파일 등)의 제공을 위해 **`ResourceHandler`**를 등록합니다. 3. Message Converters 설정: **`WebMvcAutoConfiguration`**은 JSON, XML 등의 다양한 데이터 형식을 처리하는 메시지 컨버터를 설정합니다.(`**HttpMessageConverter**`) 4. 기본적인 웹 MVC 구성: 기본적인 **`RequestMappingHandlerMapping`**, **`RequestMappingHandlerAdapter`**, **`ExceptionHandlerExceptionResolver`** 등의 웹 MVC 구성을 제공합니다. 5. HTTP 메서드 지원: **`WebMvcAutoConfiguration`**은 HTTP 메서드에 따른 요청 처리를 지원합니다. 6. 데이터 바인딩 설정: 폼 데이터를 자바 객체로 바인딩하는데 사용되는 **`DataBinder`** 설정을 제공합니다. 7. 기타 설정: 인터셉터, CORS(Cross-Origin Resource Sharing) 등의 기타 웹 MVC 관련 설정을 자동으로 구성합니다. ⇒ 위의 자동설정값이 끝나면 DispatcherServletAutoConfiguraion 이 DipatcherServlet 객체를 생성 --- **applicaiton.properties** ```java server.port=8090 server.tomcat.connection-timeout=30s server.tomcat.threads.max=100 server.tomcat.threads.min-spare=100 server.tomcat.accesslog.enabled=true server.tomcat.accesslog.suffix=log server.tomcat.accesslog.prefix=access_log server.tomcat.accesslog.rename-on-rotate=true ``` [[application.properties](http://application.properties/)](http://application.properties) 는 key-value 형식으로 키와 벨류를 구분하기 위해 `=` 문자를 사용한다. 또한 계층구조를 구분하기 위해 `.` 을 통해 계층을 구분한다. 위의 설정은 applicaiton 이구동시에 port 번호와 tomcat관련 설정들이 들어있다. - **server.tomcat.connection-timeout** - 서버와 클라이언트가 connection 을 연결하고 해당 시간 내에 응답을 하지않으면 커넥션을 끊는다. - **server.tomcat.threads.max, server.tomcat.threads.min-spare** - 톰켓의 thread pool 의 max. 와 min 을 설정한다. - 위의 값들을 둘다 100으로 설정한 이유는 ⇒ 두개의 설정 값이 다르면 서버에 부하가 높을 때는 최대값까지 스레드가 생성되지만 부하가 낮을 때는 최소값까지 스레드 가 줄어든다. **자 그러면 런타임 도중에 필요한 스레드를 생성하는 시간과 리소스 비용이 높기 때문에 두 값을 같이 사용할때가 많다.** - **server.tomcat.accesslog.enabled** - 톰켓의 엑세스 로그 사용을 허용 - 기본값이 false 이므로 로그가 필요하면 반드시 변경을 해야함. - **server.tomcat.accesslog.suffix , server.tomcat.accesslog.prefix** - 톰켓 엑세스 로그 이름 변경 - **server.tomcat.accesslog.rename-on-rotate** - 날짜가 지난 톰캣 엑세스 로그에 timestamp 를 추가하여 로그 파일 이름을 변경 ## 4.3 REST-API 설계 > 컴포넌트 시스템 간 기능을 통합하는 경우 가장 많이 고려하는 API 인터페이스가 REST-API 인데 쉽게 빠르게 개발할 수 있는 장점을 가지고 있지만 일관성이 없다면 기능 개발보다 다른 일에 더 시간을 많이 소모하기 때문에 일관성 있고 잘 설계된 REST-API 필요하다. > **REST-API 구성 요소** - 리소스(resource) - 리소스(자원)은 HTTP URL 로 표현한다. - 행위(verb) - 리소스에 대한 행위는 HTTP method 로 표현한다. - 일반적인 CRUD 표현가능 - 표현(represenatation) - 행위 내용을 HTTP 메세지 내용으로 표현 - 메시지 포멧은 JSON 을 사용 **REST-API 기본 규칙** - 리소스 이름은 가능하면 동사보다 명사를 사용한다. - 리소스는 계층적 구조를 가질 수 있다. 계층 관계를 가지므로 복수 형태를 사용한다. - 리소스의 행위는 GET, POST, PUT ,DELETE 를 기본으로 하고 때에 따라 PATCH 를 사용 ### 4.3.2 REST-API 특성과 설계 > REST-API 설계 및 구현하는 세 가지 특성을 이해하면 보다 견고한 애플리케이션 서버를 만들 수 있다. 첫번째는 무상태성,두번째는 일관성, 세번째는 멱등성이다. > 1. 무상태성 - REST-API 는 HTTP 프로토콜을 사용하는 API 이다. 이때문에 이전에 설명했던 무상태성을 그대로 이어받을 수 있는 것이다. - 이 특성을 이용하여 웹 서비스의 고가용성을 구축하면 서비스 도중에도 서버를 증설하거나 축소할수 있다. 2. 일관성 - API 를 설계할 때 같은 형태의 응답 메세지나 일관된 규칙으로 만들어진 HTTP 상태 코드를 정의 해야한다. - 일관성이 결여된 REST-API 는 개발자가 예측하기도 어렵고 사용하기도 어렵다. 만약 일관성이 없다면 API를 개발자가 예측하기도 어렵고 사용하기도 어렵다. 3. 멱등성 - $f(f(x)) == f(x)$ 라는 공식인데 함수를 여러 번 적용한 결과가 같음을 의미한다. - REST-API 의 기능이 POST, GET, DELETE, PUT 인데 해당 값 중 GET 을 호출할때 리소스의 상태는 변경되지 않는다. - 즉 데이터를 변경하지 않는 GET 메서드는 아무리 실행해도 리소스 상태가 변경되지 않는다. 만약 GET 으로 데이터의 변경이 일어난다면 REST-API 기본 원칙을 위배한것이다. - Http Method 중 POST 동일한 API 를 여러 번 호출하면 호출한 횟수만큼 데이터를 만들면 되므로 멱등성을 갖출 필요가 없기때문에 제외된다. - 즉 안전한 메서드인 GET 과 데이터를 변경하는 PUT, DELTE 는 멱등성이 있어야한다. ## 4.4 간단한 REST-API 예제 > 스테레오 타입 에너테이션들의 기능과 REST-API 에 대해 알아보고 다루어 보자. > **스테레오 타입** - @Controller - 사용자 요청을 받아 내부 로직으로 전달하는 컨트롤러 클래스에 적용한다. 사용자의 요청 메세지를 검증하는 로직을 포함. - @Service - DDD 에서 사용자의 유스 케이스나 단위로 구현된 메서드를 포함하는 클래스. - 데이터베이스를 사용하고 있다면 트랜잭션 단위로 분리된 메서드를 포함하는 클래스에서 사용 - @Component - 애플리케이션 내부에서 공통에서 사용하는 기등들을 정의할 때 사용 - REST-API를 호출하는 클래스나 공통화 모듈 같은 공통 로직을 포함하는 클래스에서 사용 - @Repository - 데이터 저장소에서 데이터를 생성, 조회, 수정, 삭제하는 메서드에 사용 ### 4.4.1 @ResponseBody 와 HttpMessageConverter > `@Controller` 에 `@ResponseBody` 선언된 메서드가 리턴하는 객체는 스프링 프레임워크에 설정한 MessageConverter 중 적합한 converter 가 json 메세지로 마셜링(⇒serialize) 한다. > **HttpMessageConverter** - 종류 1. **MappingJackson2HttpMessageConverter**: JSON 형식의 데이터를 처리합니다. Jackson 라이브러리를 사용하여 Java 객체와 JSON 데이터 간의 변환을 수행합니다. 2. **MappingJackson2XmlHttpMessageConverter**: XML 형식의 데이터를 처리합니다. Jackson 라이브러리를 사용하여 Java 객체와 XML 데이터 간의 변환을 수행합니다. 3. **StringHttpMessageConverter**: 문자열 데이터를 처리합니다. 주로 텍스트 기반의 데이터를 처리할 때 사용됩니다. 4. **FormHttpMessageConverter**: 폼 데이터를 처리합니다. 폼 데이터를 **`application/x-www-form-urlencoded`** 또는 **`multipart/form-data`** 형식으로 처리합니다. 5. **ByteArrayHttpMessageConverter**: 바이트 배열 데이터를 처리합니다. 주로 이미지 또는 다른 이진 데이터를 처리할 때 사용됩니다. 6. **ResourceHttpMessageConverter**: **`org.springframework.core.io.Resource`** 객체를 처리합니다. 파일 다운로드 등에 사용될 수 있습니다. 7. **Jaxb2RootElementHttpMessageConverter**: JAXB를 사용하여 XML 데이터를 처리합니다. 8. **AtomFeedHttpMessageConverter**: Atom 피드 데이터를 처리합니다. 9. **RssChannelHttpMessageConverter**: RSS 채널 데이터를 처리합니다. ⇒ 위 같은 구현클래스들 중에 **HttpMessageConverter** 에 있는 `canRead(), canwrite()` 은 헤더값을 MediaType 으로 변환하여 적절한 **HttpMessageConverter** 객체를 찾아낸다. ### 회고 + 기본 REST-API 의 흐름을 다시 돌아보는 기회를 가진것같았다. + servlet stack vs. reactive stack 쪽에서 reactive stack 부분에 대한 설명이 blocking , non-blocking 부분 말고는 좀 부족한것같았다.