Flyweight Pattern

Flyweight Pattern 은 메모리 상의 동일한 객체가 반복적으로 사용될 경우, 그 내부의 불변 데이터를 공유하여 메모리 낭비를 줄이는 구조적 설계 패턴이다. 객체의 상태를 고유 상태와 외부 상태로 분리하여, 공유 가능한 고유 상태만을 플라이웨이트 객체에 저장하고 팩토리를 통해 인스턴스를 관리한다.

특히 대규모 객체를 반복적으로 생성·사용하는 GUI 요소, 게임 오브젝트, 텍스트 렌더링 등의 환경에서 효과적이다. 이 패턴은 객체 간 차이를 외부화 (Extrinsic State) 하고, 공통된 내부 상태를 내부화하여 공유함으로써 객체 수를 최소화한다.

예를 들어 텍스트 렌더링 시스템에서 각 글자의 폰트 스타일 등 공통 속성은 공유하고, 위치 정보 등만 별도로 유지하여 수천 개의 문자 객체를 효율적으로 관리할 수 있다. 메모리 절감, 성능 향상이 필요한 시스템에 효과적이다.

배경

역사적 배경

플라이웨이트 패턴은 1990 년 Paul Calder 와 Mark Linton 에 의해 WYSIWYG 문서 편집기에서 글리프 (Glyph) 정보를 효율적으로 처리하기 위해 최초로 제안되었다. 이후 GoF 에 의해 공식화되어 23 개 디자인 패턴 중 하나로 정립되었다.

기술적 배경

목적 및 필요성

주요 목적

필요성

핵심 개념

Flyweight Pattern메모리 사용을 최적화하기 위해 동일한 객체를 공유해서 사용하는 구조적 디자인 패턴이다. 특히, 수많은 유사한 객체가 동시에 존재해야 할 때 사용되며, 각 객체의 공통된 내부 상태 (Intrinsic State) 는 공유하고, 개별적으로 달라지는 외부 상태 (Extrinsic State) 는 외부에서 주입된다.

핵심 원리는 " 공통된 상태를 공유 " 하고, " 변하는 상태만 외부에서 관리 " 함으로써 객체 수를 줄이고 성능을 높이는 것이다.

기본 개념

상태 분리 원칙

메모리 최적화 원리

의도 (Intent)

공유를 통해 대량의 소립 (fine-grained) 객체를 효율적으로 지원하여 메모리 사용을 최소화한다.

다른 이름 (Also Known As)

동기 (Motivation / Forces)

적용 가능성 (Applicability)

조건설명
동일한 속성을 가진 객체가 다수 생성되는 경우UI 구성 요소, 게임 객체 등
메모리 사용량이 문제인 시스템제한된 리소스를 사용하는 내장 시스템, 모바일 환경
객체의 상태를 외부에서 관리할 수 있는 경우intrinsic 상태와 extrinsic 상태를 분리 가능해야 함

패턴이 해결하고자 하는 설계 문제

문제를 해결하기 위한 설계 구조와 관계

실무 구현 관점

실무 구현을 위한 핵심 요소

팩토리 관리 (Factory Management)

상태 관리 전략 (State Management Strategy)

주요 기능 및 역할

주요 기능

핵심 역할

특징

구조적 특징

동작적 특징

핵심 원칙

설계 원칙

메모리 관리 원칙

7.5. 참여자들 간의 상호작용 방식

작동 원리 및 방식

작동 순서

  1. 클라이언트 요청: 특정 내재적 상태를 가진 Flyweight 객체 요청
  2. 팩토리 검사: 팩토리에서 기존 객체 존재 여부 확인
  3. 객체 반환: 기존 객체가 있으면 반환, 없으면 새로 생성 후 반환
  4. 상태 전달: 클라이언트가 외재적 상태를 메서드 매개변수로 전달
  5. 작업 수행: Flyweight 객체가 내재적 상태와 외재적 상태를 조합하여 작업 수행

작동 방식 다이어그램

classDiagram
    class Flyweight {
        -sharedState
        +operation(extrinsicState)
    }

    class ConcreteFlyweight {
        +operation(extrinsicState)
    }

    class FlyweightFactory {
        -flyweights : Map
        +getFlyweight(key)
    }

    class Client {
        +operation()
    }

    Flyweight <|-- ConcreteFlyweight
    FlyweightFactory --> Flyweight
    Client --> FlyweightFactory
    Client --> Flyweight

설명: 클라이언트는 Factory 를 통해 Flyweight 객체를 얻고, 외부 상태를 주입하여 사용한다.

주요 원리

패턴 적용의 결과와 트레이드오프

상태 분리 원리

graph TD
    A[원본 객체] --> B[내재적 상태<br/>Intrinsic State]
    A --> C[외재적 상태<br/>Extrinsic State]
    B --> D[Flyweight 객체에 저장<br/>공유 가능, 불변]
    C --> E[클라이언트가 관리<br/>컨텍스트별 변경]
    D --> F[메모리 절약]
    E --> F

내재적 상태 (Intrinsic State)

외재적 상태 (Extrinsic State)

객체 공유 원리

sequenceDiagram
    participant Client
    participant Factory
    participant FlyweightPool
    participant Flyweight

    Client->>Factory: getFlyweight(key)
    Factory->>FlyweightPool: check existing
    alt 기존 객체 존재
        FlyweightPool-->>Factory: return existing
    else 새 객체 필요
        Factory->>Flyweight: create new
        Factory->>FlyweightPool: store new
        FlyweightPool-->>Factory: return new
    end
    Factory-->>Client: return flyweight
    Client->>Flyweight: operation(extrinsicState)

메모리 관리 방식

graph LR
    A[대량의 유사 객체] --> B[상태 분석]
    B --> C[내재적 상태 추출]
    B --> D[외재적 상태 분리]
    C --> E[Flyweight Pool]
    D --> F[Client Context]
    E --> G[메모리 절약]
    F --> G

1
메모리 절약량 = (총 객체 수 × 객체 크기) - (플라이웨이트 수 × 플라이웨이트 크기 + 외부 상태 총 크기)

상태 분리 원리

1
2
3
전체 상태 = 고유 상태 (Intrinsic) ∪ 외부 상태 (Extrinsic)
고유 상태 = 모든 객체 간 공유 가능한 불변 정보
외부 상태 = 컨텍스트별 개별 관리되는 가변 정보

관련 패턴

패턴차이점 및 관계
SingletonFlyweight 객체를 싱글턴으로 관리할 수도 있음
Factory MethodFlyweight 객체 생성을 Factory 가 담당
Object Pool자원을 재사용한다는 점에서 유사하지만, Flyweight 은 상태 공유에 집중
Composite복잡한 공유 구조가 필요한 경우 함께 사용 가능

