패키지를 어떻게 나눌까?
패키지를 어떻게 나눌지 결정하는 과정에서 다음과 같은 개념을 활용할 수 있습니다.
- 모듈화(Modulatiry): SW 시스템을 독립적인 모듈로 나누어 관리합니다. 패키지 구조를 통해 모듈화를 실현합니다.
- 추상화(Abstraction): 복잡한 시스템을 단순하게 표현합니다. 패키지 구조는 시스템을 더 높은 수준의 추상화로 나누어 복잡성을 관리합니다.
- 캡슐화(Encapsulation): 데이터와 메서드를 하나의 단위로 묶어 외부에서 접근을 제한하는 원칙입니다. 패키지 구조는 캡슐화를 강화하여 모듈 간 의존성을 줄입니다.
- 계층화(Layering): 시스템을 계층으로 나누어 각 책임과 역할을 분명히 합니다. Layer by Package 방식은 이러한 계층화 원리를 반영합니다.
- 응집도(Cohesion)와 결합도(Coupling): 모듈 내부의 요소들이 얼마나 밀접하게 관련되어 있는지(응집도), 모듈 간 상호의존성이 얼마나 낮은지(결합도)를 평가하는 개념입니다. 패키지 구조를 설계할 때, 높은 응집도와 낮은 결합도를 유지하는 것이 중요합니다.
Feature by Package vs. Layer by Package 비교 분석
구분 | Feature by Package | Layer by Package |
구조 | - 애플리케이션의 기능(feature)별로 디렉토리를 나눔 - 각 기능 내에 관련된 모든 클래스 배치(data, model, service) - 모든 기능의 코드는 이 계층별 디렉토리에 섞여있음 |
- 애플리케이션의 계층(layer)별로 디렉토리를 나눔 - 각 계층 내에서 클래스를 배치 - 모든 기능의 코드가 이 계층별 디렉토리에 섞여있음 |
장점 | - 기능별 모듈화: 각 기능이 독립적으로 관리 → 특정 기능을 찾거나 유지보수할 때 직관적, 효율적 - 팀 작업 용이성: 여러 팀이 서로 다른 기능을 동시에 작업할 때 충돌이 적음, 각 기능이 별도의 디렉토리에 있기에 기능간 의존성을 최소화할 수 있음 - 확장성: 새로운 기능 추가 시, 관련된 코드만 새로운 디렉토리에 모아두면 됨 따라서 프로젝트가 커져도 구조가 복잡해지지 않음 |
- 레이어별 명확한 역할 구분: 각 레이어가 명확하게 구분되어 레이어 간 의존성을 쉽게 관리할 수 있음 (ex: 컨트롤러는 서비스만 호출, 서비스는 리포지토리만 호출 → 계층간 규칙 강제 적용 가능) - 공통 코드 관리 용이: 여러 기능에서 공통으로 사용하는 코드를 한 곳에 모아두어 코드 중복이 적고, 공통된 비즈니스 로직을 쉽게 유지보수 할 수 있음 - 코드 일관성: 모든 기능이 동일한 방식으로 계층화되어 있어서, 새로운 기능 추가시 일관된 구조를 유지할 수 있음 |
단점 | - 공통 코드 관리의 복잡성: 여러 기능에서 공통으로 사용되는 코드나 로직을 관리하기 위해 util, common과 같은 디렉토리 필요 - 중복 코드: 기능별로 분리하다 보니 비슷한 코드가 여러 기능에 중복될 가능성이 있음 |
- 기능간 의존성 증가: 기능별로 코드를 분리하기 어렵기 때문에, 특정 기능 수정/확장 시 다른 기능에 영향을 미칠 가능성이 높음 - 복잡성 증가: 프로젝트가 커질수록 특정 기능에 관련된 코드를 찾기 어려워질 수 있음 (ex: 예약 기능과 관련된 모든 파일이 각 레이어에 흩어져 있으면, 이 기능을 관리할 때 많은 디렉토리를 탐색해야 함) - 확장성 제한: 새로운 기능이 생길 때마다 기존 레이어에 코드를 추가해야 하기 때문에, 레이어간 의존성이 증가하고 프로젝트가 복잡해질 수 있음 |
사용 사례 | - MSA: 독립적으로 배포할 수 있는 소규모 서비스의 모음, 각 서비스가 독립적으로 운영될 때 적합함 - 대규모 프로젝트: 기능별로 팀을 나누어 개발할 때, 각 팀이 독립적으로 작업할 수 있어서 유리함 |
- 모놀리식 아키텍처(SW 전통적인 모델): 하나의 통합된 유닛, 모든 기능이 한번에 배포되고 동일한 레이어 구조로 관리될 때 적합함 - 소규모 프로젝트: 기능이 적고 코드가 비교적 간단할 때 이 방식이 편리함 |
- MSA와 모놀리식 아키텍처
- MSA
💡독립 배포, 운영
- 독립적으로 배포 가능한 일련의 서비스를 이용하는 아키텍처 방법입니다. 팀이 사용자 요구사항을 빠르게 적응할 수 있도록 CI/CD를 기반으로 합니다. 따라서 DevOps 채택과 함께 이루어지는 경우가 많습니다.
- *DevOps: 개발과 운영을 통합하여 효율성, 협력, 속도, 안정성을 개선하는 개발 및 운영 방법론
- 다른 서비스에 영향을 주는 일 없이 각 서비스를 개발, 업데이트, 배포 및 확장할 수 있습니다. 향상된 안정성과 가동 시간 및 성능으로 SW 업데이트를 더 자주 수행할 수 있습니다.
- 다만, 여러 팀이 더 많은 장소에서 더 많이 서비스를 만들기 때문에 모놀리스 아키텍처에 비해 더 복잡해집니다. 무분별한 개발 확산이 적절하게 관리되지 않으면 개발 속도가 느려지고, 운영 성능이 저하되는 결과가 나타납니다.
- Netflix: 2009년 IT 인프라를 프라이빗 데이터 센터에서 퍼블릭 클라우드로 마이그레이션, 모놀리식 아키텍처를 MSA로 대체하기로 결정했습니다. 오늘날 Netfilx는 플랫폼의 개별 부분을 관리하고 지원하는 1,000개 이상의 마이크로 서비스를 가지고 있고 엔지니어는 코드를 때로는 매일 수천 번에 달할 정도로 자주 배포합니다.
- 독립적으로 배포 가능한 일련의 서비스를 이용하는 아키텍처 방법입니다. 팀이 사용자 요구사항을 빠르게 적응할 수 있도록 CI/CD를 기반으로 합니다. 따라서 DevOps 채택과 함께 이루어지는 경우가 많습니다.
- 모놀리식 아키텍처
💡중앙 집중식- 모든 비즈니스 관련 사항을 결합해 하나의 코드 베이스를 갖춘 대규모 단일 컴퓨팅 네트워크입니다.
- 하나의 코드 베이스에 기반을 두어 단순하기 때문에 개발 속도가 빠릅니다.
- 규모가 커지고 확장이 어려워지면 더 이상 효과적이지 않습니다.
why? 하나의 기능을 조금만 변경하려고 해도 전체 플랫폼을 컴파일하고 테스트해야 하기 때문에, 오늘날 개발자들이 선호하는 애자일 접근 방식과 맞지 않습니다.
- MSA
backend-1st-studycafe는 어떤 구조일까?
src/
├── main/
│ ├── java/
│ │ └── com/example/
│ │ ├── common/ # 가격 및 좌석 타입을 관리하는 클래스
│ │ ├── reservation/ # 예약 관련 DAO, 모델, 서비스
│ │ ├── seat/ # 좌석 관련 DAO, 모델, 서비스
│ │ ├── user/ # 사용자 관련 DAO, 모델, 서비스
│ │ └── util/ # DB 연결 유틸리티 클래스
│ └── resources/
│ └── jdbc.properties # MySQL 연결 설정 파일
- Feature by Package: 예약, 좌석, 사용자와 같이 기능별로 디렉토리 구조를 나누었습니다.
- 선정 사유
- 독립적 개발: 팀원들이 여러 기능을 개발하더라도 서로의 작업에 영향을 미치지 않게 하려고, 독립적인 개발을 수행하기 위해서
- 협업의 효율성 최대화: 서로 다른 기능을 작업하고 합칠 때 코드간 충돌을 초소화하기 위해서
- 유지보수 용이성: 기능별로 명확한 구조로 추후 유지보수나 확장이 용이하기 때문에 Feature based로 디렉토리 구조를 나누었습니다.
- 선정 사유
- 디렉토리 구조에 대한 상세 내용은 다음과 같습니다.
- common: 프로젝트 전반에 걸쳐 여러 기능에서 공통으로 사용되는 코드를 모아두었습니다. (Price, Seat type)
- reservation: 스터디 카페 예약과 관련한 모든 로직을 모아둔 디렉토리입니다. 여기에는 예약과 관련된 DAO, 모델, 서비스 클래스가 들어가 있습니다. (좌석 예약)
- DAO (Data Access Object)
- 데이터베이스 CRUD 작업을 수행합니다.
- SQL 쿼리를 실행하여 데이터베이스에서 가져온 데이터를 애플리케이션의 객체로 변환합니다.
- 데이터베이스에 저장할 객체를 SQL 쿼리로 변환하여 데이터베이스에 저장합니다.
- 데이터베이스의 세부 구현을 캡슐화하여 서비스 계층이 데이터베이스와 상호작용 시, SQL 쿼리나 연결 세부사항을 알 필요가 없도록 합니다. - 모델 (Model)
- 애플리케이션에서 사용하는 데이터 구조를 정의합니다.
- 필드, Getters, Setters로 비즈니스 도메인의 데이터를 표현하는 클래스입니다. - 서비스 (Service)
- 애플리케이션의 비즈니스 로직을 처리합니다.
- 사용자 요청을 처리하기 위해 DAO 계층을 호출하고, 필요한 데이터베이스 작업을 수행합니다.
- 데이터의 상태를 변경하거나 계산을 수행하고, 최종 결과를 Main.java에 반영합니다.
- DAO (Data Access Object)
- seat: 스터디 카페 좌석과 관련된 모든 로직을 모아둔 디렉토리입니다. (좌석 선택, 인원 확인)
- user: 스터디 카페 사용자와 관련된 모든 로직을 모아둔 디렉토리입니다. (로그인, 보유 시간 확인 및 충전)
- util: DB 연결 로직을 수행합니다.
- resources: 자주 사용하는 리소스를 관리합니다. (데이터베이스 설정 파일)
- 현재 디렉토리 구조를 Layer by Package 방식으로 변환한다면?
src/
├── main/
│ ├── java/
│ │ └── com/example/
│ │ ├── service/ # 비즈니스 로직 처리
│ │ │ ├── ReservationService.java
│ │ │ ├── SeatService.java
│ │ │ └── UserService.java
│ │ ├── repository/ # 데이터베이스와 상호작용(CRUD)
│ │ │ ├── ReservationDAO.java
│ │ │ ├── SeatDAO.java
│ │ │ └── UserDAO.java
│ │ ├── model/ # 데이터 구조 정의(필드, Getter, Setter)
│ │ │ ├── Reservation.java
│ │ │ ├── Seat.java
│ │ │ └── User.java
│ │ ├── common/ # 가격 및 좌석 타입을 관리하는 클래스
│ │ └── util/ # DB 연결 유틸리티 클래스
│ └── resources/
│ └── jdbc.properties # MySQL 연결 설정 파일
프로젝트
참고자료
반응형
'CS' 카테고리의 다른 글
[REST API] REST API 개념, 구성요소, 특징, RESTful API (1) | 2024.11.24 |
---|