1.1 도서관리 시스템 개요

1.1 도서관리 시스템 개요

1. 프로젝트 소개

1.1 프로젝트 목적

이 프로젝트는 도서관 관리 시스템을 구현하면서 도메인 주도 설계(DDD)와 클린 아키텍처의 핵심 개념들을 실제로 적용해보고 이해하는 것을 주된 목적으로 합니다. 실제 비즈니스 도메인을 통해 이론적 개념들을 실전에서 경험하고, 개발자로서의 역량을 향상시키는 것을 지향합니다.

1.2 학습 목표

  1. 도메인 주도 설계(DDD) 이해와 적용
    • 유비쿼터스 언어의 실제 사용 경험
    • 바운디드 컨텍스트 식별과 컨텍스트 매핑 실습
    • 애그리거트와 도메인 이벤트 설계 경험
    • 도메인 객체의 불변식(invariants) 구현
  2. 클린 아키텍처 구현
    • 계층형 아키텍처의 실제 구현
    • 의존성 규칙의 실천적 적용
    • 유스케이스 중심의 설계 경험
    • SOLID 원칙의 실제 적용
  3. 개발 역량 향상
    • 도메인 분석과 모델링 능력 개발
    • 테스트 주도 개발(TDD) 실천
    • 이벤트 스토밍 수행 경험
    • 지속적 리팩토링 경험

1.3 도메인 학습 범위

도서관 관리 시스템이라는 실제 비즈니스 도메인을 통해 다음과 같은 도메인 문제를 다룹니다:

  • 복잡한 대출/반납 규칙의 구현
  • 도서와 도서 인쇄본의 구분된 모델링
  • 회원 등급과 권한의 설계
  • 예약 시스템의 동시성 처리

2. 핵심 기능

본 시스템은 다음과 같은 핵심 기능을 제공합니다.

2.1 회원 관리

  • 회원 가입/탈퇴 프로세스
    • 이메일 기반 회원 인증
    • 개인정보 보호 규정 준수
    • 회원 등급별 차등 서비스 제공
  • 회원 활동 관리
    • 대출/반납 이력 추적
    • 연체 관리 및 자동 제재
    • 개인화된 도서 추천

2.2 도서 관리

  • 도서 등록 및 관리
    • ISBN 기반 도서 정보 등록
    • 도서 상태 실시간 추적
    • 도서 위치 정보 관리
  • 도서 검색 시스템
    • 다중 조건 검색 지원
    • 실시간 재고 확인
    • 연관 도서 추천

2.3 대출/반납 서비스

  • 대출 프로세스
    • 회원 자격 실시간 검증
    • QR코드 기반 신속 대출
    • 연체 자동 알림

대출/반납 처리

  • 반납 프로세스
    • 무인 반납 시스템 연동
    • 반납 상태 자동 검증
    • 연체료 자동 계산

**도서(Book)**는 제목, 저자, ISBN 등의 메타 정보를 가진 추상적인 저작물을 의미하고, **도서 인쇄본(BookCopy)**는 실제 물리적인 책 한 권을 의미하며, 하나의 도서는 여러 개의 인쇄본을 가질 수 있습니다.

3. 기술 스택과 아키텍처

3.1 기술 스택 선정 배경

도메인 주도 설계와 클린 아키텍처를 효과적으로 학습하기 위해 다음과 같은 기술 스택을 선정했습니다.

백엔드 기술

Java 17을 선택한 이유는 다음과 같습니다:

  • 강력한 타입 시스템을 통해 도메인 모델을 명확하게 표현할 수 있습니다.
  • 레코드(Record)를 활용하여 불변 객체를 쉽게 구현할 수 있습니다.
  • 패턴 매칭을 통해 도메인 규칙을 더 명확하게 표현할 수 있습니다.
  • 실무에서 가장 많이 사용되는 언어로, 학습한 내용을 실제 프로젝트에 적용하기 좋습니다.

Spring Boot를 선택한 이유는 다음과 같습니다:

  • 의존성 주입을 통해 클린 아키텍처의 의존성 규칙을 쉽게 구현할 수 있습니다.
  • AOP를 통해 도메인 로직과 기술적 관심사를 분리할 수 있습니다.
  • 이벤트 기반 프로그래밍을 지원하여 도메인 이벤트를 효과적으로 구현할 수 있습니다.
  • 트랜잭션 경계를 명확하게 설정할 수 있어 애그리거트의 일관성을 보장하기 좋습니다.

데이터베이스