구조 및 아키텍처

공통된 내부 상태는 캐시된 Flyweight 객체에서 공유되고, 각 호출마다 클라이언트가 외부 상태를 주입한다.

전체 구조

classDiagram
    class Flyweight {
        <<interface>>
        +operation(extrinsicState)
    }
    
    class ConcreteFlyweight {
        -intrinsicState
        +operation(extrinsicState)
    }
    
    class UnsharedConcreteFlyweight {
        -allState
        +operation(extrinsicState)
    }
    
    class FlyweightFactory {
        -flyweights: Map
        +getFlyweight(key): Flyweight
    }
    
    class Client {
        -extrinsicState
        +operation()
    }
    
    Flyweight <|-- ConcreteFlyweight
    Flyweight <|-- UnsharedConcreteFlyweight
    FlyweightFactory --> Flyweight
    Client --> FlyweightFactory
    Client --> Flyweight
구분구성요소기능 설명역할 설명주요 특징
필수Flyweight공통 인터페이스 정의외부 상태를 매개변수로 받아 작업 수행 메서드 선언고유/외부 상태를 명확히 구분하는 시그니처 제공
ConcreteFlyweightFlyweight 인터페이스의 실제 구현고유 상태 저장 및 외부 상태 활용 작업 수행불변 객체로 설계되어 스레드 안전 확보
FlyweightFactory객체 생성/관리 및 중복 방지객체 풀 관리 및 적절한 플라이웨이트 반환싱글톤 패턴 적용, 전역 공유 가능한 객체 팩토리
Context외부 상태 저장 및 Flyweight 참조외부 상태 + Flyweight 결합하여 완전한 상태 유지각 플라이웨이트 객체에 대해 별도 외부 상태 관리
선택UnsharedConcreteFlyweight공유되지 않는 특별한 플라이웨이트 구현공통적으로 공유되지 않는 개별 객체 처리일반적인 패턴 구조에서는 사용되지 않으며, 특정 상황에만 활용됨

구현 기법

카테고리기법명정의구성 요소목적대표 기술/예시
1. 객체 생성 및 관리Factory Method 패턴 활용플라이웨이트 객체 생성을 전담하는 팩토리 메서드 구현객체 풀 (Map/Dict), 중복 확인 로직, 새 객체 생성 로직객체 생성 비용 절감, 중복 객체 방지Java FontFactory, Python FlyweightFactory
팩토리 패턴 + 싱글톤 결합전역에서 동일한 Factory 사용, 객체 풀 일관성 유지static 싱글톤 인스턴스, 정적 메서드, 공유 캐시객체 생성 책임 중앙 집중화, 메모리 공유 극대화Python CharacterFactory 예시
캐싱 및 객체 풀링 전략생성된 객체를 캐시에 보관하고 재사용해시 기반 Map, LRU 정책, TTL, 비유지형/유지형 캐시 등객체 접근 성능 향상, 메모리 효율화LRU Cache, WeakReference 사용
2. 상태 분리 및 설계Intrinsic/Extrinsic 상태 분리공유 가능한 내부 상태와 개별 외부 상태를 명확히 구분intrinsic: 불변 필드, extrinsic: 메서드 매개변수, 상태 결합 메서드객체 간 공유 가능 상태 식별, 불변 객체 설계 강화Python Character.display(), JS Particle.render()
외부 상태 전달 구조화외부 상태를 클라이언트가 직접 관리하지 않도록 구조화외부 상태 전달 DTO/Wrapper 객체, 주입 헬퍼 클래스클라이언트 코드 간소화, 외부 상태 관리 일관성DTO 패턴, 상태 캡슐화 클래스
불변 객체 설계상태 변경을 허용하지 않도록 객체를 immutable 하게 설계final 필드, 생성자에서만 설정, setter 제거공유 객체의 상태 오염 방지, 동시성 안정성 확보Python @dataclass(frozen=True), Java final 필드
3. 메모리 및 성능 최적화약한 참조 (Weak Reference) 활용GC 에 의한 회수 대상이 될 수 있는 약한 참조 기반 객체 캐시WeakHashMap, WeakReference, 약한 참조 기반 Map 구조메모리 누수 방지, 필요 없는 객체 자동 제거Java WeakHashMap, Python weakref.WeakValueDictionary
캐시 키 최적화객체 식별용 키를 고유하고 충돌 없게 생성tuple 기반 key, dict → str 변환, JSON serialize 등캐시 중복 방지, 검색 성능 개선tuple(state.items()), json.dumps()
캐시 정책 적용 (LRU, TTL 등)오래된 객체를 자동으로 제거하거나 TTL 로 만료eviction policy 설정, max size 제한, access log 기록캐시 과도 누적 방지, 메모리 점유율 조절LRUCache, TTLCache, LFUCache
4. 동시성 및 안정성멀티스레드 안전 Factory 구현멀티스레드 환경에서도 안전하게 객체 공유 및 접근 가능synchronized, thread-safe Map, Lock-Free 구조race condition 방지, 공유 객체 무결성 유지Java ConcurrentHashMap, Python threading.Lock
Double-Checked Locking객체 생성 시 동기화 영역 최소화하는 최적화 기법null 검사 2 회, synchronized block, volatile 변수불필요한 동기화 비용 최소화Java 싱글톤 객체 생성 시 사용
5. 고급 최적화 전략코드 자동 생성 도구 활용상태별 Flyweight 구현을 자동화하여 코드 반복 제거코드 생성기, AST 기반 최적화 도구, 메타프로그래밍생산성 향상, 유지보수성 향상Python metaclass, AST 최적화 툴
적용 조건 기반 자동 필터링Flyweight 패턴의 적용이 불필요한 경우를 자동으로 필터링적용 조건 수치화 (ex. 객체 1000 개 이상), 정적 분석 도구 사용오버엔지니어링 방지객체 수 기반 조건식 + 적용 여부 판별 로직

Factory Method 기반 객체 풀링

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Font:
    def __init__(self, name):
        self.name = name  # intrinsic 상태

    def render(self, content, size):
        print(f"Rendering '{content}' with font '{self.name}' at size {size}")

class FontFactory:
    _font_pool = {}

    @classmethod
    def get_font(cls, name):
        if name not in cls._font_pool:
            print(f"[Factory] Creating new Font: {name}")
            cls._font_pool[name] = Font(name)
        else:
            print(f"[Factory] Reusing Font: {name}")
        return cls._font_pool[name]

