๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] Static ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ 

์ถœ์ฒ˜

ChatGPT


1. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ Memory Leak

๋ฌธ์ œ์ 

 

  • static ๋ณ€์ˆ˜๋Š” ํด๋ž˜์Šค ๋กœ๋”๊ฐ€ ํด๋ž˜์Šค๋ฅผ ์–ธ๋กœ๋“œ(unload)ํ•  ๋•Œ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ํ•„์š” ์ด์ƒ์œผ๋กœ ์˜ค๋ž˜ ์œ ์ง€๋  ์ˆ˜ ์žˆ์–ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
  • static ๋ณ€์ˆ˜์— ๋งŽ์€ ๋ฐ์ดํ„ฐ๋‚˜ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์‹œ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ์œ ํ•˜๊ฒŒ ๋˜์–ด ๋ถˆํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ํ•„์š”ํ•œ ๋ฒ”์œ„์—์„œ๋งŒ ์‚ฌ์šฉ: static ๋ณ€์ˆ˜๊ฐ€ ์ •๋ง ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค. ํŠนํžˆ, ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š” static ๋ณ€์ˆ˜๋Š” ์ตœ์†Œํ™”ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ช…์‹œ์  ํ•ด์ œ: ์‚ฌ์šฉ์ด ๋๋‚œ static ๋ณ€์ˆ˜๋Š” ๋ช…์‹œ์ ์œผ๋กœ null๋กœ ์„ค์ •ํ•˜์—ฌ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์ด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

์˜ˆ์‹œ

public class ResourceHolder {
    private static List<Object> resources = new ArrayList<>();

    public static void addResource(Object resource) {
        resources.add(resource);
    }

    public static void clearResources() {
        resources.clear(); // ๋ช…์‹œ์ ์œผ๋กœ clear() ํ˜ธ์ถœ
    }
}

 

 

 

2. ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ Thread Safety

๋ฌธ์ œ์ 

 

  • static ๋ณ€์ˆ˜๋Š” ๋ชจ๋“  ์ธ์Šคํ„ด์Šค์—์„œ ๊ณต์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ๊ฒฝ์Ÿ ์ƒํƒœ(race condition)๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ๋™๊ธฐํ™” ์‚ฌ์šฉ: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๊ณต์œ ๋˜๋Š” static ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ๋•Œ๋Š” synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™๊ธฐํ™”ํ•œ๋‹ค.
  • ์“ฐ๋ ˆ๋“œ ์•ˆ์ „ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ ์‚ฌ์šฉ: ConcurrentHashMap์ด๋‚˜ CopyOnWriteArrayList์™€ ๊ฐ™์€ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์˜ˆ์‹œ

public class Counter {
    private static int count = 0;

    public static synchronized void increment() {
        count++;
    }

    public static synchronized int getCount() {
        return count;
    }
}

 

 

 

3. ์ „์—ญ ์ƒํƒœ(Global State) ๊ด€๋ฆฌ

๋ฌธ์ œ์ 

  • static ๋ณ€์ˆ˜๋ฅผ ๋‚จ์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์˜ ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜์–ด, ์ฝ”๋“œ์˜ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ  ๋””๋ฒ„๊น…์„ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.
  • ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ต๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“  ์ฝ”๋“œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ๋””์ž์ธ ํŒจํ„ด ์‚ฌ์šฉ: ์‹ฑ๊ธ€ํ†ค(Singleton) ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ฆฌํ•ด์•ผ ํ•  ์ „์—ญ ์ƒํƒœ์˜ ์ˆ˜๋ฅผ ์ค„์ด๊ณ , ์ „์—ญ ์ƒํƒœ ์ ‘๊ทผ์„ ์ œํ•œํ•œ๋‹ค.
  • DI(Dependency Injection) ์‚ฌ์šฉ: ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ†ตํ•ด ํด๋ž˜์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ธ๋‹ค.

์˜ˆ์‹œ

public class Config {
    private static Map<String, String> settings = new HashMap<>();

    public static void setSetting(String key, String value) {
        settings.put(key, value);
    }

    public static String getSetting(String key) {
        return settings.get(key);
    }
}

 

4. ํด๋ž˜์Šค ์–ธ๋กœ๋“œ (Class Unload) ๋ฌธ์ œ

๋ฌธ์ œ์ 

  • static ๋ณ€์ˆ˜๊ฐ€ ํด๋กœ์ €๋‚˜ ์ต๋ช… ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉ๋  ๋•Œ, ์™ธ๋ถ€ ํด๋ž˜์Šค๊ฐ€ ์–ธ๋กœ๋“œ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.
  • static ์ฐธ์กฐ๊ฐ€ ํด๋ž˜์Šค ์–ธ๋กœ๋“œ๋ฅผ ๋ง‰์•„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋˜์ง€ ์•Š๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ์ ์ ˆํ•œ ์‚ฌ์šฉ ๋ฒ”์œ„ ์ง€์ •: static ์ฐธ์กฐ๋ฅผ ํ•„์š” ์ด์ƒ์œผ๋กœ ์˜ค๋ž˜ ์œ ์ง€ํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
  • ์ •๋ฆฌ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ: ํด๋ž˜์Šค๊ฐ€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ์ •๋ฆฌ(clean-up) ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ œํ•œ๋‹ค.

์˜ˆ์‹œ

public class OuterClass {
    private static class InnerClass {
        private static OuterClass instance = new OuterClass(); // ์™ธ๋ถ€ ํด๋ž˜์Šค ์ฐธ์กฐ

        // ํ•ด์ œ ๋ฉ”์„œ๋“œ
        public static void release() {
            instance = null;
        }
    }
}

 

 

5. ๊ณผ๋„ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ

