본문 바로가기
Design Pattern/구조 패턴(Structural Patterns)

플라이웨이트(Flyweight) 패턴 - 구조 패턴 (Structural Patterns)

by 김 민 준 2024. 5. 23.

 

플라이웨이트 패턴은 개체를 가능한 한번에 공유하여 사용하도록 하여 메모리를 절약하는 구조적 디자인 패턴이다. 대량의 개체를 다룰 때 유용하며, 개체의 상태를 분리하여 공유 가능한 상태(Intrinsic State)와 공유 불가능한 상태(Extrinsic State)로 나누어 메모리 사용을 최소솨 한다. 

 

1. 공유 가능한 상태(Instrinsic State) - 개체간에 공유 할 수 있는 상태이다. 변경되지 않으며, 모든 개체가 동일하게 유지하는 부분이다. 

 

2. 공유 불가능한 상태 (Extrinsic State) - 개체마다 다를 수 있는 상태이다. 개체가 사용될 때 외부에서 전달되는 상태이다.

 

3. 플라이웨이트 팩토리 (Flyweight Factory) - 플라이웨이트 개체들을 생성하고 관리하는 역할을 한다. 이미 생성된 개체를 캐싱하여 재사용한다.

 

실무적인 예시로 바로 이해할 수 있도록 예제 소스코드를 살펴보자.

 

HTTP 요청에 대해 공유가능한 부분은 공유하여 동일하게 사용하고자 한다. 

 

HTTP Request 세팅 클래스를 먼저 선언한다.

 

// HttpRequestSettings 클래스: HTTP 요청 설정 (공유 가능한 상태)
class HttpRequestSettings {
    private int timeout;
    private String userAgent;
    private Map<String, String> headers;

    public HttpRequestSettings(int timeout, String userAgent, Map<String, String> headers) {
        this.timeout = timeout;
        this.userAgent = userAgent;
        // Headers 복사하여 보안 강화
        this.headers = new HashMap<>(headers);
    }

    public int getTimeout() {
        return timeout;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public Map<String, String> getHeaders() {
        // Headers 복사본 반환하여 보안 강화
        return new HashMap<>(headers);
    }
}

 

 

HTTP 요청 클래스를 선언한다.

 

// HttpRequest 클래스: HTTP 요청 (공유 불가능한 상태 포함)
class HttpRequest {
    private String url;
    private HttpRequestSettings settings;
    private Map<String, String> sensitiveHeaders; // 민감한 헤더는 공유되지 않음

    public HttpRequest(String url, HttpRequestSettings settings, Map<String, String> sensitiveHeaders) {
        this.url = url;
        this.settings = settings;
        this.sensitiveHeaders = new HashMap<>(sensitiveHeaders); // 민감한 헤더 복사
    }

    public void sendRequest() {
        System.out.println("Sending request to URL: " + url);
        System.out.println("Timeout: " + settings.getTimeout());
        System.out.println("User-Agent: " + settings.getUserAgent());
        System.out.println("Headers: " + settings.getHeaders());
        System.out.println("Sensitive Headers: " + sensitiveHeaders);
        // 실제 HTTP 요청 보내는 로직은 생략
    }
}

 

플라이웨이트 팩토리를 이용하여 HTTP 요청 설정을 생성하고 관리해보자.

 

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

// HttpRequestSettingsFactory 클래스: HTTP 요청 설정을 생성하고 관리
class HttpRequestSettingsFactory {
    private Map<String, HttpRequestSettings> settingsMap = new HashMap<>();

    public HttpRequestSettings getSettings(int timeout, String userAgent, Map<String, String> headers) {
        String key = timeout + "-" + userAgent + "-" + headers.hashCode();
        if (!settingsMap.containsKey(key)) {
            settingsMap.put(key, new HttpRequestSettings(timeout, userAgent, headers));
        }
        return settingsMap.get(key);
    }
}

 

사용 예시 소스코드를 살펴보자.

 

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

public class FlyweightPatternDemo {
    public static void main(String[] args) {
        HttpRequestSettingsFactory settingsFactory = new HttpRequestSettingsFactory();

        // 공통 HTTP 설정 생성
        Map<String, String> commonHeaders = new HashMap<>();
        commonHeaders.put("Accept", "application/json");

        // 민감한 헤더는 각 요청마다 개별적으로 관리
        Map<String, String> sensitiveHeaders1 = new HashMap<>();
        sensitiveHeaders1.put("Authorization", "Bearer token1");

        Map<String, String> sensitiveHeaders2 = new HashMap<>();
        sensitiveHeaders2.put("Authorization", "Bearer token2");

        HttpRequestSettings settings1 = settingsFactory.getSettings(5000, "MyApp/1.0", commonHeaders);
        HttpRequestSettings settings2 = settingsFactory.getSettings(5000, "MyApp/1.0", commonHeaders);

        // 여러 HTTP 요청 생성
        HttpRequest request1 = new HttpRequest("https://api.example.com/data", settings1, sensitiveHeaders1);
        HttpRequest request2 = new HttpRequest("https://api.example.com/user", settings2, sensitiveHeaders2);

        // 요청 보내기
        request1.sendRequest();
        request2.sendRequest();
    }
}

 

 

출력내용 

 

Sending request to URL: https://api.example.com/data
Timeout: 5000
User-Agent: MyApp/1.0
Headers: {Accept=application/json}
Sensitive Headers: {Authorization=Bearer token1}
Sending request to URL: https://api.example.com/user
Timeout: 5000
User-Agent: MyApp/1.0
Headers: {Accept=application/json}
Sensitive Headers: {Authorization=Bearer token2}

 

보안적인 부분을 신경쓰고 구현해야하는게 핵심이며, 동일한 HTTP 요청 설정을 여러 요청에서 재사용 하는 방법을 확인할 수 있다. 이를 통해 메모리 사용을 최적화 하고 설정 개체를 효율적으로 관리할 수 있다. 특히 대규모 시스템에서 HTTP 요청이 많아 질 수 있는데 유용하게 사용할 수 있는 패턴이다.