상태 분리: Intrinsic Vs Extrinsic

1
2
3
4
5
6
7
class Character:
    def __init__(self, letter, font):
        self.letter = letter          # 공유 가능한 intrinsic 상태
        self.font = font

    def display(self, x, y, color):   # 개별 extrinsic 상태는 메서드로 전달
        print(f"Display '{self.letter}' in font '{self.font}' at ({x},{y}) with color {color}")

캐싱 및 해시 기반 객체 풀링

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class FlyweightFactory:
    def __init__(self):
        self._pool = {}

    def get_flyweight(self, key):
        if key not in self._pool:
            print(f"[Cache] Creating new object for key: {key}")
            self._pool[key] = ConcreteFlyweight(key)
        else:
            print(f"[Cache] Using cached object for key: {key}")
        return self._pool[key]

class ConcreteFlyweight:
    def __init__(self, shared_state):
        self.shared_state = shared_state  # intrinsic 상태

    def operate(self, unique_state):
        print(f"[Flyweight] Shared: {self.shared_state}, Unique: {unique_state}")

약한 참조 기반 캐싱 (실패 사례 포함)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import weakref

class WeakFlyweightFactory:
    def __init__(self):
        self._pool = weakref.WeakValueDictionary()

    def get(self, key):
        if key not in self._pool:
            print(f"[WeakRef] Creating new: {key}")
            self._pool[key] = ConcreteFlyweight(key)
        return self._pool[key]

Thread-Safe Factory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import threading

class ThreadSafeFactory:
    _lock = threading.Lock()
    _pool = {}

    @classmethod
    def get(cls, key):
        with cls._lock:  # 임계 구역 보호
            if key not in cls._pool:
                print(f"[ThreadSafe] Creating: {key}")
                cls._pool[key] = ConcreteFlyweight(key)
            return cls._pool[key]

불변 객체 설계

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class ImmutableFlyweight:
    __slots__ = ['_state']  # 메모리 최적화 및 불변성 의도 명확화

    def __init__(self, state):
        self._state = state

    @property
    def state(self):
        return self._state

    def operate(self, unique):
        print(f"[Immutable] Shared: {self._state}, Unique: {unique}")

장점

카테고리항목설명주요 원인
메모리 최적화메모리 절약수천~수백만 개의 객체 생성 시, 내재 상태를 공유함으로써 메모리 사용량을 대폭 절감객체 재사용, 상태 공유
캐싱 효과동일 상태의 객체는 Factory 에서 재사용되어 캐시처럼 작동하며, 메모리 접근 속도 및 응답성 향상중앙 캐시 관리 구조
성능 향상객체 생성 비용 절감새로운 객체를 매번 생성하지 않고 재사용함으로써 생성 오버헤드 및 초기화 비용을 줄임팩토리 기반 재사용 구조
GC 부담 감소객체 수 감소로 인해 가비지 컬렉션의 빈도와 부하가 줄어들어 전체 시스템 성능 향상객체 수 감소
시스템 응답성 향상객체 생성, 메모리 할당, GC 등의 부하가 줄어들어 응답 속도 및 처리량 개선경량 구조 + 메모리 효율
일관성 및 유지보수성상태 일관성 보장공유 객체가 동일한 내재 상태를 갖기 때문에, 모든 클라이언트에서 동일한 동작 및 값 유지불변 공유 상태
관심사 분리내재 상태와 외재 상태를 명확히 분리하여 코드 구조가 명확해지고, 유지보수와 테스트가 쉬워짐상태 모델 분리 설계
확장성 및 관리 효율확장성 제공객체 수가 많아져도 상태 공유로 인해 메모리 사용이 선형적으로 증가하지 않으므로, 대규모 시스템에 적합상태 공유 기반 구조적 장점
객체 관리 용이객체의 생성, 수명, 재사용 등을 Factory 에서 일괄 관리 가능 → 객체 수 추적 및 모니터링 용이중앙 집중형 Factory 패턴 사용

단점과 문제점 그리고 해결방안

카테고리구분항목설명해결 방안 및 기법
설계 복잡성단점상태 분리의 복잡성Intrinsic/Extrinsic 상태를 명확히 나누는 것이 어려움도메인 분석 기반 설계, 상태 다이어그램 활용, 상태 캡슐화 설계
단점외부 상태 클라이언트 관리 부담외부 상태를 클라이언트가 직접 관리해야 하므로 코드가 복잡해짐외부 상태 전달용 Wrapper/DTO 객체 도입, 상태 헬퍼 클래스 활용
단점코드 가독성 저하공유/비공유 상태가 혼재되면 유지보수가 어려워짐명명 규칙 통일, 설계 문서화, 역할 분리 철저
문제점외부 상태 동기화 실패외부 상태 전달 누락 또는 오류로 기능 이상 발생상태 유효성 검증 로직 도입, 외부 상태 명세화 및 DTO 기반 전달
성능 및 리소스 이슈단점객체 접근 시 성능 저하Factory 를 통한 객체 탐색 과정에서 오버헤드 발생 가능해시 기반 검색, LRU 캐시 전략 적용, 데이터 구조 최적화
문제점캐싱 누락Factory 에 캐시 로직이 누락되면 중복 객체 생성으로 메모리 낭비키 생성 전략 정의, 객체 생성 횟수 로깅, HashMap 기반 캐시 구현
문제점메모리 누수재사용 객체가 무한 누적될 경우 GC 가 회수하지 못하고 누수 발생WeakReference 사용, 캐시 TTL 및 LRU 정책 적용, 캐시 정리 스케줄링
문제점비효율적 적용객체 수가 적은데도 무리하게 적용하면 오히려 복잡도 증가사전 조건 분석 후 적용 결정 (1000+ 객체 이상 등), 적용 타당성 점검표 도입
동시성 이슈단점동시성 문제 가능성멀티스레드 환경에서 공유 객체 접근 시 race condition 발생 가능불변 객체 설계, ConcurrentHashMap 활용, 동기화 도구 (lock, atomic 등) 적용
문제점스레드 간 상태 충돌Flyweight 객체가 mutable 할 경우 상태 충돌 발생immutable 객체 설계, 상태 변경 차단, Lock-free 설계 적용
문제점공유 객체 상태 오염의도치 않게 상태가 변경되면 전체 객체에 영향 미침상태 변경 감시 로직 도입, 상태 변경 메서드 제거 또는 감춤
개발 생산성단점개발 오버헤드초기 설계와 구현에 필요한 시간 및 리소스 증가코드 자동 생성 도구 활용, 공통 로직 템플릿화
단점오버엔지니어링 가능성적용 대상이 아닌 곳에도 무분별하게 사용하면 오히려 유지보수 어려움객체 수 기준 등 사전 적용 조건 정의, 적용 가이드 문서화
문제점상태 일관성 검증 어려움공유 객체이므로 상태 변경이 전체 영향 → 디버깅이 어려움상태 변경 로그 추적 시스템, 상태 변경 테스트 케이스 구축
문제점성능 개선 여부 측정 어려움실제 메모리 절감이나 성능 향상을 수치로 측정하기 어려움메모리/GC 프로파일링 도구 활용, 벤치마크 및 성능 로그 기반 정량 평가

