✅ Spring MVC
Spring MVC, 많은 다른 웹 프레임워크와 마찬가지로 중앙 컨트롤러 패턴을 기반으로 설계되었다. 여기서 중앙 Servlet 인
DispatcherServlet
은 요청 처리를 위한 공유 알고리즘을 제공하며 실제 작업은 구성 가능한 대리 구성 요소에 의해 수행된다. ✅ 클라이언트가 요청을 보내면?
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F96147481-52ac-444d-a421-ace525edb762%252FUntitled.png%3Ftable%3Dblock%26id%3D9ff7c955-f82d-42de-be5d-6392903c8641%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
프레젠테이션 계층
- 브라우저상의 웹 클라이언트의 요청 및 응답을 처리
- 서비스계층, 데이터 엑세스 계층에서 발생하는 Exception을 처리
- @Controller 어노테이션을 사용하여 작성된 Controller 클래스가 이 계층에 속함
서비스 계층
- 애플리케이션 비즈니스 로직 처리와 비즈니스와 관련된 도메인 모델의 적합성 검증
- 트랜잭션 관리
- 프레젠테이션 계층과 데이터 엑세스 계층 사이를 연결하는 역할로서 두 계층이 직접적으로 통신하지 않게 함
- Service 인터페이스와 @Service 어노테이션을 사용하여 작성된 Service 구현 클래스가 이 계층에 속함
레포지토리 계층
- ORM (Mybatis, Hibernate)를 주로 사용하는 계층
- DAO 인터페이스와 @Repository 어노테이션을 사용하여 작성된 DAO 구현 클래스가 이 계층에 속함
- Dabase에 data를 CRUD(Create, Read, Update, Drop)하는 계층
요청 처리를 위한 DispatcherServlet의 역할을 간단히 요약해보자면:
- 클라이언트가 요청을 보내면 해당 요청은 Servlet 컨테이너에 의해 DispatcherServlet으로 전달된다.
- DispatcherServlet은 요청 URL을 검사하고 요청을 처리하기 위해 적절한 핸들러를 결정한다.
- 적절한 핸들러를 찾으면 DispatcherServlet은 요청을 해당 컨트롤러 메서드로 전달한다.
- 컨트롤러는 비즈니스 로직을 실행하고 필요한 데이터를 준비한 후 적절한 뷰를 선택하여 응답을 렌더링한다.
- 렌더링된 뷰가 클라이언트에게 반환된다.
✅ DTO로 데이터를 주고 받는 이유
일반적으로 클라이언트와 서버 간 데이터를 주고 받을 때
DTO
혹은 VO
라는 별도의 객체를 통해 주고 받는다. 그 중에서도 Repository 계층과 DB가 주고받는 형식은 Domain
(또는 Entity
)라는 별도의 객체를 통해 주고 받는다.![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F1a81b1ce-cfef-4556-9051-80003ceba87f%252FUntitled.png%3Ftable%3Dblock%26id%3D656b8cf0-2c0c-439a-acb4-598616cf54da%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
Domain 클래스와 DTO 클래스를 분리하는 이유
- 테이블과 매핑되는 Entity 클래스가 변경되면 여러 클래스에 영향을 끼치게 되지만 View와 통신하는 DTO 클래스는 자주 변경되므로 분리해야 한다.
- 즉, DTO는 Domain Model을 복사한 형태로, 다양한 Presentation Logic을 추가한 정도로 사용하며 Domain Model 객체는 Persistent만을 위해서 사용한다.
✅ CRUD 예시
Product
라는 데이터를 CRUD 할 수 있는 Spring MVC 기반 서버를 구축했다고 가정해보자. (필자는 실제로 구축하였다.)사용자가 원하는 상품을 DB에 추가 등록하는 상황을 가정해보자.
- 상품 등록 버튼 클릭 (‘http://localhost:8080/mvc/product/create’로 POST Request 전송으로 대체)
- 등록을 원하는 상품의 상세 정보 입력(Front에서 ProductRequestMvc 형식의 Json으로 객체 매핑 후 서버로 전송)
- API Server의 Controller에서 해당 Request 수신 후 위url에 해당하는 메소드 ‘createProduct( )’ 호출
- Controller 계층에서 Service 계층의 ‘create( )’ 메소드 호출, 이때 인자로 ProductRequestMvc 객체의 속성을 넘겨줌.
- Service 계층에서 ProductEntityMvc 객체를 생성하여 Repository 계층의 ‘save( )’ 메소드 호출
- Repository 계층에서 상품 저장 후, ProductEntityMvc 객체 리턴
- Service 계층에서 Repository 계층에서 리턴한 객체를 다시 리턴
- Controller 계층에서 리턴받은 ProductEntityMvc 객체를 Converter를 통해 ProductResponseMvc 객체 형식으로 리턴
- Front에서 받은 정보를 화면에 출력
1. 상품 등록 버튼 클릭 (‘http://localhost:8080/mvc/product/create’로 POST Request 전송으로 대체)
2. 등록을 원하는 상품의 상세 정보 입력(Front에서 ProductRequestMvc 형식의 Json으로 객체 매핑 후 서버로 전송)
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252Ff34e39ce-f1b3-497a-a94b-d6ecd87ee427%252FUntitled.png%3Ftable%3Dblock%26id%3D0f965229-7e82-413c-b73b-1078ea4b34e5%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
3. API Server의 Controller에서 해당 Request 수신 후 위url에 해당하는 메소드 ‘createProduct( )’ 호출
4. Controller 계층에서 Service 계층의 ‘create( )’ 메소드 호출, 이때 인자로 ProductRequestMvc 객체의 속성을 넘겨줌.
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F4e087bd3-f1a5-4bfb-b30f-2b0fdc0df99b%252FUntitled.png%3Ftable%3Dblock%26id%3Da18773fa-0490-49c8-813e-e9b4119f059a%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
5. Service 계층에서 ProductEntityMvc 객체를 생성하여 Repository 계층의 ‘save( )’ 메소드 호출
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F29dee7e2-febd-468a-8907-5af81a4e7673%252FUntitled.png%3Ftable%3Dblock%26id%3D0e8203b0-7b72-41f7-aaf5-65991ec5b1b4%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
6. Repository 계층에서 상품 저장 후, ProductEntityMvc 객체 리턴
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F1dd696e5-aeaa-40e1-839a-0dcdc88ce0ae%252FUntitled.png%3Ftable%3Dblock%26id%3D390d0b41-c23f-4861-903f-b1df556d0126%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
7. Service 계층에서 Repository 계층에서 리턴한 객체를 다시 리턴
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252Fe1746346-a836-44de-8033-acdca163e0a7%252FUntitled.png%3Ftable%3Dblock%26id%3De533c460-6de1-4e79-a224-1093109c5e53%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
8. Controller 계층에서 리턴받은 ProductEntityMvc 객체를 Converter를 통해 ProductResponseMvc 객체 형식으로 리턴
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252Fe39aed8b-7f95-4c17-a512-99b20325900c%252FUntitled.png%3Ftable%3Dblock%26id%3D15f718ae-e5b1-45fd-a3aa-aae5d4999744%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
9. Front에서 받은 정보를 화면에 출력
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252Fe1a18480-88a4-46db-aa53-3a07d94ec86c%252F2d654df0-873d-43e1-84c7-915f68f506c5%252FUntitled.png%3Ftable%3Dblock%26id%3D3d4ac490-7464-4cbc-be92-1e4a3ca50c7f%26cache%3Dv2&w=3840&q=75&dpl=dpl_9Fy5DR7iXit8HvYKCDvmsFiYTXKA)
이러한 과정을 거쳐 클라이언트와 서버 간 API를 통해 데이터를 주고받을 수 있다.
Share article