책/도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지

[도메인 주도 개발 시작하기] 1장: 도메인 주도 개발 시작하기

2022. 9. 7. 20:35
목차
  1.  
  2. 1.1 도메인이란?
  3. 1.2 도메인 전문가와 개발자 간 지식 공유
  4. 1.3 도메인 모델
  5. 1.4 도메인 모델 패턴
  6. 1.5 도메인 모델 표출
  7. 1.6 엔티티와 밸류
  8. 1.7 도메인 용어와 유비쿼터스 언어
본문은 [도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지]를 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.

 

1.1 도메인이란?

  • 도메인(domain)이란 소프트웨어로 해결하고자 하는 문제 영역에 해당한다
  • 한 도메인은 다시 하위 도메인으로 나눌 수 있으며, 한 하위 도메인은 다른 하위 도메인과 연동하여 완전한 기능을 제공한다
    • 예를 들어 고객이 물건을 구매하면 주문, 결제, 배송, 혜택 등 하위 도메인의 기능이 엮이게 된다
  • 특정 도메인을 위한 소프트웨어라고 해서 도메인이 제공해야 할 모든 기능을 직접 구현하는 것은 아니다
    • [그림 1.2]에서 배송 도메인은 외부 배송 업체의 시스템을 사용하고, 결제 도메인은 외부 PG사의 시스템을 사용한다.
  • 도메인마다 고정된 하위 도메인이 존재하는 것은 아니며, 하위 도메인을 어떻게 구성할지 여부는 상황에 따라 달라진다

 

 

1.2 도메인 전문가와 개발자 간 지식 공유

  • 개발자는 요구사항을 분석하고 설계하여 코드를 작성하며 테스트하고 배포한다
    • 이때, 요구사항을 올바르게 이해하는 것이 중요하다
    • 요구사항을 잘못 이해하면 수정해야 할 코드가 많아지고 제품을 만드는데 실패하거나 일정이 밀리기도 한다
  • 요구상항을 올바르게 이해하기 위한 가장 쉬운 방법은 전문가와 직접 대화하는 것이다
    • 중간에 전달자가 많으면 정보의 누락이나 왜곡이 발생할 여지가 크고, 이에 따라 잘못된 소프트웨어가 만들어질 수 있다
  • 도메인 전문가 만큼은 아니더라도 이해관계자와 개발자도 도메인 지식을 갖춰야 한다
    • 제품 개발과 관련된 사람들이 같은 지식을 공유하고 직접 소통할 수록 도메인 전문가가 원하는 제품을 만들 가능성이 커진다

 

 

1.3 도메인 모델

1) 도메인 모델 예시

  • 도메인 모델에는 다양한 정의가 존재하는데, 기본적으로 도메인 모델은 특정 도메인을 개념적으로 표현한 것이다
    • 도메인 모델을 사용하면 여러 관계자들이 동일한 모습으로 도메인을 이해하고 도메인 지식을 공유하는 데 도움이 된다
    • [그림 1.3]의 모델은 도메인의 모든 내용을 담고 있지 않지만, 해당 모델을 통해 도메인이 지니고 있는 특성과 기능을 파악할 수 있다
  • 도메인을 이해하려면 도메인이 제공하는 기능과 도메인의 주요 데이터 구성을 파악해야 한다
    • 따라서 기능과 데이터를 함께 보여주는 객체 모델은 도메인을 모델링하기에 적합하다

  • 도메인 모델을 객체로만 모델링 할 수 있는 것은 아니다
    • [그림 1.4]와 같이 상태 다이어그램을 이용해서 주문의 상태 전이를 모델링할 수 있다
  • 도메인을 이해하는 데 도움이 된다면 표현 방식이 무엇인지는 중요하지 않다
    • 꼭 클래스 다이어그램이나 상태 다이어그램과 같은 UML 표기법만 사용해야 하는 것은 아니며, 그래프나 수학 공식 등 다양한 방식으로 도메인 모델을 만들 수 있다
  • 도메인 모델은 기본적으로 도메인 자체를 이해하기 위한 개념 모델이다
    • 따라서 코드를 작성하기 위해선 구현 기술에 맞는 구현 모델이 별도로 필요하다
  • 개념 모델과 구현 모델은 서로 다른 것이지만 구현 모델이 개념 모델을 최대한 따르도록 할 수 있다
    • 객체 기반 모델 -> 객체 지향 언어를 이용한 구현 모델
    • 수학적인 모델 -> 함수를 이용한 구현 모델

 

