관리 메뉴

나만의공간

🦋 플라이웨이트(Flyweight) 패턴 완전 정복 본문

IT/JAVA

🦋 플라이웨이트(Flyweight) 패턴 완전 정복

밥알이 2025. 6. 1. 22:34

✅ 플라이웨이트 패턴이란?

같은 종류의 객체를 공유하여 메모리 사용을 줄이는 구조 패턴입니다.
"객체를 너무 많이 만들면 성능이 저하된다" → 공통 속성은 공유하고, 다른 부분만 따로 관리하자!

🎯 예시 시나리오: 온라인 문서 편집기

  • 수천 개의 글자 객체가 화면에 존재
  • 모든 글자를 객체로 만들면 메모리 낭비
  • 공유: 글꼴, 크기, 스타일
  • 개별 처리: 위치(x, y)

🧠 핵심 용어 정리

용어 설명
Intrinsic 상태 공유 가능한 고정 정보 (예: 글꼴, 색상, 크기)
Extrinsic 상태 개별 객체마다 다른 정보 (예: 위치, 문맥)

💡 언제 사용하면 좋을까?

  • 같은 종류의 객체를 아주 많이 만들어야 할 때
  • 객체 생성 비용이 크고, 대부분의 상태가 공유 가능할 때
  • 객체 수를 줄여 메모리 사용량을 최적화하고 싶을 때

 

🔧 실무 예제: 지도 앱에서 관광 마커 표시하기

📁 1) Flyweight 클래스


public class PlaceIcon {
    private final String iconType;
    private final String color;
    private final String iconPath;

    public PlaceIcon(String iconType, String color, String iconPath) {
        this.iconType = iconType;
        this.color = color;
        this.iconPath = iconPath;
    }

    public void draw(int x, int y) {
        System.out.printf("📍 [%s] 아이콘을 (%d, %d) 위치에 그립니다. (색: %s, 경로: %s)%n",
                iconType, x, y, color, iconPath);
    }
}

📁 2) Flyweight Factory


import java.util.HashMap;
import java.util.Map;

public class IconFactory {
    private static final Map<String, PlaceIcon> iconPool = new HashMap<>();

    public static PlaceIcon getIcon(String iconType) {
        if (!iconPool.containsKey(iconType)) {
            switch (iconType) {
                case "관광":
                    iconPool.put("관광", new PlaceIcon("관광", "빨강", "/icons/tour.png"));
                    break;
                case "맛집":
                    iconPool.put("맛집", new PlaceIcon("맛집", "주황", "/icons/food.png"));
                    break;
                case "카페":
                    iconPool.put("카페", new PlaceIcon("카페", "초록", "/icons/cafe.png"));
                    break;
            }
        }
        return iconPool.get(iconType);
    }
}

📁 3) 클라이언트 코드


public class MapClient {
    public static void main(String[] args) {
        drawPlace("관광", 100, 200);
        drawPlace("맛집", 120, 250);
        drawPlace("관광", 110, 210);  // 재사용
        drawPlace("카페", 140, 300);
        drawPlace("관광", 130, 280);  // 재사용
    }

    public static void drawPlace(String type, int x, int y) {
        PlaceIcon icon = IconFactory.getIcon(type);
        icon.draw(x, y);
    }
}

✅ 실행 결과


📍 [관광] 아이콘을 (100, 200) 위치에 그립니다. (색: 빨강, 경로: /icons/tour.png)
📍 [맛집] 아이콘을 (120, 250) 위치에 그립니다. (색: 주황, 경로: /icons/food.png)
📍 [관광] 아이콘을 (110, 210) 위치에 그립니다. (색: 빨강, 경로: /icons/tour.png)
📍 [카페] 아이콘을 (140, 300) 위치에 그립니다. (색: 초록, 경로: /icons/cafe.png)
📍 [관광] 아이콘을 (130, 280) 위치에 그립니다. (색: 빨강, 경로: /icons/tour.png)

✅ 구조 정리 (UML 흐름 요약)


        [클라이언트]
             │
             ▼
       [IconFactory]─────┐
             │           │ 캐싱
             ▼           ▼
     [PlaceIcon:관광] [PlaceIcon:맛집]
             │ (draw 호출 시 위치 전달)

💬 실무 적용 사례

도메인 활용 예시
게임 총알, 효과음, 배경 타일 등 공유 객체
문서 편집 글꼴, 스타일 객체 공유
지도 앱 마커 아이콘 공유
웹 개발 CSS 스타일 컴포넌트 재사용
캐시 시스템 DB 커넥션, 객체 풀링 등

✅ 장단점 정리

장점 단점
메모리 사용량 대폭 감소 구현 복잡도 증가
동일 객체 재사용으로 성능 향상 외부 상태 관리 필요
객체 생성 비용 절감 멀티스레드 환경 주의

🧾 요약

항목 내용
이름 플라이웨이트(Flyweight) 패턴
목적 공통 객체를 공유하여 메모리 절약
사용 예 게임, 지도, 문서 편집기, UI 프레임워크 등
핵심 intrinsic vs extrinsic 분리, 팩토리로 공유 관리
Comments