도전 과제

카테고리도전 과제원인 및 영향탐지 및 진단예방 방법해결 방안 / 기법
1. 상태 설계상태 분리의 복잡성Intrinsic(공유) / Extrinsic(외부) 상태 구분 어려움잘못된 설계 시 객체 재사용 실패도메인 분석, 상태 다이어그램, 설계 리뷰상태 정의 기준 명확화, 도메인 모델링, 상태 클러스터링명확한 인터페이스 설계, 불변 객체 활용, 외부 상태 DTO/Wrapper 도입
2. 메모리 관리객체 풀 무한 증가에 따른 메모리 누수캐시가 계속 쌓여 GC 대상이 되지 않음메모리 소비 증가 → 성능 저하Heap Dump, VisualVM, tracemallocTTL, LRU, SoftReference, 풀 정리 로직 도입약한 참조 (WeakReference), LRU 캐시 적용, 캐시 만료 정책 구성
공유 범위 설계 실패유사하지만 공유 불가능한 상태까지 캐싱 → 오용혹은 공유 가능한 상태를 캐싱하지 않음메모리 사용 추적, 객체 생성 히스토그램상태 범위 명확화, 유사 객체 그룹 분류상태 기반 자동 공유 탐지 알고리즘, 정적 분석 기반 상태 분석
3. 동시성 관리스레드 안전성 확보공유 객체에 여러 스레드가 접근 시 동기화 문제 Race Condition 발생 가능Race Detector, Thread Dump불변 객체 설계, 외부 상태 분리ConcurrentHashMap, Double-Checked Locking, Lock-Free 구조, Actor 모델 적용
4. 성능 최적화캐시 오버헤드와 튜닝과도한 캐시 → GC 부하캐시 미스 → 객체 재생성 반복캐시 히트율, GC 로그 분석적절한 캐시 사이즈, 히트율 기반 조정LFU/LRU 캐시 전략, 프로파일링 기반 리밸런싱, 분산 캐시 연계
성능 효과 측정의 어려움플라이웨이트 적용 전후의 메모리/속도 측정이 명확하지 않음Memory Profiler, Benchmark Tool테스트 케이스 기반 정량화프로파일링 도구 (JFR, VisualVM 등), 벤치마킹 도구 (Py-Spy, perf 등) 사용
5. 유지보수/유연성객체 라이프사이클 관리객체 생성/소멸 시점 불명확 시 누수 및 오작동 발생힙 사용량 분석, 참조 카운트 확인생성/소멸 정책 명시, 수명 주기 테스트Reference Counting, Pool Size 제한, Auto Cleanup 로직 구현
적용 대상의 자동 식별 및 범용화 어려움수작업 구현 시 코드 중복 발생, 확장 어려움객체 수 추적, 중복 코드 탐색코드 템플릿 및 적용 기준 자동화AST 기반 코드 분석, 메타프로그래밍, 코드 생성기 도입
6. 마이크로서비스 환경분산 환경에서의 객체 공유 복잡성서비스 간 공유 객체 전송 시 네트워크 오버헤드일관성 보장 어려움네트워크 트레이싱, 분산 로그 분석로컬 캐시 우선, 객체 ID 전달 방식 활용로컬 Flyweight 풀, 분산 동기화 프로토콜, 클라우드 캐싱 솔루션 활용
7. 시스템 환경 변화현대 메모리/CPU 아키텍처 변화 대응 필요기존 메모리 관리 기법만으로는 한계 발생NUMA 활용도 분석, 압축 메모리 효과 분석아키텍처 의존성 제거, 하드웨어 특화 최적화 고려NUMA 최적화, 메모리 압축 기술 연계, 실시간 메모리 분석 도구 적용

분류 기준에 따른 종류 및 유형

분류 카테고리분류 기준유형설명예시/활용
1. 공유 전략공유 여부Shared Flyweight상태가 동일한 여러 객체가 공유되는 일반적 형태기본 도형, 색상 팔레트
Unshared Flyweight복합 객체 등, 일부 요소는 공유되지 않고 독립적으로 사용복합 그래픽 객체, 특수 UI 위젯 등
공유 수준Fully Shared모든 속성이 공유되는 구조동일 아이콘 이미지, 단색 스타일
Partially Shared일부 속성만 공유되고 나머지는 외부에서 주입같은 폰트 다른 크기의 텍스트
2. 상태 관리상태 유형Intrinsic State내부 불변 상태, Flyweight 객체 내에 포함되어 공유됨글꼴, 도형 정보 등
Extrinsic State외부에서 전달되는 개별 상태, 클라이언트가 보관 및 전달위치, 회전, 사용자 입력 값
상태 가변성Immutable Flyweight불변 객체로 상태 변경 불가문자 객체, 스프라이트, 스타일 버튼 등
Mutable Flyweight내재 상태는 고정, 외부 상태나 동작은 유동적DB 연결 객체, 네트워크 핸들러
3. 생성 방식생성 시점Eager Initialization시작 시 전체 객체를 한 번에 생성요일, 월, 고정된 게임 타일 등
Lazy Initialization사용 요청 시점에 생성되는 방식사용자 요청 기반 UI 구성요소
생성 전략Factory 기반중앙 팩토리에서 객체를 관리하고 제공FlyweightFactory
스마트 참조 기반캐시, 스마트 포인터, Object Pool 기반SoftReference 기반 캐싱
4. 메모리 관리저장 방식Centralized Pool하나의 풀에서 모든 Flyweight 객체를 관리HashMap 기반 객체 관리
Distributed Pool유형이나 카테고리별로 분산된 풀에서 관리모듈별 전용 캐시, 멀티팩토리 구조
보존 전략Permanent Pool애플리케이션 종료까지 유지되는 형태시스템 공통 리소스 (e.g., 기본 폰트)
Temporary Pool일정 조건이나 시간 이후 GC 대상이 되는 약한 참조 기반임시 메시지 객체, 로그 항목
5. 적용 도메인적용 분야그래픽 Flyweight3D 모델, 텍스처 등 시각 요소 공유게임 오브젝트, 배경 요소
텍스트 Flyweight문자, 스타일 등 반복되는 텍스트 구성 요소 공유워드 프로세서, 코드 에디터
UI 컴포넌트 Flyweight공통된 버튼, 아이콘, 입력 필드 등 UI 구성 요소리스트뷰, GridView 등에서의 View 재사용
데이터 커넥션 FlyweightDB 연결, 네트워크 소켓 등의 반복적 연결 객체 재사용Connection Pool, HTTP Connection 재사용