๋ฌธ์ œ์ 

 

  • static ๋ณ€์ˆ˜๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฑฐ๋‚˜, ์ž๋ฐ” ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ ๊ฐˆ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ํฐ ์ž๋ฃŒ ๊ตฌ์กฐ๋‚˜ ๋ณต์žกํ•œ ๊ฐ์ฒด๋ฅผ static์œผ๋กœ ์ •์˜ํ•  ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•œ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ธก์ •: static ๋ณ€์ˆ˜๊ฐ€ ์‚ฌ์šฉํ•  ๋ฉ”๋ชจ๋ฆฌ ์–‘์„ ์ •๋ฐ€ํžˆ ๊ณ„์‚ฐํ•˜๊ณ  ์ ์ ˆํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ•œ๋‹ค.
  • Lazy Initialization: ํ•„์š”ํ•œ ์‹œ์ ์— static ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ค„์ธ๋‹ค.

 

์˜ˆ์‹œ

public class DataLoader {
    private static List<String> data;

    public static List<String> getData() {
        if (data == null) {
            // Lazy Initialization
            data = loadData();
        }
        return data;
    }

    private static List<String> loadData() {
        // ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ๋กœ์ง
        return new ArrayList<>();
    }
}

 

 

 

 

 

 

6. ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„ Coupling

๋ฌธ์ œ์ 

 

  • static ๋ฉ”์„œ๋“œ๋‚˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜์—ฌ ๋ณ€๊ฒฝ์— ๋ฏผ๊ฐํ•œ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ํ•œ ํด๋ž˜์Šค์˜ ๋ณ€๊ฒฝ์ด ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ๋ชจ๋“ˆํ™” ๋ฐ ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ: ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“ˆํ™”๋ฅผ ์ ๊ทน ํ™œ์šฉํ•˜๊ณ , ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ƒํ˜ธ์ž‘์šฉ์„ ์ œํ•œํ•œ๋‹ค.
  • ๋””์ž์ธ ํŒจํ„ด ์ ์šฉ: SOLID ์›์น™์„ ๋”ฐ๋ฅด๋ฉฐ ์ ์ ˆํ•œ ๋””์ž์ธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐํ•ฉ๋„๋ฅผ ์ค„์ธ๋‹ค.

์˜ˆ์‹œ

interface PaymentProcessor {
    void processPayment(double amount);
}

public class PayPalProcessor implements PaymentProcessor {
    public void processPayment(double amount) {
        // PayPal ๊ฒฐ์ œ ๋กœ์ง
    }
}

public class Order {
    private PaymentProcessor paymentProcessor;

    public Order(PaymentProcessor paymentProcessor) {
        this.paymentProcessor = paymentProcessor;
    }

    public void checkout(double amount) {
        paymentProcessor.processPayment(amount);
    }
}

public class Main {
    public static void main(String[] args) {
        PaymentProcessor processor = new PayPalProcessor();
        Order order = new Order(processor);
        order.checkout(100.0);
    }
}

 

 

 

7. Lazy Initialization์˜ ๋ฌธ์ œ์ 

๋ฌธ์ œ์ 

  • static ๋ณ€์ˆ˜์— ๋Œ€ํ•œ Lazy Initialization์€ ์ดˆ๊ธฐํ™” ์ˆœ์„œ์— ๋Œ€ํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…

 

  • ์ด๋ฅธ ์ดˆ๊ธฐํ™”(Eager Initialization): static ๋ณ€์ˆ˜๋ฅผ ํด๋ž˜์Šค ๋กœ๋“œ ์‹œ์ ์— ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ์ดˆ๊ธฐํ™” ์ˆœ์„œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.
  • ๋”๋ธ” ์ฒดํฌ๋“œ ๋ฝํ‚น(Double-Checked Locking): ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์—์„œ Lazy Initialization์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ด์ค‘ ๊ฒ€์‚ฌ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ํ™•๋ณดํ•œ๋‹ค.

์˜ˆ์‹œ

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // ์ด์ค‘ ๊ฒ€์‚ฌ ๊ธฐ๋ฒ•
                }
            }
        }
        return instance;
    }
}

 

 

๊ฒฐ๋ก 

static ํ‚ค์›Œ๋“œ๋Š” ๋งค์šฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ด์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜, ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ ๋ฌธ์ œ, ํด๋ž˜์Šค ๊ฒฐํ•ฉ๋„ ์ฆ๊ฐ€ ๋“ฑ์˜ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ static ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ์ ์ ˆํ•œ ๊ด€๋ฆฌ์™€ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•ด์•ผ ํ•œ๋‹ค.

 

  • ํ•„์š”์„ฑ ๊ฒ€ํ† : static ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์‚ฌ์šฉ์ด ์ ์ ˆํ•œ์ง€ ๊ฒ€ํ† ํ•˜๊ณ , ๋ฉ”๋ชจ๋ฆฌ์™€ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๊ณ ๋ คํ•œ๋‹ค.
  • ๋ช…์‹œ์  ๊ด€๋ฆฌ: static ๋ณ€์ˆ˜๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ์„ ๋•Œ๋Š” ๊ทธ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ๋ช…ํ™•ํžˆ ์ •์˜ํ•˜๊ณ , ํ•„์š” ์—†์„ ๋•Œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ œํ•œ๋‹ค.
  • ๋””์ž์ธ ํŒจํ„ด ์ ์šฉ: ์‹ฑ๊ธ€ํ†ค, ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ, ์ธํ„ฐํŽ˜์ด์Šค ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ static ๋ณ€์ˆ˜ ์‚ฌ์šฉ์„ ์ž˜ ๊ด€๋ฆฌ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์ž๋ฐ” ํ”„๋กœ๊ทธ๋žจ์˜ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ , ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.