GRASP
GRASP(General Responsibility Assignment Software Patterns) 는 Craig Larman 이 제안한 객체지향 설계 원칙으로, 객체와 클래스에 책임을 할당하는 9 가지 핵심 패턴을 제공한다. 이 원칙들은 객체의 역할과 협력을 명확히 하여, 시스템의 유연성, 유지보수성, 확장성을 높이는 데 중점을 둔다. GRASP 는 Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations 등으로 구성되며, 실무에서 객체지향 설계의 기초이자 실질적인 지침으로 널리 활용된다.
핵심 개념
GRASP 의 핵심 개념은 " 책임 할당 (Responsibility Assignment)" 이다. 객체지향 설계에서 가장 중요한 의사결정은 어떤 클래스나 객체가 특정 책임을 담당해야 하는지 결정하는 것이다. 실무에 바로 적용 가능한 구체적이고 명확한 설계 지침이며, SOLID 원칙과 함께 객체지향 설계의 양대 축으로 활용된다.
책임의 두 가지 유형:
- 행동 책임 (Doing Responsibility): 객체 생성, 데이터 처리, 계산 수행, 다른 객체와의 협력 조정
- 인식 책임 (Knowing Responsibility): 개인 데이터, 관련 객체 참조, 파생 가능한 정보
배경 및 목적
GRASP 는 Craig Larman 이 1997 년 객체지향 설계의 경험과 모범 사례를 체계화하여 만든 원칙이다. 기존의 좋은 설계 관행들을 정리하고 표준화한 것으로, 새로운 방법론이 아닌 입증된 설계 원칙들의 집합이다.
목적 및 필요성:
- 객체지향 설계에서 책임 할당의 가이드라인 제공
- 낮은 결합도 (Low Coupling) 와 높은 응집도 (High Cohesion) 달성
- 유지보수성, 재사용성, 확장성이 높은 소프트웨어 개발
- 설계 의사결정에 대한 체계적 접근법 제공
GRASP 원칙
객체 설계 시 각 객체가 자신의 데이터와 행위에 대한 책임을 갖도록 하고, 변화에 강한 구조를 위해 결합도를 낮추고 응집도를 높인다.
시스템 이벤트 처리, 객체 생성, 데이터 관리 등에서 각 원칙을 조합하여 적용한다.
원칙 | 설명 |
---|---|
Information Expert | 책임을 수행하는 데 필요한 정보를 가장 많이 가진 클래스에 책임을 할당합니다. |
Creator | 객체 A 를 생성하는 책임을 객체 A 를 포함하거나 사용하는 객체 B 에 할당합니다. |
Controller | 시스템 이벤트를 처리하는 책임을 비 UI 클래스에 할당하여 UI 와 비즈니스 로직을 분리합니다. |
Low Coupling | 클래스 간의 결합도를 낮춰 변경에 대한 영향을 최소화하고 재사용성을 높입니다. |
High Cohesion | 클래스의 책임을 관련 있는 기능으로 묶어 응집도를 높이고 유지보수성을 향상시킵니다. |
Polymorphism | 타입에 따라 변하는 행위를 해당 타입의 클래스에 할당하여 유연성을 확보합니다. |
Pure Fabrication | 도메인 개념과 직접 관련이 없지만 시스템 설계를 개선하기 위해 인위적으로 만든 클래스를 도입합니다. |
Indirection | 두 클래스 간의 직접적인 결합을 피하기 위해 중재자 역할의 클래스를 도입합니다. |
Protected Variations | 변동성이 예상되는 요소를 인터페이스로 감싸고 이를 통해 다른 요소들이 영향을 받지 않도록 보호합니다. |
설명:
- 시스템 이벤트를 Controller가 수신하고 처리.
- Controller 는 도메인 객체 생성을 Creator로 위임.
- 도메인 객체는 정보 중심으로 책임을 갖는 Information Expert.
- 다형성과 변동성 보호는 Polymorphism과 Protected Variations로 처리.
- 설계 품질 개선을 위해 Low Coupling, High Cohesion, Indirection, Pure Fabrication을 적용.
graph TD User-->|Event|Controller Controller-->|Delegates|InformationExpert InformationExpert-->|Uses|PureFabrication Controller-->|Creates|Creator Controller-->|Uses|Indirection Indirection-->|Protects|ProtectedVariations InformationExpert-->|Polymorphism|Polymorphism
Information Expert (정보 전문가)
원칙: 데이터를 가장 많이 가진 클래스에 책임을 할당한다.
예시: Order
객체가 총합 계산 책임을 가짐
|
|
Creator (생성자)
원칙: A 객체가 B 객체를 포함하거나 사용하는 경우 A 가 B 를 생성해야 한다.
예시: Order
가 OrderItem
을 생성
Controller
원칙: 시스템 이벤트를 처리하는 객체는 UI 외부에 존재해야 한다.
예시: OrderController
가 요청을 처리
Low Coupling (낮은 결합도)
원칙: 의존성을 줄여 유지보수성을 높인다.
예시: 인터페이스 추상화
|
|
High Cohesion (높은 응집도)
원칙: 관련 기능을 한 클래스에 집중
예시: Order
는 주문 관련 기능만 포함
Polymorphism (다형성)
원칙: 다양한 구현을 동일한 인터페이스로 처리
예시: 다양한 결제 방식
|
|
Pure Fabrication (순수 창작)
원칙: 설계 품질을 높이기 위한 비도메인 클래스
예시: EmailService
는 도메인과 무관하지만 필요
Indirection (간접화)
원칙: 두 객체 사이의 직접 의존을 줄이기 위한 중개자 사용
예시: PaymentProcessor
가 중개자 역할
Protected Variations (변경 보호)
원칙: 변경 가능성이 높은 부분을 인터페이스로 감싸 보호
예시: 인터페이스로 다양한 결제 방식을 보호
|
|
장점과 단점
구분 | 항목 | 설명 |
---|---|---|
✅ 장점 | 명확한 설계 가이드라인 | 객체 책임 할당에 대한 체계적 접근법 제공 |
높은 유지보수성 | 낮은 결합도와 높은 응집도로 변경 용이 | |
재사용성 향상 | 모듈화된 설계로 컴포넌트 재사용 증대 | |
확장성 | 다형성과 보호된 변형으로 시스템 확장 용이 | |
⚠ 단점 | 초기 복잡성 | 설계 초기에 많은 고민과 분석 필요 |
과도한 추상화 위험 | 잘못 적용시 불필요한 복잡성 증가 | |
성능 오버헤드 | 간접 참조와 다형성으로 인한 성능 저하 가능 | |
학습 곡선 | 개발자의 충분한 이해와 경험 필요 |
분류에 따른 종류
분류 기준 | 종류 | 설명 |
---|---|---|
책임 유형 | 행동 책임 원칙 | Creator, Controller, Polymorphism |
구조 책임 원칙 | Information Expert, Low Coupling, High Cohesion | |
보호 책임 원칙 | Protected Variations, Indirection, Pure Fabrication | |
적용 범위 | 클래스 수준 | Information Expert, Creator, High Cohesion |
객체 수준 | Controller, Polymorphism | |
시스템 수준 | Low Coupling, Protected Variations, Indirection |
실무 적용 예시
상황 | 적용 원칙 | 구현 방법 | 효과 |
---|---|---|---|
전자상거래 주문 시스템 | Information Expert | Order 클래스가 총액 계산 | 데이터와 로직의 응집도 향상 |
결제 시스템 | Polymorphism | PaymentProcessor 인터페이스 | 다양한 결제 방법 지원 |
웹 애플리케이션 | Controller | OrderController 로 요청 처리 | UI 와 비즈니스 로직 분리 |
알림 시스템 | Pure Fabrication | NotificationService 생성 | 도메인 모델의 순수성 유지 |
활용 사례
사례 1: 온라인 쇼핑몰 시스템
시나리오: 사용자가 온라인 쇼핑몰에서 상품을 주문하고 결제하는 시스템
시스템 구성도:
graph TB subgraph "Presentation Layer" A[Web UI] --> B[OrderController] end subgraph "Application Layer" B --> C[OrderService] C --> D[PaymentService] end subgraph "Domain Layer" E[Order] --> F[OrderItem] E --> G[Customer] H[Payment] --> I[PaymentProcessor] end subgraph "Infrastructure Layer" J[OrderRepository] K[PaymentGateway] end C --> E D --> H E --> J I --> K
GRASP 원칙 적용:
- Information Expert: Order 클래스가 주문 총액 계산
- Creator: OrderService 가 Order 객체 생성
- Controller: OrderController 가 주문 요청 처리
- Polymorphism: 다양한 PaymentProcessor 구현체
- Pure Fabrication: PaymentService 는 도메인 무관 서비스
Workflow:
- 사용자 주문 요청 → OrderController
- Controller → OrderService 로 처리 위임
- OrderService → Order 객체 생성 (Creator)
- Order → 총액 계산 (Information Expert)
- PaymentService → 결제 처리 (Pure Fabrication)
- PaymentProcessor → 결제 방법별 처리 (Polymorphism)
실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점
구분 | 고려사항 | 설명 | 권장사항 |
---|---|---|---|
원칙 적용 | 상황에 맞는 원칙 선택 | 모든 GRASP 원칙을 무조건 적용하지 말고 문제 상황에 적절히 적용 | 사용 목적에 따라 선택적으로 적용하고 적용 이유를 문서화 |
책임 정의 | 명확한 책임 분리 | 클래스의 책임이 중복되지 않도록 설계 | 클래스 다이어그램과 책임 목록을 작성하여 시각화 |
책임 할당 | 단일 책임 원칙 (SRP) 준수 | 하나의 클래스가 하나의 명확한 책임만 갖도록 유지 | 각 클래스의 책임을 도출하고 불필요한 책임을 제거 |
결합도 관리 | 의존성 최소화 | 변경이 발생해도 영향이 최소화되도록 클래스 간 의존도를 줄임 | 인터페이스 도입 및 의존성 주입 (DI) 을 통한 결합도 완화 |
응집도 관리 | 응집도 최대화 | 유사한 기능을 그룹화하여 유지보수성을 높임 | 연관된 속성과 메서드를 한 클래스로 묶고 기능 단위별 책임 구분 |
유연성 확보 | 설계 변경에 대한 대응성 | 요구사항 변경 시 구조적으로 쉽게 반영되도록 설계 | 전략 패턴, 팩토리 패턴 등 유연한 디자인 패턴을 적극 활용 |
설계 복잡도 | 과도한 분리 지양 | 책임 분리를 지나치게 하면 오히려 설계가 복잡해질 수 있음 | 단순하고 명확한 구조 유지, 최소 단위 책임으로 압축하여 설계 |
설계 초기 | 도메인 모델링 선행 | 책임 할당 전 도메인과 비즈니스 로직을 충분히 파악 | 초기 모델 설계 시 시나리오 기반의 분석 및 도메인 전문가 협업 |
팀 협업 | 표준화 및 리뷰 문화 | 팀원 간 책임 기준이 다를 경우 설계 방향 불일치 가능 | 코드 리뷰, 설계 문서화, 책임 기준 합의 등 표준화된 협업 문화 유지 |
리팩토링 | 점진적 구조 개선 | GRASP 원칙에 맞지 않는 기존 코드를 점진적으로 개선 | 주기적인 리팩토링 주기 설정 및 책임 재검토 |
최적화를 위한 고려사항
구분 | 고려사항 | 설명 | 권장사항 |
---|---|---|---|
객체 생성 최적화 | 불필요한 객체 생성을 줄이기 | 빈번한 객체 생성은 GC(가비지 컬렉션) 부하 및 성능 저하로 이어질 수 있음 | 팩토리 패턴, 싱글톤, 객체 풀링 등 재사용 가능한 생성 기법 활용 |
다형성 사용 주의 | 성능 민감 구간에서 간접 호출 제한 | 과도한 다형성 (가상 메서드 호출) 은 CPU 캐시 효율 저하를 유발할 수 있음 | 성능 중요 구간에서는 구체 클래스 직접 호출 또는 전략적 캐싱 적용 |
메모리 관리 | 참조 사이클 및 누수 방지 | 순환 참조나 강한 참조로 인해 메모리 해제가 지연될 수 있음 | 약한 참조 (Weak Reference), 옵저버 패턴, 명시적 자원 해제 적용 |
캐싱 전략 | 계산 비용 절감 | 정보 전문가 (Information Expert) 에 따라 계산이 집중되면 반복 계산 부담 증가 | 계산 결과나 읽기 빈도 높은 데이터는 로컬 캐싱 또는 전역 캐싱으로 보관 |
추상화 최소화 | 과도한 간접화 회피 | 불필요한 추상화 계층은 호출 트리 증가 및 디버깅 복잡도 상승 | Pure Fabrication 최소화, 불필요한 Wrapper 제거 |
책임 분배 효율화 | 책임 중복 방지 | 과도한 책임 분산은 동일한 데이터/로직 반복 구현 가능성 존재 | 정보 전문가 원칙에 따라 데이터 소유자에게 책임 집중 |
결합도와 호출 최적화 | 객체 간 호출 비용 관리 | 지나친 객체 분리는 모듈 간 호출 빈도 증가로 오버헤드 발생 가능 | 상호작용이 잦은 객체는 같은 모듈 또는 동일 계층에 배치 |
계층 구조 최적화 | 성능 불필요한 추상 계층 제거 | 필요 없는 추상 계층이나 간접화는 런타임 성능 저하를 초래 | 성능 분석을 바탕으로 실질적 이점 없는 추상 계층 제거 |
데이터 접근 최적화 | 접근 경로 단순화 | 모든 데이터 접근을 도메인 객체에 몰아주면 깊은 호출 경로 및 중복 발생 | DAO, Repository 등 전용 데이터 접근 계층으로 분리하고 로직은 필요한 객체에 위임 |
객체 수 제어 | 과도한 클래스 분리 방지 | 설계 원칙을 적용하다가 객체 수가 지나치게 증가할 경우 메모리 및 호출 관리 부담 상승 | 단일 책임을 유지하되 연관 책임은 한 클래스로 묶어 최소 단위 구성 |
하위 주제 학습 내용
카테고리 | 주제 | 설명 |
---|---|---|
GRASP 원칙 및 구현 | GRASP 9 가지 원칙 | Creator, Controller, Expert 등 GRASP 각 원칙의 개념 및 적용 전략 학습 |
객체지향 설계 원칙 | 책임 할당과 단일 책임 원칙 (SRP) | 클래스에 명확하고 일관된 책임을 부여하고, 책임 분리 기준을 학습함 |
설계 품질 개선 | 결합도 (Coupling), 응집도 (Cohesion) | 설계의 유연성, 변경 대응력, 테스트 용이성을 높이기 위한 구조적 품질 요소 학습 |
구조적 패턴 | MVC, MVP, MVVM | Controller 원칙이 반영된 UI 아키텍처 패턴 구조와 책임 분배 방식 학습 |
의존성 제어 및 분리 | DI(Dependency Injection) 컨테이너 | Indirection 및 Pure Fabrication 구현을 위한 의존성 주입 기법 학습 |
변경에 강한 설계 전략 | Protected Variations 원칙 적용법 | 시스템 변경에 강인한 구조 설계를 위한 추상화 및 인터페이스 활용 전략 |
반응형 아키텍처 | 옵저버 패턴 | 이벤트 중심의 시스템에서 변화 감지와 처리를 위한 핵심 패턴 학습 |
함수형 설계 접근법 | 고차 함수 (Higher-Order Function) | Polymorphism 원칙을 함수형 프로그래밍 관점에서 구현하는 방법 학습 |
실무 설계 적용 | 도메인 모델링, 컨트롤러 구조 | 실제 프로젝트에서 책임 분산을 위한 도메인 중심 설계 및 이벤트 처리 방식 |
비교 학습 | GRASP vs. SOLID | 두 설계 원칙 체계의 차이점과 상호 보완 관계를 명확히 이해 |
추가 학습 주제 및 관련 분야 정리
카테고리 | 주제 | 설명 |
---|---|---|
객체지향 설계 | 인터페이스와 Indirection | 의존성 역전을 위한 인터페이스 기반 설계 및 결합도 최소화를 위한 중재 구조 학습 |
소프트웨어 아키텍처 | 레이어드 아키텍처 | 책임 분리, 계층화 구조 및 계층 간 의존 관계 관리 방식 학습 |
도메인 모델링 | DDD 의 핵심 개념 | Aggregates, Entity, Value Object 를 통해 GRASP 의 책임 분배 구현 |
설계 품질 개선 | 책임 재배치 및 중복 제거 | 리팩토링을 통해 불필요한 책임 분산을 개선하고 응집도 향상 |
테스트 전략 | 테스트 가능한 설계 | TDD 기반 책임 단위 테스트 구조와 유닛/통합 테스트 적용 방안 |
API 및 시스템 인터페이스 | RESTful API 설계 | Controller 패턴을 활용한 명확한 엔드포인트와 책임 구분 |
아키텍처 패턴 | 헥사고날 아키텍처 | GRASP 원칙 기반 포트/어댑터 구성으로 외부 의존성과 내부 도메인 분리 |
성능 최적화 | 캐싱 전략과 분리 구현 | Pure Fabrication 원칙 기반의 캐싱 서비스 계층 분리 및 응답 성능 향상 |
데이터 영속화 | ORM 설계 및 정보 전문가 적용 | 엔티티 중심으로 데이터 책임을 위임하는 GRASP 의 Information Expert 구현 |
설계 원칙 비교 학습 | SOLID 원칙 | GRASP 과의 차이 및 보완 관계 이해를 위한 객체지향 설계 핵심 원칙 학습 |
용어 정리
GRASP 원칙 (General Responsibility Assignment Software Patterns)
용어 | 설명 |
---|---|
GRASP | 객체지향 설계에서 책임 할당을 위한 9 가지 원칙의 집합. |
Information Expert | 데이터를 가장 잘 알고 있는 객체에 책임을 할당하는 원칙. |
Creator | 어떤 객체를 생성할 책임이 있는 객체를 결정하는 원칙. |
Controller | 시스템 외부 이벤트를 처리하는 객체를 정의하는 원칙. |
Pure Fabrication | 도메인 모델에 속하지 않는 기능을 별도 객체로 분리하는 원칙. |
Indirection | 객체 간 결합도를 낮추기 위해 중간 객체를 두는 설계 원칙. |
Protected Variations | 변경 가능성이 높은 요소를 인터페이스로 추상화해 변경으로부터 보호. |
Low Coupling | 객체 간 결합도를 최소화하여 변경에 유연하게 대응하는 원칙. |
High Cohesion | 관련 책임을 한 객체나 모듈에 집중시켜 응집도를 높이는 원칙. |
Polymorphism | 동일한 인터페이스로 서로 다른 구현을 사용하는 다형성 원칙. |
객체지향 핵심 개념
용어 | 설명 |
---|---|
다형성 (Polymorphism) | 동일한 메시지로 다양한 동작을 수행할 수 있는 객체지향 특성. |
책임 할당 (Responsibility Assignment) | 클래스나 객체가 수행할 책임을 분배하는 설계 활동. |
설계 품질 관련 용어
용어 | 설명 |
---|---|
결합도 (Coupling) | 클래스나 모듈 간의 의존도 수준. 낮을수록 유지보수성과 유연성이 좋음. |
응집도 (Cohesion) | 클래스 내부 구성 요소들 간의 관련성. 높을수록 모듈의 일관성과 명확성이 향상. |
설계 전략 및 기법
용어 | 설명 |
---|---|
순수 가공 (Pure Fabrication) | 도메인에 속하지 않지만 기술적 필요로 만들어진 책임 분리용 클래스. |
간접 참조 (Indirection) | 직접적인 의존성을 피하고, 구조의 유연성을 위해 중간 계층을 활용하는 기법. |
보호된 변형 (Protected Variations) | 변화에 강한 구조를 위해 인터페이스나 추상화 계층을 도입하는 전략. |
참고 및 출처
📘 공식 문서 / 백서 / 전문 블로그
- GRASP Design Principles in OOAD - GeeksforGeeks
- GRASP (object-oriented design) - Wikipedia
- GRASP - General Responsibility Assignment Software Patterns Explained
- GRASP Principles: General Responsibility Assignment Software Patterns - Bool.dev
- GRASP: 9 Must-Know Design Principles for Code - Fluent C++
- Refactoring Guru – GRASP Principles
- Uncle Bob: Principles of OOD 요약
📚 책 / 저자 중심 자료
- Craig Larman의 “Applying UML and Patterns”
- Martin Fowler – Patterns of Enterprise Application Architecture
📝 국내 블로그 및 커뮤니티 정리
- velog: GRASP와 SOLID 원칙 개요
- 티스토리: GRASP 상세 설명
- 안녕지구 블로그: SOLID & GRASP 요약
- Yumin’s Devlog: GRASP 원칙
- 도니의 iOS 프로그래밍 세상: 정보 전문가 패턴
- d-yong’s 블로그: GRASP 개요