프로젝트 개요 : 이것이 취업을 위한 백엔드 개발이다 클론코딩 - 상품관리 애플리케이션
프로젝트 환경 : IntelliJ, SpringBoot, MySQL
프로젝트 코드 : https://github.com/smkim9202/ProductManagement
DTO와 ModelMapper
- Data Transfer Object : 데이터를 전송하는 역할을 가진 객체
- 클라이언트에게 노출되는 데이터 구조와 백엔드 애플리케이션 내부 데이터 구조를 분리하기 위해 사용
- DTO 사용 이유
- 도메인 객체를 컨트롤러, 서비스, 레포지토리에서 바로 사용시 도메인 객체의 필드가 변경되면 모든 계층이 영향을 받게 됨(실무에서 데이터 구조가 바뀌는 일은 자주 일어나는 일)
- 내부적으로 동일한 도메인 객체라 하더라도 상황에 따라 조금씩 다른 데이터를 클라이언트에게 전달해야 할 때도 있음
- 엔티티(Entity)
- 도메인 객체는 구체적으로 엔티티라고 부름
- 도메인 객체이면서 id값을 가지는 존재를 Entity, 도메인 객체이면서 id를 가지지 않는 존재를 Value Object라고 부름
- DTO를 어떤 패키지에 둘지, DTO와 엔티티에 대한 변환을 어디에서 수행할지에 대한 고민이 필요
표현 계층 패키지에 DTO 추가 : ProductDto.java
package kr.co.api.product.management.presentation;
public class ProductDto {
private Long id;
private String name;
private Integer price;
private Integer amount;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public Integer getPrice() {
return price;
}
public Integer getAmount() {
return amount;
}
}
DTO에 상품 필드와 getter를 추가 => 도메인객체에서 getter 삭제
도메인 객체 DTO로 변경
ProductController.java
@RequestMapping(value = "/products", method= RequestMethod.POST)
public ProductDto createProduct(@RequestBody ProductDto productDto){
return simpleProductService.add(productDto);
}
SimpleProductService.java
public ProductDto add(ProductDto productDto){
// 1.ProductDto를 Product로 변환하는 코드
Product product = ?;
// 2.레포지토리를 호출하는 코드
Product saveProduct = listProductRepository.add(product);
// 3. Product를 ProductDto로 변환하는 코드
ProductDto saveProductDto = ?;
// 4. DTO 반환하는 코드
return saveProductDto;
}
ModelMapper 의존성 추가
ModelMapper?
- 도메인객체와 DTO 두 클래스를 변환하는 매핑 라이브러리로 도메인객체에 getter 추가 없이 서로 변환해 줌
- Reflection API를 사용하여 두 클래스 사이의 변환 기능을 제공하는 라이브러리
- 자바에서 기본으로 제공하는 라이브러리가 아니기 때문에 메이븐 의존성을 추가해줘야 함 - pom.xml에 추가
- 매번 new 키워드로 객체를 생성하는 방법도 있지만, 미리 빈으로 등록 후 의존성 주입받아서 사용하면 성능상 더 유리함 - Application.java에 빈등록
메이븐 의존성 추가 : pom.xml
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.0</version>
</dependency>
의존성 코드 추가 후 프로젝트에 다운로드
Bean 등록 : Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldAccessLevel(Configuration.AccessLevel.PRIVATE)
.setFieldMatchingEnabled(true);
return modelMapper;
}
}
기본설정 : 매개 변수가 없는 생성자로 인스턴스를 생성 후 setter로 값을 초기화하여 변환
설정변경 : ModelMapper가 private인 필드에 리플렉션 API로 전급하여 변환 할 수 있게 수정해서 setter 없이 Entity와 DTO를 변환 가능하도록 설정
DTO-Entity 변환 : SimpleProductService.java
@Service
public class SimpleProductService {
private ListProductRepository listProductRepository;
private ModelMapper modelMapper;
@Autowired
SimpleProductService(ListProductRepository listProductRepository, ModelMapper modelMapper){
this.listProductRepository = listProductRepository;
this.modelMapper = modelMapper;
}
public ProductDto add(ProductDto productDto){
// 1.ProductDto를 Product로 변환하는 코드
Product product = modelMapper.map(productDto, Product.class);
// 2.레포지토리를 호출하는 코드
Product saveProduct = listProductRepository.add(product);
// 3. Product를 ProductDto로 변환하는 코드
ProductDto saveProductDto = modelMapper.map(saveProduct, ProductDto.class);
// 4. DTO 반환하는 코드
return saveProductDto;
}
}
DTO 추가후 레이어드 아키텍처의 의존성 방향
- DTO는 레이어드 아키텍처 내에서 도메인계층의 변화가 클라이언트에게 전파되지 않도록 제한
- 표현계층에서 도메인계층으로의 의존성이 없어짐
- 응용계층에서 표현계층 DTO로의 의존성이 추가
레이어드 아키텍처에서 반드시 지켜야 하는 의존성 방향
도메인계층은 다른 계층에 의존하지 않는다
다른 모든 계층은 인프라스트럭처계층에 의존하지 않아야 한다 : DB로 변경하면서 의존성 없애도록 개선
'프로젝트 > clone coding' 카테고리의 다른 글
[백엔드 개발 : ProductManagement] 유효성 검사 추가 (0) | 2025.03.20 |
---|---|
[백엔드 개발 : ProductManagement] 상품 조회/수정/삭제 구현 (0) | 2025.03.19 |
[백엔드 개발 : ProductManagement] 상품 추가 구현(프로젝트 구조 잡기) (0) | 2025.03.17 |
[백엔드 개발 : ProductManagement] 상품관리 애플리케이션 정의 (0) | 2025.03.17 |
[Jump to SpringBoot : SBB] 프로젝트 개발과 서버 환경 분리 (0) | 2022.05.12 |