실무 적용 예시

도메인적용 사례공유 객체 (Flyweight)외부 상태 (Extrinsic)사용 기술기대 효과
텍스트 처리텍스트 에디터 문자 객체폰트, 스타일, 크기 등 렌더링 속성문자 위치, 컬러, 개별 속성Font Engine, Unicode, PDF Renderer수천~수만 개 문자에 대한 메모리 절감 (최대 90%)
게임 개발배경 오브젝트, 총알, NPC, 파티클 등3D 모델, 텍스처, 애니메이션 정보위치, 방향, 속도, 상태 등Unity, Unreal Engine, Graphics API렌더링 최적화, 프레임 향상, 대량 객체 관리 가능
웹 브라우저HTML DOM 요소 렌더링CSS 스타일, 공통 레이아웃DOM 구조, 텍스트, 위치 등HTML Parser, CSS Engine, Virtual DOM로딩 속도 향상, 스타일 재사용으로 메모리 절감
GUI 프레임워크공통 버튼, 아이콘, 위젯공통 UI 스타일, 컴포넌트 구조이벤트 핸들러, 상태값 등Java Swing, React, Flutter컴포넌트 재사용, 렌더링 최적화
지도 서비스마커 아이콘, 지도 타일아이콘 이미지, 타일 템플릿위도/경도, 현재 뷰 포인트Leaflet.js, Mapbox, Spatial Index대용량 지도 데이터에서도 빠른 렌더링과 메모리 절약
데이터 시각화차트의 데이터 포인트마커 모양, 시각적 스타일값 좌표, 색상, 범례 항목D3.js, WebGL, Highcharts대량 데이터 실시간 시각화 성능 확보
문서 처리PDF, 워드 문서 렌더링공통 서체 정보, 스타일 속성문자 위치, 하이라이트 정보PDF.js, Word Processor Engine대용량 문서 처리 시 메모리 사용량 최소화
DB 및 미들웨어쿼리 객체, 연결 (Connection) 풀 관리쿼리 문자열 구조, 커넥션 템플릿파라미터, 사용자 세션 등JDBC, HikariCP, ORM Cache커넥션/쿼리 재사용으로 동시성 처리량 증가
사물인터넷 (IoT)센서 데이터 처리 객체 재사용공통 센서 유형, 포맷 구조실시간 측정값, 디바이스 ID 등MicroPython, C++, MQTT제한된 메모리 환경에서도 고성능 처리 가능
그래픽/렌더링3D 그래픽 구성요소, 게임 맵 등메시 (mesh), 쉐이더, 재질 (material) 정보위치, 회전, 광원 정보 등OpenGL, Vulkan, Three.js대규모 씬 처리 시 GPU/메모리 자원 절약

활용 사례

사례 1: 텍스트 에디터 시스템

Microsoft Word 와 같은 텍스트 에디터에서 수천, 수만 개의 문자 객체를 효율적으로 관리해야 하는 상황

시스템 구성:

graph TB
    A[Document Editor] --> B[Character Factory]
    B --> C[Character Pool]
    C --> D[Character A]
    C --> E[Character B]
    C --> F[Character …]
    
    A --> G[Document Context]
    G --> H[Position Info]
    G --> I[Formatting Info]
    G --> J[Style Info]
    
    D --> K[Font Family]
    D --> L[Font Size]
    E --> K
    E --> L

Workflow:

  1. 사용자가 문자 입력
  2. Character Factory 에서 해당 문자 객체 확인
  3. 기존 객체가 있으면 재사용, 없으면 새로 생성
  4. Document Context 에서 위치, 스타일 정보 관리
  5. 렌더링 시 Flyweight 객체와 외재적 상태 결합

Flyweight Pattern 의 역할:

Pattern 적용 전후 차이점:

사례 2: 멀티플레이어 게임의 총알 시스템

대규모 멀티플레이어 슈팅 게임에서 수천 개의 총알 객체가 동시에 화면에 존재하는 상황

시스템 구성

1
2
3
4
5
6
7
8
Game Engine
├── BulletFactory (플라이웨이트 팩토리)
├── BulletType (플라이웨이트 인터페이스)
│   ├── PistolBullet (구체적 플라이웨이트)
│   ├── RifleBullet (구체적 플라이웨이트)
│   └── SniperBullet (구체적 플라이웨이트)
├── BulletContext (컨텍스트)
└── GameObjectManager (클라이언트)

구성 다이어그램

1
2
3
4
5
6
7
Player → GameObjectManager → BulletFactory
            BulletType (공유 객체)
        BulletContext (개별 상태: 위치, 속도, 방향)
            Rendering Engine

Workflow:

  1. 총알 발사 요청: 플레이어가 발사 버튼 클릭
  2. 팩토리 조회: GameObjectManager 가 BulletFactory 에 해당 총알 타입 요청
  3. 플라이웨이트 반환: 기존 BulletType 객체 반환 또는 새로 생성
  4. 컨텍스트 생성: 총알의 위치, 속도, 방향 등 외부 상태로 BulletContext 생성
  5. 게임 루프 처리: 매 프레임마다 BulletContext 업데이트 및 렌더링

담당 역할:

구현 예시

Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class TreeType:
    def __init__(self, name, color, texture):
        self.name = name
        self.color = color
        self.texture = texture

    def draw(self, x, y):
        print(f"Drawing {self.name} at ({x},{y}) with {self.color} and {self.texture}")

class TreeFactory:
    _tree_types = {}

    @classmethod
    def get_tree_type(cls, name, color, texture):
        key = (name, color, texture)
        if key not in cls._tree_types:
            print("Creating new TreeType")
            cls._tree_types[key] = TreeType(name, color, texture)
        return cls._tree_types[key]

class Tree:
    def __init__(self, x, y, tree_type):
        self.x = x
        self.y = y
        self.tree_type = tree_type

    def draw(self):
        self.tree_type.draw(self.x, self.y)

