플라이웨이트 패턴(Flyweight Pattern)은 대량의 유사한 객체를 효율적으로 관리하기 위해 객체 공유를 활용하는 구조적 디자인 패턴이다. 이 패턴은 각 객체에 모든 데이터를 유지하는 대신, 여러 객체가 공유할 수 있는 상태(내재 상태)와 객체마다 다른 상태(외재 상태)를 분리하여 메모리 사용량을 크게 줄인다.
개요
플라이웨이트 패턴의 정의
플라이웨이트 패턴은 많은 수의 유사한 객체를 생성해야 할 때, 공유 가능한 부분을 별도의 객체로 분리하여 재사용함으로써 메모리 효율성을 높이는 패턴이다. “플라이웨이트(경량)“라는 이름처럼, 객체를 가볍게 만드는 것이 목적이다.
내재 상태와 외재 상태
- 내재 상태 (Intrinsic State): 객체 내부에 저장되며 여러 객체가 공유할 수 있는 불변 데이터
- 외재 상태 (Extrinsic State): 객체 외부에서 전달되며 각 상황에 따라 달라지는 데이터
패턴의 필요성 및 사용 사례
플라이웨이트 패턴은 다음과 같은 상황에서 유용하다:
- 대량의 유사 객체: 수천~수백만 개의 유사한 객체가 필요할 때
- 메모리 제약: 메모리 사용량이 중요한 환경에서
- 공유 가능한 상태: 객체의 상태 중 상당 부분이 공유 가능할 때
- 객체 정체성 불필요: 객체의 고유 식별이 필요하지 않을 때
패턴의 장점과 단점
| 장점 | 단점 |
|---|---|
| 메모리 사용량 대폭 감소 | 코드 복잡성 증가 |
| 성능 향상 가능 | 상태 분리 비용 (외재 상태 전달) |
| 객체 생성 비용 절감 | 플라이웨이트가 불변이어야 함 |
| 캐싱 활용 가능 | 모든 상황에 적합하지 않음 |
플라이웨이트 패턴의 구성 요소
| |
1. Flyweight (플라이웨이트)
- 공유 가능한 인터페이스 정의
- 내재 상태 저장 및 외재 상태를 매개변수로 받음
2. ConcreteFlyweight (구체적 플라이웨이트)
- 내재 상태를 저장하는 공유 가능한 객체
- 반드시 불변(immutable)이어야 함
3. UnsharedConcreteFlyweight (비공유 플라이웨이트)
- 공유되지 않는 플라이웨이트 (선택적)
- 모든 상태를 내부에 저장
4. FlyweightFactory (플라이웨이트 팩토리)
- 플라이웨이트 객체 생성 및 관리
- 이미 존재하는 플라이웨이트 반환 (캐싱)
구현 예제
Python 예제 - 텍스트 에디터의 문자
| |
Java 예제 - 게임의 나무 (Tree)
| |
C# 예제 - 총알/파티클 시스템
| |
실제 사용 사례
1. Java String Pool
| |
2. Java Integer Cache
| |
3. 게임 개발
파티클 시스템, 총알, NPC 등 대량의 유사한 객체를 효율적으로 관리
4. 텍스트 에디터
문자별 포맷팅 정보를 공유하여 메모리 절약
관련 패턴
| 패턴 | 플라이웨이트와의 관계 |
|---|---|
| Composite | Composite의 Leaf 노드를 플라이웨이트로 구현 |
| Factory | 플라이웨이트 객체 생성과 캐싱 관리에 사용 |
| Singleton | 플라이웨이트 팩토리가 싱글턴일 수 있음 |
| State/Strategy | 상태/전략 객체를 플라이웨이트로 공유 가능 |
FAQ
Q1: 플라이웨이트 객체는 왜 불변이어야 하나요?
여러 클라이언트가 동시에 같은 플라이웨이트를 참조하므로, 한 곳에서 상태를 변경하면 모든 참조에 영향을 미칩니다. 불변 객체로 만들어 이런 부작용을 방지합니다.
Q2: 플라이웨이트 패턴을 사용하면 항상 메모리가 절약되나요?
아닙니다. 객체 수가 적거나 공유 가능한 상태가 적으면 오히려 팩토리 관리 비용이 더 클 수 있습니다. 대량의 유사 객체가 있을 때만 효과적입니다.
Q3: 외재 상태를 매번 전달하는 것이 비효율적이지 않나요?
상황에 따라 다릅니다. 메모리 절약이 연산 비용보다 중요한 경우에 플라이웨이트가 적합합니다. 외재 상태 전달 비용을 최소화하도록 설계해야 합니다.
Q4: 스레드 안전성은 어떻게 보장하나요?
플라이웨이트가 불변이면 본질적으로 스레드 안전합니다. 팩토리의 캐시 접근은 동기화가 필요할 수 있습니다.
참고 자료
- GoF의 “Design Patterns: Elements of Reusable Object-Oriented Software”
- Java String Pool 문서
- Game Programming Patterns (Robert Nystrom)
![Featured image of post [Design Pattern] Flyweight - 플라이웨이트 패턴](/post/designpattern/11_flyweight/tmp_wordcloud_hu_8041433a3865ce3f.png)
![[Design Pattern] Decorator - 데코레이터 패턴](/post/designpattern/09_decorator/tmp_wordcloud_hu_2fe4899ffc2b9123.png)
![[Design Pattern] Facade - 퍼사드 패턴](/post/designpattern/10_facade/tmp_wordcloud_hu_2a2ec8eb7cdad284.png)
![[Design Pattern] Flyweight - 플라이웨이트 패턴](/post/designpattern/11_flyweight/tmp_wordcloud_hu_77fa678ac7f0c7f9.png)
![[Design Pattern] Proxy - 프록시 패턴](/post/designpattern/12_proxy/tmp_wordcloud_hu_4f9491d332f42eed.png)
![[Design Pattern] Interpreter - 인터프리터 패턴](/post/designpattern/13_interpreter/tmp_wordcloud_hu_183dbc47827b19bc.png)
![[Design Pattern] Prototype - 프로토타입 패턴](/post/designpattern/04_prototype/tmp_wordcloud_hu_66fa2976990c89e8.png)
![[Design Pattern] Abstract Factory - 추상 팩토리 패턴](/post/designpattern/01_abstract_factory/tmp_wordcloud_hu_b099a96e6467c168.png)
![[Design Pattern] Adapter - 어댑터 패턴](/post/designpattern/06_adapter/tmp_wordcloud_hu_9c98c3aa5074382f.png)
![[Design Pattern] Bridge - 브릿지 패턴](/post/designpattern/07_bridge/tmp_wordcloud_hu_83e6bad072544abf.png)
![[Design Pattern] Composite - 컴포지트 패턴](/post/designpattern/08_composite/tmp_wordcloud_hu_127f86e1fcdf3b3b.png)