2) 하위 도메인과 모델

  • 각 하위 도메인이 다루는 영역은 서로 다르므로 같은 용어라도 하위 도메인마다 의미가 달라질 수 있다
    • 카탈로그 도메인의 상품은 상품 가격, 상세 내용을 담고 있는 정보를 의미하는 반면 배송 도메인의 상품은 고객에게 실제 배송되는 물리적인 상품을 의미한다
  • 도메인에 따라 용어 의미가 결정되므로 여러 하위 도메인을 하나의 다이어그램에 모델링하면 안 된다
  • 모델의 각 구성요소는 특정 도메인으로 한정할 때 비로소 의미가 완전해지므로 각 하위 도메인마다 별도로 모델을 만들어야 한다

 

 

1.4 도메인 모델 패턴

1) 아키텍처 구성

  • 일반적으로 애플리케이션의 아키텍처는 [그림 1.5]와 같이 네 개의 영역으로 구성되며, 각 영역의 역할은 [표 1.1]과 같다
  • 앞서 살펴본 도메인 모델이 도메인 자체를 이해하는 데 필요한 개념 모델을 의미한다면, 지금 살펴볼 도메인 모델은 마틴 파일러가 쓴 [엔터프라이즈 애플리케이션 아키텍처 패턴] 책의 도메인 모델 패턴을 의미한다
    • 도메인 모델 패턴은 아키텍처 상의 도메인 계층을 객체 지향 기법으로 구현하는 패턴이다

 

2) 도메인 모델 패턴 예제

  • 도메인 계층의 도메인의 핵심 규칙을 구현한다
    • 주문 도메인의 경우 '출고 전에 배송지를 변경할 수 있다'라는 규칙과 '주문 취소는 배송 전에만 할 수 있다'라는 규칙을 구현한 코드가 도메인 계층에 위치하게 된다
    • 이런 도메인 규칙을 객체 지향 기법으로 구현하는 패턴이 도메인 모델 패턴이다

 

배송지 정보 변경 가능 여부를 OrderState에서 판단

public class Order {
    private OrderState state;
    private ShippingInfo shippinginfo;

    public void changeShippingInfo(ShippingInfo newShippingInfo) {
        if (!state.isShippingChangeable()) {
            throw new IllegalStateException("can't change shipping in " + state);
        }
        this.shippinginfo = newShippingInfo;
    }
    
    // ...
}


public enum OrderState {
    PAYMENT_WAITING {
        public boolean isShippingChangeable() {
            return true;
        }
    },
    PREPARING {
        public boolean isShippingChangeable() {
            return true;
        }
    },
    SHIPPED, DELIVERING, DELIVERY_COMPLETED;

    public boolean isShippingChangeable() {
        return false;
    }
}
  • 위 코드는 주문 도메인의 일부 기능을 도메인 모델 패턴으로 구현했다
  • OrderState에는 주문 대기 중이거나 상품 준비 중에는 배송지를 변경할 수 있다는 도메인 규칙을 구현하고 있다
  • 큰 틀에서 보면 OrderState는 Order에 속한 데이터이므로 배송지 정보 변경 가능 여부를 판단하는 코드를 Order로 이동할 수도 있다

 

배송지 정보 변경 가능 여부를 Order에서 판단

public class Order {
    private OrderState state;
    private ShippingInfo shippinginfo;

    public void changeShippingInfo(ShippingInfo newShippingInfo) {
        if (!isShippingChangeable()) {
            throw new IllegalStateException("can't change shipping in " + state);
        }
        this.shippinginfo = newShippingInfo;
    }

    private boolean isShippingChangeable() {
        return state == OrderState.PAYMENT_WAITING || state == OrderState.PREPARING;
    }
    // ...
}


public enum OrderState {
    PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED;
}
  • 배송지 정보 변경 가능 여부를 Order에서 판단하도록 수정했다
    • 배송지 변경이 가능한지를 판단할 규칙이 주문 상태와 다른 정보를 함께 사용한다면 OrderState만으로는 배송지 변경 가능 여부를 판단할 수 없으므로 Order에서 로직을 구현해야 한다
  • 중요한 점은 주문과 관련된 중요 업무 규칙을 주문 도메인 모델인 Order나 OrderState에서 구현한다는 점이다
    • 핵심 규칙을 구현한 코드는 도메인 모델에만 위치하므로 규칙이 바뀌거나 규칙을 확장해야 할 때 다른 코드에 영향을 덜 주고 변경 내역을 모델에 반영할 수 있게 된다

 