# 사용 예시
forest = []
tree_type = TreeFactory.get_tree_type("Oak", "Green", "Rough")
forest.append(Tree(10, 20, tree_type))
forest.append(Tree(30, 40, tree_type))

for tree in forest:
    tree.draw()

Python: 문서 컨텍스트 관리

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from abc import ABC, abstractmethod
from typing import Dict, Optional

class Character(ABC):
    """Flyweight 인터페이스 - 문자 객체의 공통 인터페이스"""
    
    @abstractmethod
    def render(self, position_x: int, position_y: int, font_size: int, color: str) -> None:
        """문자 렌더링 - 외재적 상태를 매개변수로 받음"""
        pass

class ConcreteCharacter(Character):
    """구체적인 Flyweight - 공유 가능한 문자 객체"""
    
    def __init__(self, symbol: str, font_family: str):
        # 내재적 상태 - 모든 인스턴스에서 공유됨
        self._symbol = symbol
        self._font_family = font_family
    
    def render(self, position_x: int, position_y: int, font_size: int, color: str) -> None:
        """외재적 상태와 내재적 상태를 결합하여 문자 렌더링"""
        print(f"문자 '{self._symbol}' 렌더링:")
        print(f"  위치: ({position_x}, {position_y})")
        print(f"  폰트: {self._font_family}, 크기: {font_size}")
        print(f"  색상: {color}")

class CharacterFactory:
    """Flyweight Factory - 문자 객체 생성 및 관리"""
    
    _characters: Dict[str, Character] = {}
    
    @classmethod
    def get_character(cls, symbol: str, font_family: str = "Arial") -> Character:
        """문자 객체 획득 - 기존 객체 재사용 또는 새로 생성"""
        key = f"{symbol}_{font_family}"
        
        if key not in cls._characters:
            print(f"새로운 문자 객체 생성: {symbol} ({font_family})")
            cls._characters[key] = ConcreteCharacter(symbol, font_family)
        else:
            print(f"기존 문자 객체 재사용: {symbol} ({font_family})")
        
        return cls._characters[key]
    
    @classmethod
    def get_created_characters_count(cls) -> int:
        """생성된 문자 객체 수 반환"""
        return len(cls._characters)

class Document:
    """클라이언트 - 문서 컨텍스트 관리"""
    
    def __init__(self):
        self._characters = []  # 문자와 외재적 상태 저장
    
    def add_character(self, symbol: str, x: int, y: int, 
                     font_size: int, color: str, font_family: str = "Arial"):
        """문자 추가 - Flyweight 객체와 외재적 상태 관리"""
        character = CharacterFactory.get_character(symbol, font_family)
        self._characters.append({
            'character': character,
            'x': x, 'y': y,
            'font_size': font_size,
            'color': color
        })
    
    def render_document(self):
        """문서 전체 렌더링"""
        print("\n=== 문서 렌더링 시작 ===")
        for char_data in self._characters:
            char_data['character'].render(
                char_data['x'], char_data['y'],
                char_data['font_size'], char_data['color']
            )
        print(f"\n총 생성된 Character 객체 수: {CharacterFactory.get_created_characters_count()}")
        print(f"총 문서 내 문자 수: {len(self._characters)}")

# 사용 예시
def main():
    document = Document()
    
    # "HELLO" 문자열 추가 - 같은 문자는 객체 재사용
    word = "HELLO"
    for i, symbol in enumerate(word):
        document.add_character(
            symbol=symbol,
            x=i * 20, y=100,
            font_size=12, color="black"
        )
    
    # 동일한 문자 'L' 다시 사용 - 기존 객체 재사용됨
    document.add_character('L', 150, 100, 16, "red")
    
    document.render_document()

if __name__ == "__main__":
    main()

실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점

카테고리고려 항목설명권장사항
설계 단계상태 분석공유 가능한 상태 (intrinsic) 와 개별 상태 (extrinsic) 를 명확히 구분도메인 모델 기반 분석, 문서화, UML 등으로 분리 구조 시각화
적용 조건 확인유사한 객체가 충분히 많은 상황에서만 Flyweight 적용이 효과적1000 개 이상 객체 생성 예상 시 도입 고려
공유 기준 정의어느 범위까지 상태를 공유할 것인지 결정 필요설계 시점에 intrinsic/extrinsic 경계 정의, 책임 분리
외부 상태 전달 전략외부 상태가 많아지면 클라이언트의 관리 복잡도 증가DTO, Wrapper, Context 객체 등을 통한 관리
메모리 사용량 분석Flyweight 적용이 메모리 절약에 실질적으로 기여하는지 측정 필요적용 전/후 메모리 프로파일링 (JFR, VisualVM, tracemalloc 등)
구현 단계팩토리 설계Flyweight 객체의 생성과 캐싱을 책임지는 팩토리 구조HashMap 캐싱, LRU 정책, Singleton 또는 추상 팩토리 패턴 적용
팩토리 동시성 관리멀티스레드 환경에서의 객체 중복 생성 방지Double-Checked Locking, ConcurrentHashMap 활용
객체 라이프사이클 관리객체의 생성/소멸 시점을 명확히 제어해야 메모리 누수를 방지약한 참조 (WeakReference), TTL 기반 캐시, 참조 카운팅 등 적용
불변성 보장공유 객체가 외부에서 변경되면 전체 시스템에 오류 유발 가능불변 객체 (Immutable Object), final/const 필드 사용, setter 제거
성능 최적화캐시 전략무제한 캐시로 인한 메모리 문제 발생 방지LRU, TTL 캐시 정책, 캐시 최대 크기 제한 설정
캐시 오버헤드캐시 관리가 과도해지면 오히려 성능 저하 유발 가능적중률 기반 캐시 최적화, GC-Friendly 전략 적용
동시성 처리다중 스레드에서의 안정성 확보 필요읽기 전용 객체 설계, 동기화 최소화, Lock-Free 자료구조 사용
지연 초기화 (Lazy Loading)필요 시점에만 객체 생성하여 초기 리소스 사용 최소화Factory 내 lazy instantiation 적용
유지보수성팩토리 책임 분리팩토리가 너무 많은 책임을 가지면 코드 관리가 어려워짐타입별 팩토리 분리, SRP 적용, 인터페이스 기반 구조 적용
확장성 고려새로운 Flyweight 타입을 유연하게 추가 가능해야 함추상 팩토리 패턴, DI/IoC 구조 설계 고려
코드 문서화상태 분리 기준과 객체 공유 구조가 명확히 문서화되지 않으면 유지보수가 어려움주석, 다이어그램, 적용 기준 명시
테스트 전략공유 객체 검증공유 객체의 변경이 전체 시스템에 영향을 줄 수 있으므로 정밀 테스트 필요불변성 테스트, 상태 변경 감지 테스트, 객체 생성 횟수 측정 등
메모리 사용 테스트메모리 절약 효과를 실제로 검증해야 설계의 타당성이 확보됨적용 전/후의 객체 수, 메모리 사용량 비교 측정

