[ 컴포넌트 구성 원리 ]
복잡한 시스템을 작고 독립적인 컴포넌트로
구성하기 위한 설계 원리다.
컴포넌트는 보통 패키지 단위(Java의 package)로
묶이는 클래스 집합을 의미한다.
컴포넌트 구성 원리는 결국 두 가지를 결정한다.
- 어떤 클래스를 어떤 컴포넌트(패키지) 안에 넣을 것인가
- 컴포넌트 사이 의존관계를 어떻게 만들 것인가
목표는 컴포넌트 내부는 높은 응집,
컴포넌트 사이는 낮은 결합을 유지하는 것이다.
컴포넌트를 잘못 나누면 생기는 문제
현대의 복잡한 시스템은
컴포넌트를 독립적으로 개발하고
독립적으로 배포 가능한 단위로 설계해야 한다.
하지만 어떤 컴포넌트가 다른 컴포넌트에
과하게 의존하면 다음 문제가 생긴다.
- 작은 변경이 여러 컴포넌트 수정으로 번진다
- 배포 단위가 꼬여서 작은 수정도
여러 컴포넌트 재배포가 된다 - 유지보수 비용이 증가하고
장애 대응이 늦어진다
그래서 컴포넌트 구성 원리는 작고
관리하기 쉬운 컴포넌트(패키지)를
만들기 위한 기준을 제공한다.
구성 원리의 큰 분류
이 장의 원리는 크게 두 축으로 정리된다.
1) 제어 역전(Hollywood 원리)
컴포넌트 사이 의존관계를 관리해
낮은 결합을 유지하는 원리
2) 패키지 설계 원리
재사용성과 유지보수성을 높이기 위한
패키징 원리(REP, CCP, CRP)
제어 역전
1) 의존관계의 기본 형태
ClassA가 ClassB가 제공하는 서비스를
사용하려면 ClassA는 ClassB에 종속된다.
이때 ClassB가 변경되면 ClassA도
영향을 받기 쉬워 결합도가 올라간다.
ClassA ---> ClassB
2) 제어 역전(Dependency Inversion)과 Hollywood 원리
제어 역전은 의존을 구체 클래스가 아니라
인터페이스/추상화에 걸도록 바꿔
결합을 낮추는 방향이다.
대규모 시스템에서는 프레임워크를 많이 사용한다.
프레임워크는 UI, DB, 라이브러리 등
외부 컴포넌트를 포함한 실행 흐름을 제공하고,
개발자가 작성한 코드는 그 흐름 속에서 호출되는 방식이 된다.
이런 구조를 요약한 표현이 Hollywood 원리다.
전화하지 마세요. 우리가 전화합니다
즉, 하위 요소가 상위 요소를 직접 호출하는 방식보다,
상위 요소가 필요할 때 하위 요소를 호출하도록 흐름을 구성한다.
[상위 흐름/프레임워크]
|
v
[하위 요소/애플리케이션 코드]
3) 의존성 주입(DI)
의존성 주입은 제어 역전을 구현하는 대표적인 방법이다.
객체를 직접 생성하지 않고 외부에서 주입받도록 만들면
결합이 느슨해지고 테스트가 쉬워진다.
ClassA ---> Service <--- ClassB
public interface Service {
String getInfo();
}
public class ClassB implements Service {
@Override
public String getInfo() {
return null;
}
}
public class ClassA {
private final Service service;
public ClassA(Service service) {
this.service = service;
}
public void doSomething() {
String info = service.getInfo();
}
}
ClassA는 Service에만 의존하고,
어떤 구현체를 사용할지는 외부에서 결정한다.
패키지 설계 원리
대규모 시스템에서는 컴포넌트를
독립적으로 배포 가능한 가장 작은 단위로 본다.
예를 들면 Java의 jar 같은 단위다.
재사용 가능한 패키지로 설계할 때
적용되는 원리는 REP, CCP, CRP 세 가지다.
1) 재사용, 릴리스 등가의 원리(REP)
패키지는 재사용 가능한 단위여야 하고,
독립적으로 배포할 수 있도록
응집력 높은 클래스들로 구성되어야 한다.
재사용되는 단위와 릴리스(배포) 단위는 같아야 한다.
2) 공통 폐쇄의 원리(CCP)
한 패키지에는 동일한 이유로
동일한 시점에 변경되는 기능이 있어야 한다.
같이 변경되는 것들은 같이 묶어
변경의 파급을 패키지 내부로 제한한다.
3) 공통 재사용의 원리(CRP)
함께 사용되거나 함께 재사용되는
컴포넌트들은 함께 패키징되어야 한다.
어떤 컴포넌트에 의존하게 되면
패키지화된 컴포넌트 안의 기능들에도
함께 의존하게 되므로 관련 없는 기능이 섞이면
불필요한 종속이나 성능 저하 같은 문제가 생길 수 있다.
세 원리의 균형
세 가지 원리는 서로 상충할 수 있으므로 균형이 필요하다.
REP
/\
/ \
/ \
CCP ---------- CRP
- REP와 CCP를 과하게 따르면 패키지가 커져
작은 변경도 영향 범위가 커질 수 있다 - CRP를 과하게 따르면 패키지가 잘게 나뉘어
구조 관리가 복잡해질 수 있다
설계 원리 적용 예시
사용자 관리 기능과 관련된 클래스가 다음과 같다고 하자.
- User
- UserService
- UserRepository
package com.example.usermanagement;
public class User {
private String id;
private String name;
// Getters and setters
}
public class UserService {
public void createllser(User user) {
// Logic to create user
}
public User getUser(String id) {
// Logic to get user
return new User();
}
}
public class UserRepository {
public void save(User user) {
// Logic to save user
}
public User findById(String id) {
// Logic to find user by id
return new User();
}
}
이 클래스들은 서로 의존하고
함께 변경될 가능성이 높으므로
com.example.usermanagement 같은
패키지로 묶는 것이 자연스럽다.
이렇게 묶으면 변경 관리가 쉬워지고,
패키지 버전이 올라갈 때 관련 클래스들이
함께 업데이트되어 일관성과 호환성이 보장되기 쉽다.
[ 마무리 ]
- 컴포넌트 구성 원리는 패키지 단위로
클래스를 묶고 컴포넌트 사이 의존을 관리해
유지보수와 배포를 쉽게 만드는 설계 기준이다 - 제어 역전은 추상화에 의존하도록 만들고,
실행 흐름은 상위 요소가
하위 요소를 호출하도록 구성한다 - 패키지 설계 원리(REP, CCP, CRP)는 재사용,
변경 관리, 불필요한 의존 제거를 균형 있게 고려하게 한다
'개주 훈련일지 > 📚 코살대 교본 학습' 카테고리의 다른 글
| 아키텍처 기초 (0) | 2026.02.09 |
|---|---|
| SQL) 윈도우 함수 (0) | 2026.02.08 |
| 객체지향 설계 원리 (1) | 2026.02.06 |
| SQL) 그룹 함수 (0) | 2026.02.02 |
| 전통적인 설계 원리 (0) | 2026.02.01 |