'도메인 모델'이라는 용어는 도메인 자체를 의미하는 개념적인 모델을 의미하지만, 도메인 계층을 구현할 때 사용하는 객체 모델을 언급할 때에도 '도메인 모델'이라는 용어를 사용한다. 이 책에서도 도메인 계층의 객체 모델을 표현할 때 도메인 모델이라고 표현하고 있다.

 

3) 개념 모델과 구현 모델

  • 개념 모델은 순수하게 문제를 분석한 결과물이다
    • DB, 트랜잭션 처리, 성능, 구현과 같은 기술을 고려 X
    • 따라서 실제 코드를 작성할 땐 개념 모델을 있는 그대로 사용할 수 없음
  • 개념 모델을 만들 때 처음부터 완벽하게 도메인을 표현하는 모델을 만드는 것은 불가능에 가깝다
    • 프로젝트 초기에 완벽한 도메인을 만들더라도 결국 도메인에 대한 새로운 지식이 쌓이면서 모델을 보완하거나 변경하는 일이 발생함
  • 따라서 처음부터 완벽한 개념 모델을 만들기보다는 전반적인 개요를 알 수 있는 수준으로 개념 모델을 작성해야 한다

 

 

1.5 도메인 모델 표출

  • 구현을 시작하기 위해서는 도메인에 대한 초기 모델이 필요하다
  • 도메인을 모델링할 때 기본이 되는 작업은 모델을 구성하는 핵심 구성요소, 규칙, 기능을 찾는 것이다
  • 이 과정은 요구사항에서 출발한다

 

1) 도메인 모델 표출 예제

앞선 예제에 이어서 주문 도메인과 관련된 몇 가지 요구사항을 살펴보자

  • 최소 한 종류 이상의 상품을 주문해야 한다
  • 한 상품을 한 개 이상 주문할 수 있다
  • 총 주문 금액은 각 상품의 구매 가격 합을 모두 더한 금액이다
  • 각 상품의 구매 가격 합은 상품 가격에 구매 개수를 곱한 값이다
  • 주문할 때 배송지 정보를 반드시 지정해야 한다
  • 배송지 정보는 받는 사람 이름, 전화번호, 주소로 구성된다
  • 출고를 하면 배송지를 변경할 수 있다
  • 출고 전에 주문을 취소할 수 있다
  • 고객이 결제를 완료하기 전에는 상품을 준비하지 않는다

 

위 요구사항에서 주문은 '출고 상태로 변경하기', '배송지 정보 변경하기', '주문 취소하기', '결제 완료하기' 기능을 제공한다는 사실을 도출할 수 있고, Order에 관련 기능을 메서드로 추가할 수 있다.

public class Order {
    public void changeShipped() { ... }
    public void changeShippingInfo(ShippingInfo newShippingInfo) { ... }
    public void cancel() { ... }
    public void completePayment() { ... }
}

 

다음 요구사항으로부터 주문 항목(OrderLine)이 주문할 상품, 상품의 가격, 구매 개수를 포함하는 동시에 각 구매 항목의 구매 가격도 제공해야 한다는 사실을 알 수 있다.

  • 한 상품을 한 개 이상 주문할 수 있다
  • 각 상품의 구매 가격 합은 상품 가격에 구매 개수를 곱한 값이다
public class OrderLine {
    private Product product; // 주문할 상품
    private int price; // 상품의 가격
    private int quantity; // 구매 개수
    private int amounts; // 구매 가격 합

    public OrderLine(Product product, int price, int quantity) {
        this.product = product;
        this.price = price;
        this.quantity = quantity;
        this.amounts = calculateMounts();
    }

    private int calculateMounts() {
        return price * quantity;
    }

    public int getAmounts() { ... }
    
    // ...
}

 

2) 정리

  • 내용이 많아 다른 예제는 생략했다
  • 중요한 것은 요구사항을 분석함으로써 도메인 모델이 지니고 있어야 할 상태와 기능, 그리고 제약조건 등을 찾을 수 있다는 것이다
    • 이와 같이 도메인 지식이 쌓여가면서 도메인 모델을 점진적으로 만들어 갈 수 있다 
  • 이렇게 만든 모델은 요구사항 정련을 위해 도메인 전문가나 다른 개발자 논의하는 과정에서 공유하기도 한다

 

 

 

