
단위 테스트는 코드 내의 단위(클래스, 메서드) 범위를 테스트하기 때문에 다른 객체나 외부 리소스에 의존성을 가지는 경우 테스트를 작성하기 까다롭다.예를 들면 데이터베이스에 의존하는 경우 데이터베이스에 데이터가 준비되어있어야 한다던지, 테스트하고자하는 영역 이외에 신경써야할 부분이 많아진다.또한 그렇게 테스트를 진행한다고 하더라도 데이터베이스 연결까지 포함하여 테스트하기 때문에 단위 테스트보다는 통합 테스트나 기능 테스트에 더욱 가깝다.이러한 경우에 활용할 수 있는 두 가지 방법이 있는데 그것이 스텁과 모의 객체이다. 스텁 활용하기스텁이란 테스트를 위한 테스트용 객체이다.간단히 예를 들면 HTTP 통신을 위한 부분이 단위 테스트에 포함된다고 가정한다면, HTTP 통신을 담당하는 테스트 클래스를 따로 생성..

테스트 코드를 작성하는 것은 단순하게 구현된 기능을 테스트한다는 의미 이상의 효과를 발휘한다.여러 긍정적인 효과를 발휘하고 테스트 자체로도 품질 지표가 되기도 한다.그렇다면 테스트 코드를 작성함으로써 프로젝트 전반에 끼치게 되는 긍정적인 효과를 알아보자. 테스트 커버리지테스트 커버리지가 높으면 안정적으로 리팩토링이 가능하기 때문에, 이상적으로는 테스트 커버리지를 100% 달성하는 것이 좋다.테스트 커버리지를 높히기 위해서는 모든 public API를 테스트하는 것만으로는 부족하다. (블랙박스 테스트)우선 테스트 커버리지를 측정하고 이에 대해 커버되지 않는 영역에 대해 화이트박스 테스트를 진행해야한다.그렇다면 테스트 커버리지는 어떻게 측정할 수 있을까? IntelliJ의 내장 기능 사용IntelliJ에서 ..

https://docs.spring.io/spring-boot/api/java/org/springframework/boot/context/event/package-summary.html org.springframework.boot.context.event (Spring Boot 3.4.4 API)package org.springframework.boot.context.eventdocs.spring.io위 링크를 보면 org.springframework.boot.context.event 패키지의 클래스들의 spring docs를 확인할 수 있다.스프링이 기동되는 시점에 여러 이벤트가 발생하고 필요한 경우에는 해당 이벤트의 리스너를 구현할 수도 있다. 그렇다면 이벤트의 종류를 스프링의 코드를 기반으로 학습해..
여러가지 개발 서적을 접하다보면 단위 테스트의 필요성을 자주 강조하고 있다.그렇다면 여러 가지 종류의 테스트 중에서 단위 테스트는 무엇이며, 단위 테스트가 필요한 이유는 무엇일까? 테스트 유형단위 테스트통합 테스트시스템 테스트인수 테스트테스트의 범위가 작은 것 부터 위와 같이 테스트 유형을 분류할 수 있다. 단위 테스트단위 테스트는 소스 코드의 메서드나 클래스를 테스트하여 해당 코드가 정상 동작하는지 확인한다.따라서 좋은 단위 테스트가 작성되어 있을 때 코드를 변경하는 경우, 기존 코드에 대한 영향도를 쉽게 파악할 수 있다. 통합 테스트통합 테스트는 여러 개의 컴포넌트가 정상적으로 상호작용하는지 확인한다.예를 들어 객체 간의 협력, 외부 리소스와의 연동 등을 테스트한다. 시스템 테스트시스템 테스트는 시스..

