전체 글 361

Effective Java - try-finally 대신 try-with-resources 사용하기!

기존의 코드 - try, finally Java 7 버전 이전에는 다 사용하고 난 자원을 반납하기 위해 try-catch-finally 구문을 사용했다. 예시로 살펴보자. public class MainApplication { public static void main(String[] args) { Scanner scanner = null; try { scanner = new Scanner(new File("input.txt")); // scanner 사용 } catch (FileNotFoundException e) { // 예외 처리 } finally { if (scanner != null) { scanner.close(); } } } } 예시에서는 Scanner를 생성하고 finally 구문 안에서 ..

Language/Java 2022.08.31

CQRS에서 조회 모델으로 DDL을 생성하는 이슈 해결!

문제 발생 최근에 사이드 프로젝트에서 DDD와 CQRS를 적용해서 개발하다가 갑자기 테스트가 깨지는 현상이 발생했다. 각 모델은 다음과 같이 정의되어있었다. (간략화) Command Model @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Song { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private long artistId; private String name; private String image; public Song(long artistId, String name, String image) { this.art..

Server/JUnit, Spock 2022.08.29

Java - Spock으로 BDD 테스트하기! (JUnit 대체)

Spock Spock은 BDD(Behaviour-Driven Development) Framework입니다. TDD프레임워크인 JUnit과 비슷한 점이 많으나, 기대하는 동작과 테스트 의도를 더 명확하고 간결하게 드러내주는 큰 장점이 있습니다. 해당 포스팅에서는 Spock을 사용할 때의 이점과 사용 방법에 대해 알아보겠습니다. 테스트 아래의 MemberTier라는 enum에 대한 테스트를 진행하겠습니다. MemberTier는 각 멤버의 등급마다 다른 할인율을 적용해서 계산해주는 함수형 인터페이스를 필드로 가지고 있습니다. public enum MemberTier { BRONZE("할인율 0%", (price) -> { validPrice(price); return calPrice(price, 0); })..

Server/JUnit, Spock 2022.08.25

MSA에서 트랜잭션을 보장하는 방법(2PC, SAGA)

개요 1개 애플리케이션에서 여러 개의 DB 서버를 사용한다면 Java의 경우 JTA나 ChainedTransactionManager 등을 사용해서 분산 트랜잭션을 사용할 수 있다. 문제는 MSA에서 트랜잭션을 어떻게 보장하냐는 것이다. 결제을 한다고 하면 아래의 마이크로 서비스와의 연동이 있을 수 있다. 주문, 배달, 리워드 해당 기능들이 결제 서버, 주문 서버, 배달 서버, 리워드 서버 등으로 분리되어 있다. 트랜잭션을 어떻게 관리할 수 있을까? 2PC (Two-Phase Commit) 2단계에 거쳐 영속하는 작업을 말한다. 해당 가상의 서비스에서는 주문이 끝나면 회원에 등록된 카드로 금액이 결제 되어야 한다. 배달이 진행되어야 하고 사용한 포인트는 차감되어야 한다. Transaction Coordin..

OOP - IS-A 관계, HAS-A 관계 차이 (상속)

IS-A 관계 (is a relationship) 상속 관계를 의미한다. 상속 관계에서는 '~은 ~이다.'가 성립한다. 아래의 예시에서 Student와 Person은 IS-A 관계가 성립한다. public class Student extends Person { private int studentId; } 여기서 Person은 추상화된 개념을 표현한 것이다. HAS-A 관계 (has a relationship) 포함 관계를 의미한다. 포함 관계는 '~은 ~를 가진다.`가 성립한다. 아래의 예시에서 Student와 Book은 HAS-A 관계가 성립한다. public class Student { private Book book; }

Programming/OOP 2022.08.08

MSA(Microservices Architecture)의 장단점

장점 각 서비스를 독립적으로 배포가 가능하다. 유연한 확장 코드 관리가 편리하다. (git conflict 가능성 감소) 책임이 명확하게 분리된다. 장애 범위가 축소된다. 광고 서비스가 장애나도 전체 범위로 확산되지 않음 팀별 코드 이해도 증가 생산성 증가 출시 시간 단축 단점 구현 난이도 상승 API 사용 범위 파악이 어려움 해당 API 스펙을 변경하면 예상 치 못한 서비스에서 장애가 날 수 있음 리소스 비용이 크다. 서버가 많이 필요 배포가 훨씬 더 많고 잦음 트랜잭션 관리가 복잡함 분산 서비스마다 트랜잭션 관리를 처리해야 함 메시징 시스템이 필요할 수 있음 통합 테스트가 어려움

DDD - CQRS란 무엇인가?!

해당 포스팅은 "도메인 주도 개발 시작하기" 라는 내용을 정리한 글입니다. 해당 도서는 아래 Link에서 확인할 수 있습니다. - http://www.yes24.com/Product/Goods/108431347 단일 모델의 단점 주문 내역 조회 기능을 구현하려면 여러 애그리거트에서 데이터를 가져와야 한다. Order에서 주문 정보를 가져와야 하고, Product에서 상품 정보를 가져와야 하고, Member에서 회원 정보를 가져와야 한다. 조회 화면 특성상 속도가 빠를수록 좋은데 여러 애그리거트의 데이터가 필요하면 구현 방식을 고민해야 한다. 식별자(ID)를 이용해서 애그리거트에 참조하게 되면 즉시 로딩(Eager loading) 방식과 같은 JPA의 쿼리 관련 최적화 기능을 사용할 수 없다. -> 이는..

Programming/DDD 2022.08.08

DDD - 이벤트란 무엇인가 ?! (+ 마이크로 서비스 간 트랜잭션 처리)

해당 포스팅은 "도메인 주도 개발 시작하기" 라는  내용을 정리한 글입니다. 해당 도서는 아래 Link에서 확인할 수 있습니다. - http://www.yes24.com/Product/Goods/108431347 시스템 간 강결합 문제 쇼핑몰에서 구매를 취소하려면 환불을 처리해야 한다. 이때 환불 기능을 실행하는 주체가 도메인 엔터티가 될 수 있다. 아래와 같이 환불 기능을 제공하는 도메인 서비스를 파라미터로 전달받아 사용할 수 있다. public class Order { // 외부 서비스를 실행하기 위해 도메인 서비스를 파라미터로 전달 받음 public void cancel(RefundService refundService) { // 주문과 관련된 로직 verifyNotYetShipped(); th..

Programming/DDD 2022.08.03

SpringBoot - CircleCI + S3 + CodeDeploy 배포 구축하기 (+ 실서버 운영 환경 설정, 멀티모듈)

사이드 프로젝트를 진행하는 배포 프로세스를 고민하게 되었다. CI 도구로 Jenkins, Travice CI, CircleCI, Github Action 중 고민을 했고 젠킨스로 구성하고 싶었지만 별도 서버가 필요해서 포기했다. Travice CI는 한 번 해보기도 했고 CircleCI가 인기가 많아진다고 하고 기능이 다양하고 Github 친화적이라고 해서 CircleCI로 진행해보게 되었다. 이번에는 오케스트레이션은 빠져있고 무중단 배포 환경을 구축한 것이 아니다. 테스트 자동화, 배포 자동화에 대해서만 다룬다. (나중에 여유가 된다면 k8s에 올릴 계획이다.) 기본 CI/CD Pipeline 구축 테스트 및 빌드, 배포 자동화까지 적용해보자. .circleci/config.yml CircleCI의 c..

Server/Gradle 2022.08.01

DDD - 바운디드 컨텍스트란 무엇인가 ?!

해당 포스팅은 "도메인 주도 개발 시작하기" 라는  내용을 정리한 글입니다. 해당 도서는 아래 Link에서 확인할 수 있습니다. - http://www.yes24.com/Product/Goods/108431347 도메인 모델과 경계 도메인 모델을 만들 때 빠지기 쉬운 함정이 도메인을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것이다. 한 도메인은 여러 하위 도메인으로 구분되기 때문에 한 개의 모델로 여러 하위 도메인을 모두 표현하려고 시도하면 하위 도메인을 공동체에 협력하는 자율적인 객체가 아닌 수동적인 개체로 만들어 버린다. 이는 OOP에 명백히 어긋나며 하위 도메인의 개념과 요구사항을 반영하기 어렵게 된다. 모델은 특정한 컨텍스트(문맥)에서 완전한 의미를 갖는다. 같은 제품이라도 카탈로그 ..

Programming/DDD 2022.07.25