1.6 엔티티와 밸류

  • [그림 1.6]은 앞서 요구사항 분석 과정에서 만든 모델이며, 이 안에는 엔티티와 밸류가 모두 존재한다
  • 도출한 모델은 크게 엔티티와 밸류로 구분할 수 있다
  • 엔티티와 밸류를 제대로 구분해야 도메인을 올바르게 설계하고 구현할 수 있으므로 이 둘의 차이를 명확하게 이해해야만 도메인을 잘 구현할 수 있다

 

1) 엔티티

  • 엔티티의 가장 큰 특징은 식별자를 가진다
    • 식별자는 엔티티 객체마다 고유해서 각 엔티티는 서로 다른 식별자를 가진다
    • 엔티티의 식별자는 바뀌지 않는다
  • 엔티티의 식별자는 바뀌지 않고 고유하므로 두 엔티티의 식별자가 같으면 두 엔티티는 같다고 판단할 수 있다
    • 이는 코드 상에서 equals() 메서드와 hashCode() 메서드로 구현될 수 있다

 

2) 엔티티의 식별자 생성

엔티티의 식별자를 생성하는 시점은 도메인의 특징과 사용하는 기술에 따라 달라지는데, 보통 다음 중 한 가지 방식으로 생성한다

  • 특정 규칙에 따라 생성
  • UUID나 Nano ID와 같은 고유 식별자 생성기 사용
  • 값을 직접 입력
  • 일련번호 사용(시퀀스나 DB의 자동 증가 칼럼 사용)

자동 증가 칼럼을 제외한 다른 방식은 다음과 같이 식별자를 먼저 만들고 엔티티 객체를 생성할 때 식별자를 전달한다.

// 엔티티를 생성하기 전에 식별자 생성
String orderNumber = orderRepository.generateOrderNumber();

Order order = new Order(orderNumber, ...);
orderRepository.save(order);

자동 증가 칼럼은 DB 테이블에 데이터를 삽입해야 비로소 값을 알 수 있으므로 테이블에 데이터를 추가하기 전까지는 식별자를 알 수 없다. 따라서 엔티티 객체를 생성할 때 식별자를 전달 할 수 없다.

Article article = new Article(author, title, ...);
articleRepository.save(article); // DB에 저장한 뒤 구한 식별자를 엔티티에 반영
Long savedArticleId = article.getId(); // DB에 저장한 후 식별자 참조 가능

 

3) 밸류 타입

  • [그림 1.8]에서 '받는 사람'과 '주소'라는 개념을 표현하기 위해 각 필드들이 사용된다
    • receiverName과 receiverPhoneNumber필드는 '받는 사람'이라는 하나의 개념을 표현한다
    • shppingAddress1, shppingAddress2, shippingZipcode 필드는 '주소'라는 하나의 개념을 표현한다
  • 밸류 타입은 이렇듯 개념적으로 완전한 하나를 표현할 때 사용한다
    • 밸류 타입을 이용하여 받는 사람(Receiver)과 주소(Address)라는 개념을 표현할 수 있다

 

그림 1.8을 밸류 타입을 이용하여 수정한 코드

public class Receiver {
    private String name;
    private String phoneNumber;

    public Receiver(String name, String phoneNumber) {
        this.name = name;
        this.phoneNumber = phoneNumber;
    }

    public String getName() {
        return name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }
}

public class Address {
    private String address1;
    private String address2;
    private String zipcode;

    public Address(String address1, String address2, String zipcode) {
        this.address1 = address1;
        this.address2 = address2;
        this.zipcode = zipcode;
    }
}
  • 위의 코드는 도메인 개념과 관련된 데이터를 모아서 하나의 클래스 형태로 만든 것을 보여준다
    • 이렇게 밸류 타입을 사용하면 개념적으로 완전한 하나를 잘 표현할 수 있다
  • 밸류 타입을 사용함으로써 ShippingInfo의 가독성도 향상되었다

 

하나의 예제를 더 살펴보자. OrderLine은 int타입의 price와 amounts 필드를 사용하는데, 이를 밸류 타입인 Money타입으로 대체하여  의미를 보다 명확하게 표현하고 밸류 타입이 가지고 있는 기능을 이용할 수 있다.