예를 들어 이체 성공 시 Push 알림을 받아야하는 요구사항을 구현해야한다고 생각해보자.가장 단순하고 쉽게 생각하면 아래와 같은 코드를 떠올릴 것이다.public class TransferService { public TransferResult transfer(String accountNumber, int amount) { Transfer transfer = Transfer.of(accountNumber, amount); transfer.execute(); PushRequest pushReq = PushRequest.of( PushTemplate.TRANSFER_SUCCESS, Maps.of("account..

하나의 애그리거트를 대상으로 동시에 다른 두 요청이 들어왔을 때 일관성이 깨질 수 있다. 만약 위의 그림과 같이 하나의 계좌에 대해 1,000원 출금/입금 거래가 동시에 들어왔다고 가정해보자.트랜잭션 처리가 정상적으로 이루어지지 않는다면 최종 커밋이 유효하게 처리되어 계좌 잔액이 2,000원이 되어 일관성이 깨지게 된다. 선점 잠금선점 잠금은 애그리거트를 선점한 요청이 모두 끝나기 전까지 다른 요청이 해당 애그리거트를 수정할 수 없도록 하는 방식이다.위의 그림과 같이 두 번째 요청은 애그리거트에 접근하기 위해 첫 번째 요청이 끝날 때까지 블로킹한다.두 번째 요청이 수행되면 첫 번째 요청의 결과 뒤에서 입금 거래가 수행되기 때문에 데이터의 일관성을 유지할 수 있게 된다. 일반적으로 선점 잠금을 위해서 DB..
응용 계층 구성응용 계층은 도메인 객체를 사용해서 사용자가 원하는 기능을 제공한다.응용 계층은 표현 계층에 의존성을 가지지 않으며 어떤 통신을 이용하는지 등의 정보를 알 필요는 없다. public Result processSomething(FunctionRequest request) { Aggregate aggregate = aggregateRepository.findById(request.getId()); aggregate.process(request.getValue()); return createResult(aggregate);}일반적으로 응용 계층의 코드는 위와 같이 간단한 구조의 코드 형태를 가지게 된다.복잡한 비즈니스 로직은 도메인 영역에서 처리되어야하며, 이를 어..

JPA를 사용하지 않고 MyBatis나 JDBC를 활용하더라도 의존성을 잘 관리한다면 충분히 DDD를 적용할 수 있다.그러나 JPA와 같은 ORM을 사용한다면 도메인 모델과 데이터 모델을 매핑하는 다양한 기능을 제공하기 때문에 JPA를 사용해서 DDD를 적용하는 방법을 알아보고자 한다. 레포지토리 구성기본적으로 하나의 애그리거트에는 하나의 레포지토리를 구성한다.@Repositorypublic class JpaTransferRepository implements TransferRepository { @PersistenceContext private EntityManager entityManager; @Override public Optional findById(String i..

도메인이 많아지는 경우만약 100개 이상의 도메인을 표현하는 다이어그램을 보고 시스템을 이해하려한다면 한 번에 이해가 되지 않을 것이다.특정 기능을 수정하는 경우 이 기능과 인접한 몇 개의 도메인만을 파악하여 수정해서 전체적인 시스템의 일관성이 틀어지게 될 수도 있다. 이처럼 복잡한 도메인을 이해하기 위해 애그리거트를 사용한다.도메인 영역의 여러 객체를 애그리거트 단위로 묶어서 상위 단위의 다이어그램으로 시스템을 보다 간단하게 파악할 수 있다. 위와 같은 여러 객체의 관계를 애그리거트로 묶어서 간단하게 파악할 수 있다.애그리거트는 관련된 모델을 하나로 묶었기 때문에 동일한 라이프사이클을 가진다. 따라서 Account를 생성할 때는 AccountType과 RatePolicy를 같이 생성한다. 라이프사이클이..

도메인 주도 개발을 해야하는 이유?도메인 주도 개발은 OOP를 깔끔하게 적용할 수 있는 하나의 방법이다.유지보수성이 높은 코드를 생산하기 위해 OOP 기반의 도메인을 설계하고, 쿼리 매퍼 대신 ORM을 사용하려고해도 완벽하게 들어맞지 않는 경우가 있다.특히 서버 애플리케이션의 경우에는 일반적으로 데이터 영속성을 관리하기 위한 외부 의존성(DB)을 가지기 때문에 이와 같은 의존성을 분리하여 도메인을 설계해야한다. 또한 이러한 설계를 MVC기반의 Layered Architecture와 혼용하여 적용해야하는 경우가 대다수다.이 때 도메인 주도 개발을 이해하는 것은 보다 쉽게 의존성을 관리할 수 있는 레퍼런스로 활용될 수 있다.DDD는 OOP를 적용할 수 있는 하나의 방법이기 때문에 절대적이지 않으며 이를 참고..