테스트 전략

리팩토링 전략

활용 시 흔한 실수

성능을 최적화하기 위한 고려사항 및 주의할 점

카테고리고려 항목설명권장사항
메모리 최적화객체 풀 크기 설정풀 크기를 조절하여 과도한 메모리 점유 또는 미사용 객체 방지애플리케이션 특성 기반 임계값 설정
GC 부하공유 객체가 많을수록 GC 압력 증가약한 참조 사용 (e.g. WeakReference), GC 튜닝 (G1GC, ZGC 등) 적용
메모리 릭 방지캐시나 객체 풀에 남아있는 객체로 인한 메모리 누수 위험TTL 설정, 정기적 캐시 정리, 최대 크기 제한 설정
상태 분리 최적화Intrinsic/Extrinsic 상태의 과도한 일반화 또는 경계 불명확성명확한 설계 경계 및 역할 단위 분리, 잘 정의된 인터페이스 구성
메모리 프로파일링Flyweight 적용 전후 힙 사용량 및 객체 수 비교 분석Java: JFR, VisualVM / Python: tracemalloc, memory_profiler
성능 최적화팩토리 검색 성능객체 검색 시 해시 충돌 등으로 인한 성능 저하 가능고유 상태 기반 해시함수 사용, 충돌 최소화, 로드 팩터 조절
지연 초기화 (Lazy Init)객체가 불필요하게 미리 생성되는 것을 방지필요한 시점에만 객체 생성 (lazy loading)
배치 처리대량 객체 생성 시 개별 처리보다 효율적객체 예상 수요 기반 일괄 생성 또는 preloading 활용
직렬화/역직렬화 최적화저장 또는 전송 시 공유 객체의 효율적 처리 필요Intrinsic 상태만 직렬화, Extrinsic 은 클라이언트가 재조립
캐시 오버헤드과도한 캐시 크기 또는 갱신 비용 발생LRU, LFU, TTL 전략 기반 관리, 캐시 적중률 모니터링
I/O 최적화네트워크 전송 효율성분산 환경에서 전체 객체 대신 공유 상태만 전송해야 함Extrinsic 상태는 로컬에서 생성, Intrinsic 만 전송
동시성 최적화읽기 성능읽기 전용 객체는 락 없이 사용 가능불변 객체 설계, 락 프리 (lock-free) 구조 적용
팩토리의 동시성 처리멀티스레드 환경에서 객체 중복 생성 또는 race condition 방지 필요Double-checked locking, CAS(Compare-And-Swap) 사용
동기화 오버헤드필요 이상의 락으로 인해 성능 저하 가능Concurrent 자료구조 사용, 비동기 처리, 동기화 최소화
확장성분산 환경에서 객체 공유 전략객체 공유 범위가 넓을수록 네트워크 지연, 동기화 복잡성 증가지역성 기반 캐싱 (Locality-based Caching), CDN 및 Edge 캐시 활용
유지보수성코드 문서화공유 상태 및 외부 상태 분리가 명확하지 않으면 유지보수 어려움UML 다이어그램, 주석, 패턴 적용 이유 및 제약사항 문서화
추상화 수준과도한 일반화로 인해 이해도 저하 및 복잡성 증가 가능역할별 책임 분리, 너무 일반적인 Flyweight 는 피하고 유스케이스 기반 설계
모니터링캐시 히트율 및 객체 수 추적캐시 성능과 객체 재사용 효과 측정샘플링 기반 모니터링 도구 적용 (e.g. Prometheus, Grafana, custom logs)
변화 대응력요구사항 변화 및 확장성 대응 전략초기 설계가 경직되면 유연한 확장/변경이 어려움설정 기반 팩토리 설계, 플러그인 아키텍처 구조 고려, 동적 로딩 전략 적용

주제와 관련하여 주목할 내용

카테고리주제항목설명
디자인 패턴Flyweight Pattern구조적 패턴객체의 공유를 통한 메모리 절약 및 성능 최적화를 목표로 하는 GoF 패턴
패턴 비교Flyweight vs Object PoolFlyweight 는 불변 객체 공유, Object Pool 은 상태가 있는 객체 재사용
연계 패턴Singleton, Factory, Composite, Proxy패턴 조합을 통해 생성, 구조화, 접근 제어를 강화
설계 원칙 적용SRP, DRY상태 분리와 관심사 분리를 통한 높은 응집도와 재사용성
상태 분리 설계Intrinsic / Extrinsic내부 불변 상태 vs 외부 클라이언트 상태 분리
성능 최적화메모리 절약 전략객체 재사용중복 인스턴스를 제거하고 공유를 통해 메모리 사용량 최소화
캐시 전략LRU, TTL, SoftReference상태 공유 객체의 교체/수명 관리 전략
성능 분석 도구VisualVM, Heap Dump, JProfilerFlyweight 적용 전후의 메모리/성능 측정 도구
객체지향 설계불변 객체Immutable Object상태 변경이 불가능한 객체로 스레드 안전성과 일관성 확보
객체 풀링Object Pooling자주 사용되는 상태 객체의 풀링을 통한 생성 비용 감소
Factory 관리객체 생명 주기 통제생성/캐시/제거를 일관성 있게 관리
프로그래밍 기술동시성 제어Thread Safety, Double-Checked Locking멀티스레드 환경에서도 안전한 객체 공유 보장
약한 참조/GC 최적화WeakReference, GC 관리자동 메모리 수거로 Flyweight 객체의 수명 관리
프레임워크/언어 적용언어별 사례Java String Pool, Python Interned Object언어 런타임 수준의 Flyweight 적용 사례
프레임워크 연계Spring (Bean Scope), React.js (VDOM reuse)Bean 공유, 컴포넌트 재사용을 통한 성능 최적화
캐시 도구Redis, Memcached분산 환경에서 객체 상태 캐시와 공유
도메인별 적용 사례게임 개발Unity 오브젝트 풀, 애니메이션 인스턴싱대량의 반복 객체에 대한 재사용 최적화
웹 개발HTTP Cache, CDN, Service Worker리소스 캐싱 및 상태 공유 통한 성능 향상
데이터베이스 최적화Connection Pooling, Query Cache쿼리 결과 및 연결 공유로 I/O 성능 증대
그래픽스Scene Graph, Texture Atlas, LOD3D 데이터 중복 제거 및 레벨별 렌더링 최적화
미래 기술 확장고급 메모리 기술CXL, 3D Stack Memory분산 메모리 환경에서도 Flyweight 적용 가능성 탐색
양자 컴퓨팅상태 얽힘 공유 모델양자 시스템에서의 상태 공유 개념으로 확장
블록체인스마트 컨트랙트 최적화, IPFS상태 공유를 통한 가스비 절감 및 중복 저장 제거
보안 기술Zero Trust, 동형 암호화암호화된 상태에서의 데이터 공유 및 접근 제어 최적화

