일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- sqld자격증합격
- java알고리즘문제풀이
- 비전공자sqld
- java map
- 코딩부트캠프후기
- java map 저장
- java기본자료형
- 항해15기
- 격파르타합격후기
- 격파르타후기
- javaJRE
- java참조자료형
- 작은수제거하기
- 프로그래머스제일작은수
- java set 저장
- 프로그래머스
- 격파르타비전공자
- java set 출력
- java알고리즘
- java 자료구조 활용
- java list 저장
- java최솟값구하기
- java list 출력
- 컴파일
- javaJVM
- 항해99후기
- java map 출력
- 격파르타장점
- 인터프린터언어
- 노베이스부트캠프
- Today
- Total
코딩과 결혼합니다
[JPA] 아키텍처 패턴(+ 디자인 패턴) 본문
이전에 아키텍처 패턴에 대한 질문을 받았었다. 난 이 개념에 대해 모르고 있어 알고 있는 디자인 패턴을 설명하는 부끄러운 실수를 했었다. 강의를 들으며 그때 물어봤던 게 이 패턴이었구나 깨닫는다. 오늘도 새로운 지식을 습득하며 한층 성장한다!
디자인 패턴
소프트웨어 설계 시 특정 맥락에서 자주 발생하는 문제들을 효과적으로 해결하기 위한 방법
생성 패턴, 구조 패턴, 행동 패턴 등으로 분류할 수 있다.
https://refactoring.guru/ko/design-patterns
디자인 패턴들
refactoring.guru
아키텍처 패턴
주어진 상황에서의 소프트웨어 아키텍처에서 일반적으로 발생하는 문제점들에 대한 일반화되고 재사용 가능한 솔루션이다. 아키텍처 패턴은 소프트웨어 디자인 패턴과 유사하지만 더 큰 범주에 속한다.
10가지의 일반적인 패턴들이 있지만 오늘은 [도메인 모델 패턴], [트랜잭션 스크립트 패턴]에 대해서 알아보고자 한다.
도메인 모델 패턴
비즈니스 로직을 객체 지향적으로 모델링한다. 비즈니스 로직이 복잡하고, 비즈니스 규칙이 많거나 변경되는 경우에 적합하다.
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {
@Id
@GeneratedValue
@Column(name = "order_item_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "item_id")
private Item item;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "order_id")
private Order order;
private int orderPrice;
private int count;
//==생성 메서드==//
public static OrderItem createOrderItem(Item item, int orderPrice, int count) {
OrderItem orderItem = new OrderItem();
orderItem.setItem(item);
orderItem.setOrderPrice(orderPrice);
orderItem.setCount(count);
item.removeStock(count);
return orderItem;
}
//==비즈니스 로직==//
public void cancel() {
getItem().addStock(count);
}
//==조회 로직==//
/**
* 주문 상품 전체 가격 조회
*/
public int getTotalPrice() {
return getOrderPrice() * getCount();
}
}
이 코드를 보면 비즈니스 로직을 Entity에 구현하고 있다.
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class OrderService {
private final OrderRepository orderRepository;
private final MemberRepository memberRepository;
private final ItemRepository itemRepository;
/**
* 주문
*/
@Transactional
public Long order(Long memberId, Long itemId, int count) {
//엔티티 조회
Member member = memberRepository.findOne(memberId);
Item item = itemRepository.findOne(itemId);
//배송조회 정보
Delivery delivery = new Delivery();
delivery.setAddress(member.getAddress());
//주문상품 생성
OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);
//주문 생성
Order order = Order.createOrder(member, delivery, orderItem);
//주문 저장
orderRepository.save(order);
return order.getId();
}
/**
* 주문 취소
*/
public void cancelOrder(Long orderId) {
//주문 엔티티 조회
Order order = orderRepository.findOne(orderId);
//주문 취소
order.cancel();
}
}
서비스 계층은 단순히 엔티티에 필요한 요청을 위임하는 역할을 하게 된다.
각 도메인 모델이 자신의 역할과 책임에 집중할 수 있으므로 코드의 가독성과 유지보수성이 향상된다. 또한, 비즈니스 로직이 복잡해지더라도 객체 지향의 원칙에 따라 유연하게 대응할 수 있다.
하지만 이를 적용하려면 객체지향 설계 원칙과 패턴에 대한 깊은 이해가 필요하며, 초기 개발 비용이 높을 수 있다.
⭐여기서 이러한 문제가 생길 수 있다. 협업을 할 때에 누군가 Entity에 만들어 놓은 비즈니스 로직을 사용하지 않고 직접 객체를 생성하여 set 하여 값을 채우는 방식을 쓸 수도 있는데, 이는 나중에 유지보수를 하기 어려워지게 만든다.
protected OrderItem(){
}
그러한 상황을 방지하기 위해 이런 식으로 protected 해주어 다른 생성을 모두 막아준다.
JPA는 Protected까지 기본 생성자를 만들 수 있게 허용해 준다고 한다. 좀 더 간단하게 적용하는 방법으로는 롬복의 기본생성자를 만들어주는 어노테이션에 (access = AccessLevel.PROTECTED)를 해주면 된다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
트랜잭션 스크립트 패턴
간단한 비즈니스 로직을 처리하는 경우에 적합하다. 하나의 트랜잭션 내에서 모든 작업을 순차적으로 처리하며, 로직이 복잡하게 얽혀있지 않는 경우에 유리하다.
public void createPost(PostRequestDto requestDto, User user, List<MultipartFile> photos) throws IOException {
List<PostImg> postImgList = null;
if (photos != null && !photos.isEmpty()) {
postImgList = postS3Service.uploadPhotosToS3AndCreatePostImages(photos);
}
Post post = new Post(requestDto, user);
postRepository.save(post);
if (postImgList != null) {
associatePostImagesWithPost(post, postImgList);
}
}
이전의 프로젝트에서 내가 사용했던 패턴 방식과 유사해 보인다. 서비스단에서 모든 로직을 순차적으로 처리한다.
서비스가 복잡해질 때에는 그 관심사에 따라서 서비스 클래스를 분리하여 메서드를 호출해 사용할 수 있게 하였다.
코드의 가독성과 유지보수성을 높이는 데 도움이 되었지만, 비즈니스 로직이 복잡해질수록 한계가 드러난다고 한다.
여러 트랜잭션 스크립트에서 중복된 로직이 발생하거나, 하나의 스크립트가 너무 복잡해질 경우에는 도메인 모델 패턴 등 다른 아키텍처 패턴을 고려해 보는 게 좋을 것 같다.
'2세 > JPA' 카테고리의 다른 글
[JPA] 지연 로딩과 조회 성능 최적화(1) (0) | 2024.02.19 |
---|---|
[JPA] API 설계 시 주의할 점(DTO 사용하기) (0) | 2024.02.17 |
[JPA] 상속관계 매핑 - 테이블 전략 (0) | 2024.02.14 |
[JPA] 엔티티 설계시 주의점 (0) | 2024.02.13 |
[JPA] 기본키 생성 전략 (0) | 2024.02.12 |