DAO(Data Access Object)
- 데이터베이스에 접근하기 위한 로직을 관리하기 위한 객체
- 비즈니스 로직의 동작 과정에서 데이터를 조작하는 기능은 DAO 객체가 수행함
- 단, Spring Data JPA에서 DAO의 개념은 Repository(레포지토리)가 대체
- 규모가 작은 서비스에서는 DAO를 별도로 설계하지 않고 바로 서비스 레이어에서 데이터베이스에 접근해서 구현하기도 함
- 하지만 DAO를 서비스 레이어와 리포지토리 중간 계층을 구성하여 사용하면, 비즈니스 로직을 개발할 때 유지보수 측면에서 용이한 경우가 많음
서비스와 비즈니스 레이어
- 객체지향적인 설계에서는 서비스와 비즈니스 레이어를 분리해서 서비스 레이어에서는 서비스 로직을, 비즈니스 레이어에서는 비즈니스 로직을 수행해야 한다는 의견이 많다.
- 서비스 레이어는 주로 사용자 인터페이스(UI)나 컨트롤러와 같은 프레젠테이션 계층에서 받은 요청을 처리하는 역할을 하며,
트랜잭션 관리, 보안 및 권한 확인, 로깅, 예외 처리 등의 '서비스 로직'을 수행한다. - 서비스 레이어는 여러 비즈니스 로직을 조합하고 순서를 제어하여 하나의 비즈니스 프로세스를 완성하기도 한다.
- 비즈니스 레이어는 애플리케이션의 핵심 비즈니스 로직을 담당한다.
- 비즈니스 레이어에서는 비즈니스 규칙을 적용하고, 데이터를 처리하며, 계산을 수행한다.
- 비즈니스 레이어는 도메인 모델을 표현하고, 데이터 액세스 레이어와 통신하여 데이터를 저장하거나 가져온다.
DAO 구현
- DAO 클래스는 일반적으로 '인터페이스 - 구현체' 구성으로 생성함
- DAO 클래스는 의존성 결합을 낮추기 위한 디자인 패턴으로,서비스 레이어에 DAO 객체를 주입받을 때 인터페이스를 선언하는 방식으로 구성할 수 있음
- 아래는 Product라는 엔티티의 대한 DAO의 인터페이스와 구현체 클래스 코드이다.
ProductDAO
public interface ProductDAO {
Product insertProduct(Product product);
Product selectProduct(Long number);
Product updateProductName(Long number, String name) throws Exception;
void deleteProduct(Long number) throws Exception;
}
ProductDAOImpl
@Component
public class ProductDAOImpl implements ProductDAO {
private ProductRepository productRepository;
@Autowired
public ProductDAOImpl(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@Override
public Product insertProduct(Product product) {
Product savedProduct = productRepository.save(product);
return savedProduct;
}
@Override
public Product selectProduct(Long number) {
Product selectedProduct = productRepository.getById(number);
return selectedProduct;
}
@Override
public Product updateProductName(Long number, String name) throws Exception {
Optional<Product> selectedProduct = productRepository.findById(number);
Product updatedProduct;
if (selectedProduct.isPresent()) {
Product product = selectedProduct.get();
product.setName(name);
product.setUpdatedAt(LocalDateTime.now());
updatedProduct = productRepository.save(product);
} else {
throw new Exception();
}
return updatedProduct;
}
@Override
public void deleteProduct(Long number) throws Exception {
Optional<Product> selectedProduct = productRepository.findById(number);
if (selectedProduct.isPresent()) {
Product product = selectedProduct.get();
productRepository.delete(product);
} else {
throw new Exception();
}
}
}
@Service, @Component
- 두 어노테이션은 스프링 빈을 자동으로 등록하는 `@ComponentScan`의 대상이 되며, 이를 통해 스프링은 이들을 자동으로 빈으로 등록하고 종속성 주입을 수행한다.
- @Component: 일반적인 컴포넌트를 등록하는 데 사용된다. 예를 들어, DAO, 서비스, 유틸리티 클래스 등을 등록할 때 사용
- @Component로 등록된 빈은 자동으로 주입되지 않는다. 빈을 주입하려면 @Autowired 어노테이션을 함께 사용해야 한다.
- @Service: 비즈니스 로직을 담당하는 서비스 클래스를 등록하는 데 사용됩니다. @Component보다 더 구체적인 어노테이션이다.
- @Service로 등록된 빈은 자동으로 주입된다. @Autowired 어노테이션 없이도 다른 빈에 주입될 수 있다.
- @Service는 @Component보다 더 명확하고, 자동 주입 기능도 제공하기 때문에 코드를 간소화할 수 있다.
DTO(Data Transfer Object)
- 일반적으로 데이터베이스에 접근하는 계층에서만 Entity를 사용하고, 그 외 다른 계층으로 데이터를 전달할 때는 DTO 객체를 사용함
- 아래는 Product라는 엔티티의 DTO 객체 예시 코드이다.
package com.springboot.jpa.data.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ProductDto {
private String name;
private int price;
private int stock;
}
스프링 부트 애플리케이션의 구조
참고 자료
- 스프링 부트 핵심 가이드 "스프링 부트를 활용한 애플리케이션 개발 실무" , 장정우, 2022
'Development > Spring' 카테고리의 다른 글
[Spring] 빌드 관리 도구,Gradle과 Maven (0) | 2024.02.19 |
---|---|
[Spring] Spring Data JPA에서 getReferenceById vs findById (지연로딩과 즉시로딩) (1) | 2024.02.18 |
[Spring] Spring Data JPA, Repository (0) | 2024.02.17 |
[Spring] 영속성 컨텍스트 (Persistence Context) (0) | 2024.01.30 |
[Spring] Springboot Swagger 3 적용하기 (Springdoc-OpenAPI3) (0) | 2024.01.30 |