JPA/Hibernate를 선택한 이유는 다음과 같습니다:

  • 도메인 모델과 데이터베이스 모델을 분리하여 클린 아키텍처를 구현하기 용이합니다.
  • 애그리거트 단위의 영속성 관리가 가능합니다.
  • 낙관적 락킹을 통해 동시성 제어를 구현할 수 있습니다.
  • 값 객체와 엔티티를 효과적으로 매핑할 수 있습니다.

3.2 아키텍처 설계

클린 아키텍처의 원칙을 따르면서 DDD 개념을 효과적으로 구현하기 위해 다음과 같은 계층 구조를 채택했습니다:

도메인 계층

도메인 모델의 핵심 로직을 포함하는 계층입니다:

// 도메인 객체는 외부 의존성 없이 순수하게 구현됩니다
public class Book {
    private final BookId id;
    private Title title;
    private Author author;
    private BookStatus status;

    // 도메인 로직은 도메인 객체 안에 캡슐화됩니다
    public void markAsLost() {
        if (status != BookStatus.BORROWED) {
            throw new IllegalStateException("대출 중인 도서만 분실 처리할 수 있습니다.");
        }
        this.status = BookStatus.LOST;
    }
}

응용 계층

유스케이스를 구현하고 도메인 객체를 조율하는 계층입니다:

// 포트와 어댑터 패턴을 통해 외부 시스템과의 의존성을 역전시킵니다
public class LoanBookCommandHandler {
    private final BookRepository bookRepository;    // 포트
    private final MemberRepository memberRepository;// 포트
    private final EventPublisher eventPublisher;    // 포트

    public LoanResult handle(LoanCommand command) {
        // 유스케이스의 흐름을 명확하게 표현합니다
        var book = bookRepository.findById(command.getBookId());
        var member = memberRepository.findById(command.getMemberId());
        
        var loan = member.loanBook(book);  // 도메인 로직은 도메인 객체에 위임
        
        bookRepository.save(book);
        eventPublisher.publish(new BookLoanedEvent(loan));
        
        return LoanResult.success(loan);
    }
}

인프라 계층

기술적 구현을 담당하는 계층입니다:

// 실제 구현은 인프라 계층에서 이루어집니다
@Repository
public class JpaBookRepository implements BookRepository {
    private final BookJpaRepository repository;
    
    @Override
    public Book findById(BookId id) {
        return repository.findById(id.getValue())
                .map(this::toDomain)
                .orElseThrow(() -> new BookNotFoundException(id));
    }
}

3.3 개발 환경 설정

학습 효과를 극대화하기 위해 다음과 같은 개발 환경을 구성합니다:

필수 도구

  • IntelliJ IDEA : 강력한 리팩토링 도구와 디버깅 기능을 제공합니다.
  • Docker: 개발 환경의 일관성을 보장합니다.
  • Git: 버전 관리와 함께 리팩토링 이력을 관리합니다.

로컬 개발 환경 설정

# 1. 프로젝트 클론
git clone https://github.com/your-org/library-system.git

# 2. 도커 컨테이너 실행
docker-compose up -d

# 3. 애플리케이션 실행
./gradlew bootRun

테스트 환경 설정

// 도메인 테스트는 외부 의존성 없이 실행할 수 있어야 합니다
class BookTest {
    @Test
    void 도서_분실_처리() {
        // Given
        Book book = new Book(BookId.newId(), "도메인 주도 설계", "에릭 에반스");
        book.loan(Member.newMember());
        
        // When
        book.markAsLost();
        
        // Then
        assertThat(book.getStatus()).isEqualTo(BookStatus.LOST);
    }
}

4. 프로젝트 진행 방식

4.1 이터레이션 계획

2주 단위의 이터레이션으로 진행하며, 각 이터레이션마다 다음과 같은 학습 주제를 다룹니다:

  1. 첫 번째 이터레이션: 도메인 모델 설계

    • 이벤트 스토밍을 통한 도메인 이해
    • 핵심 애그리거트 설계
    • 도메인 이벤트 정의
  2. 두 번째 이터레이션: 아키텍처 구현

    • 클린 아키텍처 적용
    • 의존성 주입 설정
    • 리포지토리 구현
  3. 세 번째 이터레이션: 비즈니스 규칙 구현

    • 도메인 서비스 구현
    • 트랜잭션 경계 설정
    • 동시성 제어

4.2 코드 리뷰 지침

  • 도메인 로직이 도메인 계층에 올바르게 구현되었는지 확인
  • 의존성 규칙 위반 여부 검토
  • 불변식이 명확하게 표현되었는지 검증
  • SOLID 원칙 준수 여부 확인

Last updated on