Spring 웹 계층
Web Layer
- 흔히 사용하는 컨트롤러(Controller)와 JSP/Freemarker 등의 뷰 템플릿 영역이다.
- 이외에도 필터(@Filter), 인터셉터, 컨트롤러 어드바이스(@ControllerAdvice) 등 외부 요청과 응답에 대한 전반적인 영역을 의미한다.
Service Layer
- @Service에 사용되는 서비스 영역이다.
- 일반적으로 Controller와 Dao의 중간 영역에서 사용된다.
- @Transactional이 사용되어야 하는 영역이기도 하다.
Repository Layer
- Database와 같이 데이터 저장소에 접근하는 영역이다.
- Dao(Data Access Object) 영역이라고 생각하면 된다.
Dtos
- Dto(Data Transfer Object)는 계층 간에 데이터 교환(Service -> Repository)을 위한 객체를 의미하며, Dtos는 이들의 영역을 의미한다.
- 예를 들어 뷰 템플릿 엔진에서 사용될 객체나 Repository Layer에서 결과로 넘겨준 객체 등이 이들을 이야기한다.
Domain Model
- 도메인이라 불리는 개발 대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화시킨 것을 도메인 모델이라고 한다.
- 배달 앱이라고 가정하면, 주문, 결제, 배달상태 등이 될 수 있다.
- 비즈니스 로직을 처리하는 영역이다.Serivce가 아닌 Domain에서 처리한다.
- Service는 트랜잭션을 보장해주고 Domain 내 비즈니스 로직을 필요한 순서대로 호출한다.
- @Entity가 사용된 영역 역시 도메인 모델이라고 이해하면 된다.
- 다만, 무조건 데이터베이스의 테이블과 관계가 있어야 하는 것은 아니다. VO처럼 값 객체들도 이 영역에 해당하기 때문이다.
CRUD 기능 구현
Member를 등록, 수정, 삭제, 조회하는 기능을 Spring과 JPA로 구현
전체 소스는 https://github.com/Minji1004/MinjiShop 에 있다.
Web Layer
Controller
- @Controller를 선언해준다.
- DTO 클래스에 setter가 없으면 화면으로부터 값을 가지고오지 못한다.
- @RequiredArgsConstructor는 롬복이 제공하는 기능으로, final이 붙은 필드로 구성된 생성자를 만든다.
- 생성자가 하나 밖에 없으면 @Autowired가 붙지 않아도, 생성자 방식으로 의존성을 주입한다.
- return되는 String은 응답을 보낼 화면 이름이다.
ex) members/createMemberForm -> members/createMemberForm.mustache로 보내진다.
- Model 객체에 담긴 값은 mustache 파일로 보내진다.
아래는 API용 Controller이다. Member 정보의 수정 및 삭제는 API로 구현했다.
- @RestController: JSON을 반환하는 컨트롤러로 만들어준다.
Dtos
Entity는 절대 뷰 템플릿(mustache)용으로 사용하면 안된다.
DB 테이블과 밀접한 관계가 있으므로, Reuqest/Response는 엔터티가 아닌 DTO를 만들어서 받아야 한다.
Service Layer
Service
-
@Service를 붙여 Service 클래스임을 설정한다.
-
@Transactional을 붙인다. 없으면 아래와 같은 에러가 난다.
-
Repository에서 사용하기 전에 DTO를 Entity로 바꿔준다. 또한 DB에서 가져온 Entity는 다시 DTO나 필요한 값만 빼서 내보낸다. (Service와 Repository Layer 간 데이터 교환)
- JPA에서 수정, 삭제 시 우선 Entity ID로 JPA 영속 컨텍스트에서 조회해서 해당 Entity를 영속 상태로 만든다.
JPA에서 수정은 영속 상태에 있는 엔터티의 값만 변경해주면 된다.
그러면 JPA 영속 컨텍스트에서 변경 감지를 하여 DB에 flush 할 때 DB에 update SQL을 자동으로 보낸다.
Repository Layer
Repository
- @Repository 를 붙인다.
- @PersistenceContext는 스프링 컨테이너에 등록된 EntityManger 스프링 빈을 주입받는다.
- JPQL은 JPA에서 제공하는 객체지향 쿼리 언어다.
Domain
- @Entity를 붙인다.
- DB의 테이블과 매핑된다.
아래 Member 엔티티의 자세한 내용은 Spring Data JPA 를 이용해 기본 도메인 Entity 생성을 참조한다.