자바의 디자인 패턴 (싱글톤)

김종태·2022년 9월 5일
0

디자인 패턴(Design Pattern) 이란?

소프트웨어를 설계할때 특정한 상황에 발생하는 고질적인 문제들을 해결하기 위한 해결책 이다.

‘싱글톤’, ‘옵저버’, ‘전략패턴’ 등 여러가지 상황에 대한 훌륭한 솔루션이 존재하며 설계시에 적절히 활용하면 목적에 맞는 설계를 하는데 큰 도움이 된다.

싱글톤(Singleton).

싱글톤(Singleton)이란 객체의 인스턴스가 오직 1개만 생성되는 패턴이다. 굉장히 자주 등장하는 디자인 패턴이며 대표적으로 Spring의 Bean 기본 생성 전략이 싱글톤으로 설계되어 있다.

자바에서의 싱글톤 구현

  • 싱글톤 클래스
    public class Singleton {
    
      private static Singleton instance = new Singleton();
      
      private Singleton() {
    	/*
    	 * 생성자를 private로 선언하여 외부에서 호출할 수 없도록 설계
    	 */
      }
    
      public synchronized static Singleton getInstance() {
          return instance;
      }
    }
  • 싱글톤 클래스 호출 방법
    public class Test{
        
      public statci void main(String[] args) {
    		Singleton a = Singleton.getInstance();
    		Singleton b = Singleton.getInstance();
    		if(a == b)
    		System.out.println("동일한 인스턴스 입니다.");
    	}
    
    }

위 예제는 자바에서의 가장 기본적인 싱글톤 패턴 예제이다. 결과는 당연하게도 “동일한 인스턴스 입니다.” 라는 문자열이 출력되게 된다.

Singleton 클래스를 살펴보면 instance 라는 클래스 변수를 선언하여, 프로그램이 실행되는 시점에 인스턴스를 생성하고 getInstance() 정적 메소드를 통해 단 하나의 instance를 반환하도록 설계되어 있다.

주의깊게 살펴볼 부분은 기본 생성자를 private로 선언함으로서 new Singleton() 과 같이 새로운 인스턴스를 생성하는 것을 방지하는 부분이다.

또한 getInstance() 메소드는 synchronized 를 통해 동기화 시켜주었는데 이는 멀티쓰레드 환경에서 같은 인스턴스를 참조하는 과정에서 발생하는 동시성 문제를 방지하기 위한 방법중 하나이다

동기화 하지 않는 코드와 실행시간 비교시 성능적으로 불리한 측면이 있다.

싱글톤 패턴의 장단점

장점

  • 오직 한가지 인스턴스를 반환하는 것을 보장
  • 다른 클래스의 인스턴스들이 데이터를 공유하기 쉬워짐 💡 DataBase Connection Pool과 같은 공통된 객체를 여러개 생성하여 사용하는 경우 유용
  • 인스턴스를 생성할때 발생하는 비용이 줄어듬

단점

  • 다른 인스턴스들 간에 결합도가 높아짐 (즉 의존성이 높아지는 문제)
  • 개방-폐쇠 원칙에 위배됨
  • 멀티쓰레드 환경에서 인스턴스가 여러개 생성되는 문제가 발생 가능 💡 Thread-safe한 싱글톤 클래스를 설계하는 여러가지 방법이 존재함
  • TDD에서 싱글톤은 걸림돌이 됨 (단위 테스트가 어려움) 💡 단위 테스트에서는 서로 독립적이어야 하는데, 싱글톤 패턴은 각 테스트마다 독립적인 인스턴스를 생성하기 어려움

Spring Bean에서의 싱글톤

스프링 프레임워크에서 제공하는 강력한 기능 중 하나인 Spring Bean은 기본 스코프로 싱글톤 패턴을 사용한다.

Spring MVC에서 @Controller @Service @Repository 와 같이 Bean으로 설정된 컴포넌트들은 스코프를 따로 지정하지 않았다면 싱클톤 패턴이 적용된다. 그렇다면

한개의 컨트롤러가 어떻게 수많은 요청을 처리하나?

굉장히 멍청한 생각이 떠올랐다….., JVM의 구조 따위는 개나 줘버린 발상이다

나는 단순히 싱글톤 패턴이기 때문에 수많은 요청들을 하나의 인스턴스가 처리한다고? 라는 발상이 떠오른 것이다.

결론적으로

싱글톤 패턴은 인스턴스의 공유를 위함으로 설게를 하는데, 공유된 객체 자체는 힙 영역에 생성되지만 내부적인 정보 (메소드 등)은 메소드 영역에 생성되기 때문에 여러 요청이 들어온다 한들 싱글톤 패턴으로 인한 병목은 발생하지 않는다.

추가적으로 @Controller @Service @Repository 와 같은 컴포넌트들은 메소드를 공유하여 사용하기 위한 목적이지 특정한 상태(변수)를 공유하기 위한 컴포넌트가 아니라는 점이다. 때문에 동기화를 수행할 필요가 없다.

profile
기록하며 성장하는 개발자 김종태

0개의 댓글