265. 플라이웨이트 (Flyweight) - 인스턴스 공유 메모리 절약 캐시 팩토리 구조 패턴 객체 재사용 GoF

핵심 인사이트: (258번 구조 패턴의 극한 다이어트) "슈팅 게임을 만들었다! 플레이어가 기관총을 쏘면 화면에 총알(객체) 1만 개가 날아다닌다! 총알 1개당 new 총알()을 때려서 x, y 좌표랑 '노란색 총알 텍스처(사진 10MB)'를 다 따로 RAM에 넣었다! 1만 발 쏘니까 메모리 100GB가 터지면서 컴퓨터가 멈춰버렸다 ㅆㅂ!!" 최적화 장인이 와서 뺨을 갈긴다. "야 이 미친놈아!! 총알 1만 개의 x, y 좌표(위치)는 다 다를 수 있지만, 그 총알의 '노란색 텍스처 그림(10MB)'은 1만 개가 100% 다 똑같이 생긴 판박이 껍데기잖아!! 왜 똑같은 10MB짜리 사진을 1만 번이나 메모리에 중복해서 쑤셔 박아!! 당장 그 무거운 '노란색 그림(고유 상태)' 1개를 램 구석에 딱 한 번만 띄워(공유 팩토리)!! 그리고 총알 1만 개를 쏠 때는, 각자 가벼운 x, y 좌표(외부 상태)만 쥐여주고, 그림은 그 램 구석의 원본 1개를 '포인터(참조 주소)'로 다 같이 쳐다보고(공유 Share) 가리키게 만들어!! 그럼 총알 1억 발을 쏴도 텍스처 용량은 10MB 하나로 끝이잖아!!" 객체의 내장을 파내어 공유의 극한을 달리는 메모리 다이어트의 끝판왕, 플라이웨이트다.

Ⅰ. 대량 객체 생성의 메모리 파멸

  • 게임의 총알, 숲속의 나무 10만 그루, 문서 편집기 프로그램의 글자(A, B, C...) 수만 개.
  • 이놈들을 화면에 그리기 위해 클래스 인스턴스(new)를 10만 번 호출하면 램(RAM)이 견디지 못하고 시스템이 폭파됩니다.

Ⅱ. 플라이웨이트 (Flyweight) 패턴의 개념 🌟

  • Flyweight (경량급, 깃털처럼 가벼운)
  • 개념: GoF 구조 패턴 중 하나로, 수많은 수의 자잘한 객체들을 무식하게 다 생성하지 않고, 객체들 사이에서 '완벽히 똑같이 중복되는 데이터(고유 상태)'를 딱 1번만 메모리에 생성해 두고, 수만 개의 다른 객체들이 그 원본을 참조(공유)하여 돌려쓰게 함으로써 시스템의 메모리 사용량을 비약적으로 줄여주는(다이어트) 메모리 최적화 패턴입니다.

Ⅲ. 살을 깎아내는 마법 (내부 상태 vs 외부 상태) 🌟 핵심 🌟

객체의 속성(데이터)을 칼로 반 갈라버리는 게 핵심입니다.

1. 고유 상태 (Intrinsic State / 내부 상태) - "영원히 변하지 않는 공유 자산"

  • 숲속 나무 10만 그루의 데이터 중 **'나무껍질 텍스처 사진'과 '나뭇잎 색깔'**은 10만 그루가 다 똑같습니다.
  • 이 무겁고 똑같은 놈들을 플라이웨이트 공장(Factory)에 딱 1개만 new 해서 캐시(Cache)로 올려둡니다. (공유 객체)

2. 외부 상태 (Extrinsic State) - "계속 변하는 껍데기 변수"

  • 반면, 나무들의 **'심어진 X, Y 좌표'나 '나무의 키(높이)'**는 10만 그루가 전부 제각각 다릅니다. 이건 공유할 수 없습니다.
  • 이건 플라이웨이트 객체 안에 저장하지 않고, 밖에서 클라이언트(게임 엔진)가 그릴 때 함수의 파라미터(매개변수)로 살짝 전달해서 그때그때 다르게 그려줍니다.

3. 플라이웨이트 팩토리 (Flyweight Factory) 🌟

  • 253번 싱글톤(Singleton)과 영혼이 비슷합니다.
  • 클라이언트가 "야, 빨간색 나무 하나 줘!" 라고 공장(Factory)에 찌릅니다.
  • 공장 검사 로직: "어? 램(RAM)에 띄워놓은 빨간 나무 객체가 있나? 아, 저번 놈이 달라고 해서 이미 1개 만들어(캐싱) 놨네! 자, 너도 이거 새로 만들지 말고 원래 있던 놈 메모리 주소(참조값) 가져가서 쳐다봐(공유)!"
  • 만약 "파란색 나무 줘!" 했는데 없으면? 그때서야 1개를 새로 만들어 램에 올리고 돌려줍니다.

Ⅳ. 싱글톤 패턴(253번)과의 결정적 차이 🌟 헷갈림 주의

  • 싱글톤 (Singleton): 어떤 클래스든 우주에서 **"무조건, 오직 딱 1개의 객체"**만 있어야 합니다. (종류 1개)
  • 플라이웨이트: "빨간 나무 1개", "파란 나무 1개", "노란 나무 1개" 등 "특정 종류(Key)별로 1개씩" 캐싱해 두고, 수만 명에게 그 주소를 뿌려줍니다. (캐시 풀 Cache Pool 관리의 느낌)

📢 섹션 요약 비유: 플라이웨이트(Flyweight) 패턴은 10만 대군이 모인 전쟁터의 **'마법의 돌려입기 투명 갑옷'**입니다. 멍청한 장군(Flyweight 안 쓰는 놈)은 병사 10만 명에게 각자 30kg짜리 무거운 철갑옷(객체 데이터)을 10만 벌씩 새로 주조해서(new) 입힙니다. 군대의 짐차(메모리 RAM)가 갑옷 300만 kg의 무게를 이기지 못하고 무너집니다(메모리 터짐). 똑똑한 제갈량(플라이웨이트 아키텍트)은 다릅니다. 그는 **'철갑옷의 무거운 외형과 질감(내부 상태, Intrinsic)'**을 진짜 철로 10만 벌 만들지 않습니다. 허공(캐시 메모리)에 거대한 철갑옷 홀로그램 원본 딱 1벌만 띄워놓습니다(Flyweight Factory). 그리고 10만 명의 병사들에게는 그 홀로그램을 몸에 투영시키는 '가벼운 유리구슬(참조 포인터)' 딱 1개씩만 쥐여줍니다. 그리고 병사 각자의 이름표와 서 있는 위치(외부 상태, Extrinsic)만 각자 따로 기억하게 합니다. 밖에서 보면 10만 명이 각자 무거운 철갑옷을 입은 것처럼 완벽하게 보이지만, 실제 수레(메모리)에 실린 철갑옷의 무게는 오직 '단 1벌'어치뿐입니다. 수만 개의 겹치는 덩어리들을 무자비하게 추출해 내어 하나로 공유시켜버리는 메모리 다이어트의 절대 기적입니다.