C-S-R 패턴
: 애플리케이션의 계층을 명확하게 분리하여 유지보수성과 확장성을 높이는 레이어드 아키텍처의 한 형태
-> 웹 어플리케이션에서 비즈니스 로직을 체계적으로 관리할 수 있다.
- MVC 패턴을 확장하여 "Model"을 더 세분화하여 "Service"와 "Repository" 계층으로 분리한 패턴
- 비즈니스 로직(Service)을 Controller에서 분리하여 유지보수성과 확장성을 높이는 방식
계층을 왜 나누는가??
- 핵심은 비즈니스 로직을 순수하게 유지하는 것. 외부의 것이 바뀌어도 비즈니스 로직은 바뀌어선 안된다.
- 외부API나 DB는 바뀔 확률이 크다 -> 서비스에서 이런 연결을 다 도맡으면, 외부 환경이 바뀌었을 때 비즈니스 로직도 바꿔야함
=> 외부와 통신하는 repository와 controller를 둬서, 그게 바뀌어도 서비스에 있는 비즈니스 로직이 바뀌지 않게 하는것이 핵심
Controller
- 사용자 요청을 처리하고, Service단에 넘겨주고 돌아온 반환값을 HTTP 응답으로 변환해 반환하는 역할을 담당
- @Controller 또는 @RestController로 구현됨
- @Controller는 주로 View(HTML,JSP 등)을 반환하는 컨트롤러로, 웹 페이지(HTML)을 반환
- @RestController를 사용하면 REST API(JSON 응답) 형태를 반환
- 사용자의 HTTP 요청을 받아서 적절한 Service 계층으로 전달
- Service 계층에서 처리된 결과를 적절한 HTTP 응답(Response)으로 변환하여 뷰 또는 데이터 반환
- HTTP 메서드에 따라 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping 등을 사용하여 요청을 처리
- 요청 파라미터 검증이 필수!
- implementation 'org.springframework.boot:spring-boot-starter-validation' 의존성 추가하고
- contorller 메소드 파라미터에 @Valid 달아주고,
- DTO 필드에 @NotNull 같은 어노테이션으로 입력값 검증 가능
Controller 원칙
- DTO를 사용하여 엔티티와의 의존성을 줄여야함! + 엔티티의 중요한 정보가 노출되지 않도록 함
- return, 파라미터 모두 DTO 사용
- 요청과 응답에는 데이터를 제한해야함! -> DTO를 사용해서 API에 약속된 형태로 인수를 받고, 반환
- 비즈니스 로직을 담아선 안됨
- RESTful 원칙 준수 - 명확한 URI 설계, 적절한 HTTP 메서드 사용 등을 통해 일관된 API 제공
- 엔티티 -> DTO 변환 로직이 들어감 (DTO를 return 해줘야하기 때문)
Service
- 비즈니스 로직을 담당하며, 컨트롤러와 리포지토리 사이의 중간 다리 역할을 함
- @Service 어노테이션을 사용하여 서비스 클래스를 정의!
- 엔티티 내의 메서드를 활용하여 로직을 처리하고, Repository의 메소드를 호출 -> 하나의 트랜잭션으로 관리
- 비즈니스 규칙 캡슐화: 서비스 계층에서 비즈니스 규칙을 구현하여, 컨트롤러나 리포지토리에서 로직이 분리되도록 합니다.
- 트랜잭션 관리: @Transactional 어노테이션을 사용하여 트랜잭션을 관리합니다.
- DTO -> 엔티티 변환 로직이 들어감 (Repository에 엔티티를 넘겨줘야하기 때문)
Repository
- 데이터 접근을 담당하고, DB와의 상호작용을 추상화함
- 데이터베이스 CRUD 작업 수행 (기본적인 것은 Spring Data JPA에서 제공)
- 쿼리 메서드 정의 (복잡한 경우)
- 데이터 소스와의 직접적인 상호작용 처리
- Spring Data JPA 사용: 리포지토리 인터페이스를 정의하고, Spring Data가 이를 구현하도록 합니다.
- 커스텀 쿼리 작성: 필요한 경우 @Query 어노테이션을 사용하여 복잡한 쿼리를 작성합니다.
C-S-R 패턴의 장점
- 책임 분리 : 각 계층이 명확한 역할을 가지므로 가독성과 유지보수성 향상
- 재사용성 : 서비스 계층의 비즈니스 로직은 다양한 컨트롤러에서 재사용 / 리포지토리 계층의 메소드를 다양한 서비스에서 재사용
- 테스트 용이성 : 각 계층을 독립적으로 테스트할 수 있어 단위테스트(Mocking이용) 및 통합 테스트가 용이
- 확장성 : 새로운 기능 추가 시 기존 계층을 크게 변경하지 않고 확장 가능
ex) DB를 옮기고 싶을 때도 Service 로직은 그대로 두고, Repository 패턴만 바꿔서 적용시켜주면 된다.
Rest API가 아니라 GRPC로 제공하고 싶을 때도, Service 로직은 그대로 두고 Controller만 변경하면 됨
-> 변경이 되어도 비즈니스 로직이 흔들리지 않을 가능성이 높다.
CSR 패턴에서 서비스(Service) 중심의 비즈니스 로직을 도메인 객체 중심으로 "옮기고 확장"한 것이 클린 아키텍처의 핵심 변화 중 하나. 여기에 Port 개념 등을 추가