public class OrderLine {
    private Product product; // 주문할 상품
    private int price; // 상품의 가격
    private int quantity; // 구매 개수
    private int amounts; // 구매 가격 합
    ...
}

 

public class OrderLine {
    private Product product; // 주문할 상품
    private Money price; // 상품의 가격
    private int quantity; // 구매 개수
    private Money amounts; // 구매 가격 합
}



public class Money {
    private int value;

    // 생성자, getter 생략...

    // 돈 계산을 위한 기능이 추가됨
    public Money add(Money money) {
        return new Money(this.value + money.value); // 불변 보장
    }

    public Money multiply(int multiplier) {
        return new Money(value * multiplier);
    }
}

 

정리하자면 밸류타입은 아래와 같은 장점을 가진다고 할 수 있다

  1. 가독성이 향상된다
  2. 의미를 보다 명확하게 표현할 수 있다
  3. 밸류 타입을 위한 기능을 추가할 수 있다

 

4) 도메인 모델에 setter 넣지 않기

  • 도메인 모델에 get/set 메서드를 무조건 추가하는 것은 좋지 않은 버릇이다
  • setter는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 한다
    • 예를 들어 changeShippinngInfo()가 배송지 정보를 새로 변경하는 의미를 가졌다면 setShippingInfo() 메서드는 단순히 배송지 값을 설정한다는 것은 의미한다
    • 이렇게 setter를 쓰면 단순히 상태 값만 변경할 것인지 혹은 다른 처리를 위한 코드를 함께 구현할 것인지 애매해진다
  • set 메서드의 또 다른 문제는 도메인 객체가 생성될 때 온전하지 않은 상태가 될 수 있다는 것이다
    • 불완전한 상태의 객체를 생성한 뒤 setter로 도메인 객체의 프로퍼티를 채우는 방식으로 코드를 구현할 수 있다
    • 이런 경우 핵심 프로퍼티가 누락된 도메인 객체가 생성되어 문제를 일으킬 수 있다
  • 도메인 객체가 불완전한 상태로 사용되는 것을 막기 위해선 객체의 생성 시점에 필요한 데이터를 전달하고, 이를 검증해야 한다
    • 즉, 생성자를 통해 필요한 데이터를 모두 받고, 필요한 경우 생성자 내부에 검증 코드를 추가한다
  • 불변으로 밸류 타입으로 구현하면 자연스럽게 setter를 구현하지 않을 수 있다
    • setter를 구현해야 할 특별한 이유가 없다면 불변 타입의 장점을 살릴 수 있도록 밸류 타입은 불변으로 구현한다

 

5) DTO의 get/set 메서드

  • DTO는 Data Transfer Object의 약자로 프레젠테이션 계층과 도메인 계층이 데이터를 서로 주고받을 때 사용하는 일종의 구조체이다
  • DTO는 도메인 로직을 담고 있지 않으므로 get/set 메서드를 제공해도 도메인 객체의 데이터 일관성엔 영향을 줄 가능성이 높지 않다
  • 하지만 DTO도 밸류 타입과 마찬가지로 setter를 열어주는 대신 생성 시점에 값이 주입되게 만듦으로써 불변 객체를 만드는 것이 좋다

 

 

1.7 도메인 용어와 유비쿼터스 언어

  • 코드를 사용할 때 도메인에서 사용하는 용어는 매우 중요하다
  • 도메인에서 사용하는 용어를 코드에 반영하지 않으면 개발자는 코드의 의미를 해석해야 하는 부담을 지우게 된다
    • 예컨대 '결제 대기 중', '상품 준비 중', '출고 완료됨', '배송 중', '배송 완료됨', '주문 취소됨'이라는 주문 상태가 있는데 이를 코드 상에서 STEP1, STEP2, STEP3, STEP4, STEP5, STEP6이라는 Enum 상수로 표현되어있을 수 있다
    • 이렇게 구현이 이루어져 있다면 개발자는 코드↔도메인 용어 해석 과정에서 어려움을 겪게 될 것이다
    • 도메인 용어를 사용해서 PAYMENT_WATING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED라는 Enum 상수로 표현한다면 더욱 읽기 쉬운 코드가 될 것이다
  • 에릭 에반스는 도메인 주도 설계에서 언어의 중요함을 강조하기 위해 유비쿼터스 언어(ubiquitous language)라는 용어를 사용했다
    • 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고 이를 대화, 문서, 도메인 모델, 코드, 테스트 등 모든 곳에서 같은 용어를 사용한다
    • 이렇게 하면 용어의 모호함을 줄이고 불필요한 해석 과정을 줄일 수 있다
    • 시간이 지나 도메인에 대한 이해가 높아지면 새롭게 이해된 내용을 잘 표현할 수 있는 용어를 찾아내고 이를 다시 공통의 언어로 만들어 함께 사용한다
    • 새로 발견한 용어는 코드나 문서에도 반영해서 산출물에 최신 모델을 적용한다
  • 영어로 코드를 작성해야 하는 환경 때문에 도메인 용어를 영어로 해석하는 노력이 필요하다
    • 알맞은 영단어를 찾는 것은 쉽지 않은 일이지만 시간을 들여 찾는 노력을 해야 한다
    • 도메인에 어울리지 않는 단어를 사용하면 코드는 도메인과 점점 멀어지게 된다
