

Flyweight
intrinsic state(변하지 않는 데이터)을 보관하는 객체.FlyweightFactory
Flyweight 객체의 생성과 공유를 담당.Flyweight가 있으면 반환, 없으면 생성 후 캐싱.Flyweight 객체를 관리하는 컬렉션을 유지한다.Client
FlyweightFactory를 통해 Flyweight를 받아 사용하며, extrinsic state(컨텍스트별 데이터)를 함께 전달.Client가 FlyweightFactory에 요청 ⇒ Factory는 키를 기준으로 캐시 탐색Flyweight가 존재하면 재사용, 없으면 새 생성 후 캐시에 저장Client는 Flyweight의 메서드에 extrinsic state를 인자로 넘겨 사용class Book {
constructor(title, author, isbn) {
this.title = title;
this.author = author;
this.isbn = isbn; // intrinsic (공유)
Object.freeze(this); // 공유 객체 불변화 권장
}
}
// 공유 객체 캐시
const books = new Map();
// Flyweight Factory: 같은 ISBN이면 같은 인스턴스 재사용
const createBook = (title, author, isbn) => {
if (books.has(isbn)) return books.get(isbn);
const book = new Book(title, author, isbn);
books.set(isbn, book);
return book;
};
// 개별 목록: 공유 객체 + 개별 상태(extrinsic)를 함께 보관
const bookList = [];
const addBook = (title, author, isbn, availability, sales) => {
const fly = createBook(title, author, isbn); // 공유 객체 참조
const entry = {
book: fly, // 공유 상태(참조)
availability, // 개별 상태
sales, // 개별 상태
};
bookList.push(entry);
return entry;
};
// 사용 예시
const a = addBook("Dune", "Frank Herbert", "9780441172719", "in-stock", 1200);
const b = addBook("Dune", "Frank Herbert", "9780441172719", "sold-out", 1300);
// 같은 ISBN은 같은 인스턴스를 공유한다 ⇒ true
console.log(a.book === b.book);
intrinsic / extrinsic state 분리, Factory 기반 객체 공유가 핵심 설계 기법이다.class Book {
constructor(title, author, isbn) {
this.title = title;
this.author = author;
this.isbn = isbn;
}
}
const books = new Map();
const createBook = (title, author, isbn) => {
const existingBook = books.has(isbn);
if (existingBook) {
return books.get(isbn);
}
const book = new Book(title, author, isbn);
books.set(isbn, book);
return book;
};
const bookList = [];
const addBook = (title, author, isbn, availability, sales) => {
const book = {
...createBook(title, author, isbn),
sales,
availability,
isbn,
};
bookList.push(book);
return book;
};
예시 코드의 문제점
...createBook(...)로 인스턴스를 펼치면 새로운 객체가 만들어져서 공유가 깨진다. 프로토타입 메서드와 정체성도 사라지기 때문에 동일 인스턴스를 재사용하는 의도가 무력화된다.Book 클래스가 갖는 title, author, isbn은 공유 상태(intrinsic)로 관리해야 하고, availability와 sales는 개별 상태(extrinsic)로 분리해야 메모리 절감 효과를 얻을 수 있다. (<코드 및 활용 예시>의 코드에서는 공유 상태는 참조를 통해 공유하고 있음)isbn은 이미 Book 인스턴스 안에 포함되어 있는데, 엔트리에도 중복으로 넣고 있다. 필요에 따라 유지할 수는 있지만, 의도적으로 중복을 두는 게 아니라면 불필요하다.
- 프로토타입 상속의 기본 아이디어
map, filter, reduce 메서드가 따로 복사되어 들어있는 게 아니라, 모두 Array.prototype에 정의되어 있고, 각 배열 인스턴스는 참조만 한다.function Book(title, author, isbn) {
this.title = title;
this.author = author;
this.isbn = isbn;
}
Book.prototype.getInfo = function () {
return `${this.title} - ${this.author}`;
};
const a = new Book("Dune", "Frank Herbert", "9780441172719");
const b = new Book("Foundation", "Isaac Asimov", "9780553293357");
console.log(a.getInfo === b.getInfo); // true → 같은 함수 참조
- 자바스크립트에서 Flyweight가 그리 중요하지 않은 이유
intrinsic)를 공유해서 메모리를 절약하는 것이다.
- 자바스크립트에서 Flyweight이 의미 있는 경우
Font 객체로 만들어 캐싱하고, 개별 문자는 해당 Font 객체 참조만 들고 있게 할 수 있다.Flyweight로 관리하면 메모리 효율이 커진다.Flyweight 방식으로 메모리 절감을 노릴 수 있다.