이 프로젝트는 SpringBoot를 사용하여 **단일 책임 원칙(Single Responsibility Principle)**의 위반 사례와 준수 사례를 명확하게 비교할 수 있도록 만든 도서관 관리 시스템입니다.
src/
├── main/
│ ├── java/com/designpattern/
│ │ ├── bad/ # SRP 위반 예제
│ │ │ ├── BadBookEntity.java
│ │ │ ├── BadLibraryService.java (모든 책임이 한 클래스에)
│ │ │ ├── BadBookRepository.java
│ │ │ └── BadLibraryController.java
│ │ │
│ │ ├── good/ # SRP 준수 예제
│ │ │ ├── domain/
│ │ │ │ ├── Book.java (오직 데이터만 담당)
│ │ │ │ └── Borrow.java
│ │ │ ├── service/
│ │ │ │ ├── BookService.java
│ │ │ │ ├── BorrowService.java
│ │ │ │ ├── LateFeeCalculator.java
│ │ │ │ ├── EmailService.java
│ │ │ │ ├── PaymentService.java
│ │ │ │ ├── LoggingService.java
│ │ │ │ └── StatisticsService.java
│ │ │ ├── validator/
│ │ │ │ ├── BookValidator.java
│ │ │ │ └── BorrowerValidator.java
│ │ │ ├── formatter/
│ │ │ │ ├── BookFormatter.java
│ │ │ │ ├── PersonFormatter.java
│ │ │ │ └── DateTimeFormatter.java
│ │ │ ├── facade/
│ │ │ │ └── LibraryFacade.java (여러 서비스 조율)
│ │ │ ├── repository/
│ │ │ │ ├── BookRepository.java
│ │ │ │ └── BorrowRepository.java
│ │ │ └── controller/
│ │ │ └── LibraryController.java
│ │ │
│ │ ├── IndexController.java
│ │ └── SampleApplication.java
│ │
│ └── resources/
│ ├── templates/ # Mustache 템플릿
│ │ ├── bad/ # 나쁜 예제용 페이지
│ │ ├── good/ # 좋은 예제용 페이지
│ │ └── index.mustache # 메인 페이지
│ ├── static/
│ │ ├── css/
│ │ │ ├── bad-style.css # 나쁜 예제용 CSS
│ │ │ └── good-style.css # 좋은 예제용 CSS
│ │ └── js/
│ │ ├── bad-script.js # SRP 위반 JS 코드
│ │ └── good-script.js # SRP 준수 JS 코드
│ │
│ └── application.yml
- Framework: Spring Boot 3.4.4
- Language: Java 17
- Database: H2 (인메모리)
- Template Engine: Mustache
- Frontend: HTML, CSS, Vanilla JavaScript
- Build Tool: Gradle
- BadLibraryService: 13가지 이상의 책임을 가진 거대한 클래스
- 도서 CRUD
- 대출/반납 처리
- 결제 처리
- 이메일 발송
- 로깅
- 통계 계산
- 유효성 검증
- 데이터 포매팅
- 암호화
- 파일 입출력
- BadBookEntity: 비즈니스 로직이 포함된 Entity
- JavaScript: 모든 기능이 한 파일에 스파게티 코드로 구현
- 명확한 책임 분리:
BookService: 도서 관련 비즈니스 로직만BorrowService: 대출/반납 로직만EmailService: 이메일 발송만PaymentService: 결제 처리만LoggingService: 로깅만LateFeeCalculator: 연체료 계산만
- Facade 패턴:
LibraryFacade가 여러 서비스를 조율 - Clean Entity: Domain 객체는 오직 데이터만 담당
- JavaScript: 각 모듈이 단일 책임만 가지도록 구조화
- 저장소 클론
git clone [repository-url]
cd sample- 애플리케이션 실행
./gradlew bootRun- 브라우저에서 접속
http://localhost:8080
- 메인 페이지 (
/): 나쁜 예제와 좋은 예제 소개 - 나쁜 예제 (
/bad/books): SRP 위반 사례 체험 - 좋은 예제 (
/good/books): SRP 준수 사례 체험
- 높은 결합도: 하나의 변경이 전체에 영향
- 테스트의 어려움: 많은 의존성으로 인한 복잡한 테스트
- 코드 재사용 불가: 특정 기능만 떼어내기 어려움
- 가독성 저하: 긴 메서드와 복잡한 로직
- 낮은 결합도: 독립적인 모듈들
- 높은 응집도: 관련된 기능만 함께 위치
- 쉬운 테스트: 단위 테스트 작성 용이
- 유지보수성: 변경이 필요한 부분만 수정
- 확장성: 새로운 기능 추가 용이
- 클래스 크기:
BadLibraryServicevs 분리된 여러 서비스들 - 메서드 길이: 나쁜 예제의 긴 메서드 vs 좋은 예제의 짧은 메서드
- 의존성: 나쁜 예제의 높은 결합도 vs 좋은 예제의 의존성 주입
- 테스트: 나쁜 예제는 모킹이 복잡, 좋은 예제는 단위 테스트 용이
- [SOLID 원칙에 대한 자세한 설명]
- [Clean Code 관련 서적]
- [Design Patterns]
이 프로젝트는 학습 목적으로 만들어졌습니다. 더 좋은 예제나 개선사항이 있다면 언제든 기여해주세요!
MIT License