저작자표시 비영리 (새창열림)

'책 > 도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지' 카테고리의 다른 글

[도메인 주도 개발 시작하기] 6장: 응용 서비스와 표현 영역  (0) 2022.10.14
[도메인 주도 개발 시작하기] 5장: 스프링 데이터 JPA를 이용한 조회 기능  (0) 2022.10.07
[도메인 주도 개발 시작하기] 4장: 리포지터리와 모델 구현  (0) 2022.10.03
[도메인 주도 개발 시작하기] 3장: 애그리거트  (1) 2022.09.20
[도메인 주도 개발 시작하기] 2장: 아키텍처 개요  (0) 2022.09.16
  1.  
  2. 1.1 도메인이란?
  3. 1.2 도메인 전문가와 개발자 간 지식 공유
  4. 1.3 도메인 모델
  5. 1.4 도메인 모델 패턴
  6. 1.5 도메인 모델 표출
  7. 1.6 엔티티와 밸류
  8. 1.7 도메인 용어와 유비쿼터스 언어
'책/도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지' 카테고리의 다른 글
  • [도메인 주도 개발 시작하기] 5장: 스프링 데이터 JPA를 이용한 조회 기능
  • [도메인 주도 개발 시작하기] 4장: 리포지터리와 모델 구현
  • [도메인 주도 개발 시작하기] 3장: 애그리거트
  • [도메인 주도 개발 시작하기] 2장: 아키텍처 개요
코택
코택
TaxFree코택 님의 블로그입니다.
코택
TaxFree
코택
전체
오늘
어제
  • 분류 전체보기 (369)
    • Spring (29)
      • Spring (18)
      • 스프링 핵심 원리 - 고급편 (11)
    • Spring Batch (4)
    • JPA (4)
    • CS (89)
      • 자료구조 (2)
      • 네트워크 (5)
      • 운영체제 (1)
      • 데이터베이스 (4)
      • SQL (7)
      • 알고리즘 이론 (4)
      • 알고리즘 문제 풀이 (66)
    • 웹 (28)
      • React.js (4)
      • Next.js (1)
      • Node.js (14)
      • FastAPI (4)
      • Django (5)
    • 프로그래밍 언어 (45)
      • Python (5)
      • Java + Kotlin (29)
      • JavaScript + TypeScript (11)
    • 테스트코드 (26)
      • ATDD, 클린 코드 with Spring (4)
      • 이규원의 현실 세상의 TDD: 안정감을 주는 코드.. (20)
    • 인프라 (6)
      • AWS (2)
      • Kubernetes (4)
    • 트러블슈팅 (25)
    • 책 (89)
      • Effective Java (54)
      • Effective Kotlin (14)
      • 도메인 주도 개발 시작하기: DDD 핵심 개념 정.. (11)
      • 웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 (6)
      • 도메인 주도 설계 첫걸음 (4)
    • Git (10)
    • 회고 (5)
    • etc (8)

블로그 메뉴

  • 홈
  • 방명록
  • 관리
  • GitHub
  • LinkedIn

공지사항

  • 스킨 관련

인기 글

태그

  • BOJ
  • 백준
  • http
  • 그래프 탐색
  • fastapi
  • 브루트포스
  • mysql
  • atdd
  • Shortest Path
  • 장고
  • Git
  • 그래프
  • 깊이 우선 탐색
  • 파이썬
  • dp

최근 댓글

최근 글

hELLO · Designed By 정상우.
코택
[도메인 주도 개발 시작하기] 1장: 도메인 주도 개발 시작하기
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.