반드시 학습해야할 내용

카테고리주제하위 항목 / 키워드설명
디자인 패턴Flyweight PatternStructural Pattern, 상태 분리, 객체 공유GoF 구조적 패턴 중 하나로, 객체의 메모리 사용을 줄이기 위한 공유 설계 방식
관련 디자인 패턴Singleton, Factory Method, Proxy, Object Pool생성, 접근, 재사용 관점에서 연관되는 주요 패턴들
패턴 비교 학습Singleton vs Flyweight, Prototype vs Flyweight인스턴스 수, 재사용 방식, 상태 관리 방식의 차이 비교
객체지향 설계상태 분리 설계 원리Intrinsic/Extrinsic State객체 내부/외부 상태의 분리와 설계 전략
SOLID 원칙SRP, OCP객체 재사용과 유지보수성을 높이기 위한 설계 원칙
메모리 최적화메모리 관리 전략GC, Soft/Weak Reference, Memory Pool객체 수명 주기 및 재사용을 통한 메모리 절감 전략
캐시 전략LRU, TTL, Hash Consing공유 객체 또는 리소스의 수명/교체/재사용을 위한 전략
성능 지표Memory Footprint, Cache Hit Ratio성능 측정을 위한 주요 지표 정의
동시성 프로그래밍Thread Safety불변 객체 설계, 락, Double-Checked Locking멀티스레드 환경에서 안전한 공유 객체 생성 및 접근
Lock-Free Techniques무잠금 프로그래밍병렬 환경에서 동기화 오버헤드 최소화
Concurrent CollectionsJava ConcurrentHashMap 등안전한 공유 객체 풀 관리
성능 분석 및 최적화프로파일링 & 모니터링 도구VisualVM, JProfiler, Memory Analyzer메모리 사용 분석 및 최적화 도구 활용
메모리 정렬 및 접근 최적화Cache Locality, Memory AlignmentCPU 성능 친화적인 메모리 레이아웃 설계
프레임워크 & 언어언어별 구현 특성Java, C++, Python언어별 Flyweight 패턴 구현 방식 및 차이
프레임워크 사례Spring,.NETDI, AOP, Bean Pool 등과의 연계
도구 및 라이브러리Guava Cache, Caffeine, Spring Cache실무에서 객체 공유/재사용을 위한 도구
실무 적용 분야컴퓨터 그래픽스Scene Graph, Texture Atlas, LOD중복 모델/리소스를 GPU 메모리 효율적으로 관리
게임 개발Asset Streaming, Animation Instancing리소스 동적 로딩 및 애니메이션 재사용 최적화
웹 개발CDN, Service Workers, HTTP Cache정적 리소스 및 오프라인 캐싱의 재사용 전략
데이터베이스Query Result Cache, Connection Pool, Materialized View결과셋 재사용과 연결 풀 관리로 성능 향상
분산 시스템Distributed Caching (Redis 등), Load Balancing마이크로서비스 간 공유 객체, 세션, 캐시 관리
이론/기초 개념구조적 디자인 패턴 군 이해Composite, Proxy, DecoratorFlyweight 와 함께 쓰이는 구조 중심의 패턴군 분석
자료구조/알고리즘 기반Hash Table, Map, Trie빠른 공유 객체 탐색/관리를 위한 자료구조
대규모 객체 설계 전략Object Grouping, Shallow Copy, Factory Pool대량 객체 관리를 위한 설계 기법
아키텍처 적용Microservices ArchitectureShared Data Optimization, Stateless ProxyFlyweight 원리를 마이크로서비스에 적용한 분산 설계 사례
코드 품질 및 검토Code Review, Pattern ValidationFlyweight 적용의 적절성, 유지보수성, 성능 영향 분석

용어 정리

카테고리용어설명
디자인 패턴 개념Flyweight Pattern객체의 내부 상태를 공유하여 메모리 사용을 최소화하는 구조적 디자인 패턴
Flyweight공유 가능한 객체를 나타내는 추상 개념
Concrete Flyweight공유 가능한 객체의 실제 구현체, 내부 상태 (intrinsic) 를 포함
Unshared Concrete Flyweight공유되지 않는 객체, 개별 생성되어야 하는 예외적인 케이스
Flyweight FactoryFlyweight 객체를 생성하고 캐싱하는 팩토리 역할 수행
ContextFlyweight 와 외부 상태를 결합해 완전한 의미를 가지는 객체
상태 관리Intrinsic State공유 가능한 불변 내부 상태, 객체 간 공통
Extrinsic State외부에서 주입되는 개별 상태, 공유되지 않으며 컨텍스트 의존적
Immutable Object변경 불가능한 객체, Flyweight 의 상태 공유 특성과 연관
메모리 최적화 기법Object Pool상태 있는 객체의 재사용을 위해 미리 생성해두는 저장소
Hash Consing동일 값의 객체를 하나로 공유하여 중복 제거
Lazy Initialization실제로 필요할 때까지 객체 생성을 지연시키는 기법
Memory Footprint프로그램이 사용하는 전체 메모리 용량
Cache Locality메모리 접근 지역성 원리를 활용한 성능 최적화 기법
캐싱 및 참조 관리LRU (Least Recently Used)가장 오래된 캐시 항목부터 제거하는 정책
TTL (Time To Live)일정 시간이 지나면 캐시 항목을 제거하는 기한
Cache Hit Ratio요청 중 캐시로부터 처리된 비율
Soft Reference메모리 부족 시 가비지 컬렉션 대상이 되는 약한 참조
Weak Reference객체가 다른 강한 참조가 없으면 GC 에 의해 수거될 수 있는 참조 방식
병렬성/싱글톤 관련Double-Checked Locking멀티스레드 환경에서 안전하고 효율적인 싱글톤 생성 기법
GC 및 런타임Garbage Collection사용하지 않는 객체를 자동으로 메모리에서 해제하는 메커니즘

참고 및 출처

공식 및 이론 중심 자료

실무 사례 및 블로그 기반 자료