빈약한 도메인 모델 (Anemic Domain Model)
- 특징
- VO(또는 엔티티): 데이터를 담는 역할만 함. (getter/setter 중심)
- 비즈니스 로직은 서비스 계층에 존재.
- 장점
- 객체가 단순하고 테스트하기 쉬움.
- 서비스 계층에서 로직을 한눈에 파악 가능.
- 단점
- 도메인 객체가 비즈니스와 분리됨 → 로직 응집도가 낮아짐.
- 도메인 객체의 사용 의도가 불명확할 수 있음.
풍성한 도메인 모델 (Rich Domain Model)
- 특징
- 도메인 객체가 데이터를 담고 비즈니스 로직도 포함.
- 서비스 계층은 도메인의 비즈니스 메서드를 호출하여 작업 위임.
- 장점
- 도메인 객체가 비즈니스 로직을 캡슐화 → 높은 응집도.
- 도메인 중심 설계(DDD)에 적합.
- 단점
- 설계 복잡도 상승.
- 객체 간 의존성이 증가할 가능성 있음.
VO와 DTO의 역할 구분
- VO (Value Object)
- 역할: 비즈니스 로직과 데이터를 캡슐화.
- MyBatis에서 DB 결과 매핑받고, 서비스 계층에서 비즈니스 작업 수행.
- 생성자 또는 팩토리 메서드를 통해 데이터 무결성 유지.
- 비즈니스 규칙 포함 가능 (ex: 유효성 검사, 상태 변경 메서드).
- DTO (Data Transfer Object)
- 역할: 데이터 전송 목적.
- 외부 인터페이스(View/Controller/API 응답)와 통신 시 사용.
- VO의 데이터를 받아 필요한 필드만 선택적으로 포함.
- VO로부터 생성되며 비즈니스 로직은 포함하지 않음.
빈약한 도메인 모델 예시
- VO (데이터만 포함)
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Example {
private Long id;
private String name;
private String status;
// 데이터만 포함 (getter/setter 제공)
}
2. Service (비즈니스 로직 포함)
@Service
public class ExampleService {
@Autowired
private ExampleMapper exampleMapper;
public void activateExample(Long id) {
// VO 조회
Example example = exampleMapper.findById(id);
// 비즈니스 로직 처리
if (!"INACTIVE".equals(example.getStatus())) {
throw new IllegalStateException("Only inactive items can be activated.");
}
example.setStatus("ACTIVE");
// 업데이트 쿼리 호출
exampleMapper.update(example);
}
}
특징
- VO는 데이터를 담는 역할만 수행(getter/setter).
- 모든 비즈니스 로직이 서비스 계층에 집중.
- VO는 단순한 데이터 컨테이너로 사용됨.
풍성한 도메인 모델 예시
- VO (비즈니스 로직 포함)
import lombok.Getter;
@Getter
public class Example {
private Long id;
private String name;
private String status;
// 비즈니스 로직 포함
public void activate() {
if (!"INACTIVE".equals(this.status)) {
throw new IllegalStateException("Only inactive items can be activated.");
}
this.status = "ACTIVE";
}
}
2. DTO (데이터 전송 용도)
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class ExampleDto {
private Long id;
private String name;
// VO로부터 DTO 생성
public ExampleDto(Example vo) {
this.id = vo.getId();
this.name = vo.getName();
}
}
3. Service (비즈니스 로직 위임)
@Service
public class ExampleService {
@Autowired
private ExampleMapper exampleMapper;
public ExampleDto activateExample(Long id) {
// VO 조회
Example example = exampleMapper.findById(id);
// 비즈니스 로직을 VO로 위임
example.activate();
// 업데이트 쿼리 호출
exampleMapper.update(example);
// DTO로 변환 후 반환
return new ExampleDto(example);
}
}
- VO가 데이터를 캡슐화하고 비즈니스 로직을 포함.
- 서비스 계층은 VO의 메서드를 호출하여 로직을 위임.
- DTO는 클라이언트에 데이터를 전달하는 역할만 수행.
비즈니스 로직 분리와 역할 명확화
- 빈약한 도메인 모델은 단순하지만 응집도가 낮음.
- 풍성한 도메인 모델은 VO의 책임이 명확하고 재사용성 높음.
장점
- 책임 분리
- VO: 비즈니스 로직 캡슐화.
- DTO: 데이터 전달에만 집중.
- 안전한 데이터 전송
- DTO를 통해 불필요한 정보 노출 방지.
- VO는 내부 비즈니스 용도로만 활용.
- 유지보수 용이성
- VO와 DTO가 분리되어 변경 사항이 국한됨.
- 서비스 계층 로직 간소화.
'Spring' 카테고리의 다른 글
ServletResponse.isComitted(), FilterChain (with GPT) (1) | 2024.12.19 |
---|---|
(지피티 선생님의) 람다와 일급 객체, FP 특강 (0) | 2024.12.12 |
WebFlux 첨들어봄 (1) | 2024.12.10 |
Spirng AOP (3) | 2024.09.03 |
Spring MVC 설정 파일 이해하기 : web.xml & dispatcher-servlet.xml (1) | 2024.09.03 |