๊ด€๋ฆฌ ๋ฉ”๋‰ด

<Hello Hosung๐Ÿ˜Ž/>

[Java] ๋””์ž์ธ ํŒจํ„ด - ์‹ฑ๊ธ€ํ†ค ๋ณธ๋ฌธ

๐Ÿ’ป Java

[Java] ๋””์ž์ธ ํŒจํ„ด - ์‹ฑ๊ธ€ํ†ค

์ขŒ์ถฉ์šฐ๋Œ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ผ๊ธฐ๐Ÿง 2024. 11. 13. 22:34

 
์‹ฑ๊ธ€ํ†ค(Singleton) ํŒจํ„ด์€ ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์˜ค์ง ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.
์ฃผ๋กœ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‚˜ ๋กœ๊ทธ ์ฒ˜๋ฆฌ๊ธฐ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
 

1. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ํ•ต์‹ฌ ํŠน์ง•

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

 

2. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ๊ตฌํ˜„ ์˜ˆ์ œ (Java)

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ Java๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
 
์˜ˆ์ œ ์ฝ”๋“œ: ๊ธฐ๋ณธ ์‹ฑ๊ธ€ํ†ค ๊ตฌํ˜„

public class Singleton {
    // ์ •์  ๋ณ€์ˆ˜๋กœ ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค๋ฅผ ์„ ์–ธ
    private static Singleton instance;

    // private ์ƒ์„ฑ์ž๋ฅผ ์„ ์–ธํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์„ค์ •
    private Singleton() {}

    // ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ
    public static Singleton getInstance() {
        if (instance == null) {       // ์ฒ˜์Œ ํ˜ธ์ถœ๋  ๋•Œ ์ธ์Šคํ„ด์Šค๊ฐ€ null์ธ์ง€ ํ™•์ธ
            instance = new Singleton(); // ์ธ์Šคํ„ด์Šค๊ฐ€ ์—†์œผ๋ฉด ์ƒ์„ฑ
        }
        return instance;               // ์ด๋ฏธ ์žˆ์œผ๋ฉด ๊ธฐ์กด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜
    }

    public void showMessage() {
        System.out.println("์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค!");
    }
}

 
์‚ฌ์šฉ ์˜ˆ์‹œ
 
 

public class Main {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        singleton1.showMessage();  // ์ถœ๋ ฅ: ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค!

        // ๋‘ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋™์ผํ•œ์ง€ ํ™•์ธ
        System.out.println(singleton1 == singleton2); // true (๋‘ ๊ฐ์ฒด๋Š” ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค)
    }
}

 

3. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ์‚ฌ์šฉ

๊ธฐ๋ณธ ์‹ฑ๊ธ€ํ†ค ๊ตฌํ˜„์€ ๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋ฌธ์ œ์—†์ด ์ž‘๋™ํ•˜์ง€๋งŒ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” getInstance() ๋ฉ”์„œ๋“œ๊ฐ€ ๋™์‹œ์— ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์–ด ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜, ์ด๋ฅธ ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
์˜ˆ์ œ ์ฝ”๋“œ: ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ์‹ฑ๊ธ€ํ†ค (Double-Checked Locking)

public class ThreadSafeSingleton {
    private static volatile ThreadSafeSingleton instance;

    private ThreadSafeSingleton() {}

    public static ThreadSafeSingleton getInstance() {
        if (instance == null) {
            synchronized (ThreadSafeSingleton.class) { // ๋™๊ธฐํ™” ๋ธ”๋ก
                if (instance == null) {
                    instance = new ThreadSafeSingleton();
                }
            }
        }
        return instance;
    }
}

 

4. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ์žฅ๋‹จ์ 

์žฅ์ 

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

๋‹จ์ 

  • ์˜์กด์„ฑ์ด ๊ฐ•ํ•ด์ ธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์ž˜๋ชป ๊ตฌํ˜„ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

5. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์ด ์œ ์šฉํ•œ ์ƒํ™ฉ

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๊ด€๋ฆฌ: ํ•˜๋‚˜์˜ ์—ฐ๊ฒฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ „์—ญ์—์„œ ๊ณต์œ ๋˜๋„๋ก ํ•ด์•ผ ํ•  ๋•Œ.
  • ์„ค์ • ๊ด€๋ฆฌ ๊ฐ์ฒด: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์—์„œ ๋™์ผํ•œ ์„ค์ •์„ ์ฐธ์กฐํ•  ๋•Œ.
  • ๋กœ๊น… ํด๋ž˜์Šค: ๋ชจ๋“  ํด๋ž˜์Šค๊ฐ€ ๋™์ผํ•œ ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•ด์•ผ ํ•  ๋•Œ.

 
 
์ถ”๊ฐ€์ ์œผ๋กœ Spring ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์ง์ ‘ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. Spring์ด ๋นˆ(Bean) ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

Spring์˜ ์‹ฑ๊ธ€ํ†ค ๊ด€๋ฆฌ ๋ฐฉ์‹

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

@Service
public class MyService {
    public void doSomething() {
        System.out.println("์ž‘์—… ์ˆ˜ํ–‰ ์ค‘...");
    }
}

 

์œ„ ์ฝ”๋“œ์—์„œ MyService๋Š” Spring์˜ @Service ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜๊ณ , ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ด ๋นˆ์„ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ ๋นˆ ์Šค์ฝ”ํ”„

Spring์—์„œ๋Š” ๋‹ค์–‘ํ•œ ๋นˆ ์Šค์ฝ”ํ”„๋ฅผ ์ œ๊ณตํ•ด ํ•„์š”์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์‹ฑ๊ธ€ํ†ค(Singleton): ๊ธฐ๋ณธ ์Šค์ฝ”ํ”„์ด๋ฉฐ, ๋ชจ๋“  ์š”์ฒญ์—์„œ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ํ”„๋กœํ† ํƒ€์ž…(Prototype): ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌํ€˜์ŠคํŠธ(Request), ์„ธ์…˜(Session): ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์—์„œ ๊ฐ๊ฐ ์š”์ฒญ, ์„ธ์…˜๋‹น ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Spring์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋นˆ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ํšจ๊ณผ๋ฅผ ์‰ฝ๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Spring์—์„œ๋Š” ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ๋นˆ์˜ ์Šค์ฝ”ํ”„ ์„ค์ •์„ ํ†ตํ•ด ์ ์ ˆํ•œ ์ธ์Šคํ„ด์Šค ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.