본문 바로가기
Framework/Spring Framework

[Spring Framework] 싱글톤(Singleton)의 개념

by 원동호 2018. 7. 25.

싱글톤이란 무엇일까?

 

 

싱글톤을 알기위해서는 동일성, 동등성에 대해서 알 필요가 있다.

두 변수의 값을 비교하기 위해, 우리는 == 연산자를 사용했다.

 

하지만 이 연산자를 이용한 비교는 , primitive(원시) 타입의 자료형에만 해당되는 사항이다.

primitive 타입 자료형이란 int, double, char, boolean 등의 기본 자료형을 말한다.

하지만 자바에서 지원하는 타입은 primitive 타입만이 있는것이 아니다.

우리가 흔히 사용하는 오브젝트, 주소값을 가지는 reference타입 이라는 자료형도 존재한다.

 

reference 타입이란 우리가 흔히 사용하는 ,new 연산자로 생성할 수 있는 오브젝트를 말한다.

new 연산자란 간단히 클래스의 오브젝트를 생성하는 연산자라고 표현할 수 있지만, 좀 더 상세하게 얘기하면 클래스의 오브젝트를 생성하여 메모리에 올리고, 그 참조변수를 반환해주는 연산자 이다.

 

primitive 타입과의 차이점이 여기서 발생한다. 바로 참조변수 라는 개념이다. 참조변수란 주소값을 의미하며 , 메모리에 올라간 오브젝트를 가리키는 주소값이다. 이러한 reference 타입 자료형을 비교할 때는 primitive 타입 변수와는 달리, 값의 비교가 두 가지의 의미를 가지게 된다.

 

바로 동일성과 동등성의 개념이다.

 

동일하다 는 두 개의 오브젝트가 완전히 같을 경우를 의미하고,

동등하다 는 두 오브젝트가 같은 정보를 갖고 있을 경우를 의미한다.

 

동일하다 의 경우 == 연산자로 표시되고, 동등하다 의 경우 equals 연산자로 표시된다.

오브젝트 간 == 연산자는 주소값의 비교, equals는 내용의 비교가 된다.

== 연산자가 성립한다는 것은 주소값이 같다는 의미이고, 결국 두 변수가 같은 오브젝트를 가리키고 있다는 의미이다.

 

String 클래스를 예로 들어 보겠다.

 

String 클래스는 두 가지 생성 방식이 있으며, 각각의 차이점이 존재한다.

 

1. new 연산자를 이용한 방식 -> Heap 영역에 존재

 

2. 리터럴("")을 이용한 방식 -> string constant pool 영역에 존재

 

public class Stringtest{ 
	public static void main(String[] args) {
	
	String test1 = new String("String"); 
	String test1_1 = new String("String"); 
	String test2 = "StringA"; 
	String test2_1 = "StringA"; 
	System.out.println("test1 : " + System.identityHashCode(test1 )); 
	System.out.println("test1_1 : " + System.identityHashCode(test1_1 )); 
	System.out.println(); 
	System.out.println("test2 : " + System.identityHashCode(test2 )); 
	System.out.println("test2_1 : " + System.identityHashCode(test2_1 )); 
	} 
}

 

결과는 어떻게 될까?

test1 과 test1_1 은 new 연산자로 생성 하였기때문에 Heap 영역에 다른 주소( 다른 객체) 로 생성 될 것이다.

하지만

test2 와 test2_1 은 주소값이 같다.

 

왜일까?

 

JVM 에서 String을 조금 특별하게 관리하기 때문이다. new 연산자가 아닌 리터럴("")을 이용해서 String 객체를 생성하면 JVM은 먼저 String constant pool 영역을 찾아간다. JVM은 String constant pool 영역에서 이전에 같은 값을 갖고 있는 String 객체가 있는지 찾은 후, 같은 값을 갖고 있는 String 객체가 존재 하면 해당 객체의 주소값을 반환하여 참조하도록 한다.

결국 test2와 test2_1의 주소가 같은 이유는 String constant pool의 객체를 참조하고 있기 때문이다.

 

※ 결론 : 자바에서는 문자열 상수에 대해서 문자열이 동일할 경우 하나의 인스턴스만 생성하고, 이를 공유하도록 한다.

 

출처: 

http://joont.tistory.com/143

 [Toward the Developer]

 
다시 본문으로 돌아와서 싱글톤은 해당 클래스의 인스턴스가 하나만 만들어지는 ,전역 변수와 같은것을 말한다.보통 객체가 여러개 있는 것 보다 하나만 있어야 하는 경우에 사용한다. EX) DB CONNECTION POOL
스프링은 모든 빈 객체들을 싱글톤으로 관리를 한다고 했었다.

 

AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
Student student1 = ctx.getBean("student", Student.class); 
Student student2 = ctx.getBean("student", Student.class); 

if(student1.equals(student2)) { 	
	System.out.println("student1 == student2"); 
} else { 	
	System.out.println("student1 != student2"); 
} 

위 소스는 "student"라는 이름을 가진 빈을 2번 가져와서 비교했다. 결과는 어떻게 나올까?

student1==studnet2 라고 출력될 것이다.

두 오브젝트는 동일하며, 설정파일에서 빈을 가져올 때마다 오브젝트를 새로 생성하지 않는다.

 

왜 스프링에서는 위와 같이 빈을 싱글톤으로 만들까?

 

Student 클래스를 예로 들어보자면 , 학생 정보 조회 기능을 하는 selectStudentInfo 형태의 메소드가 있다고 하면,

이 Student 클래스는 웹 사이트에서 학생 정보 조회하는 페이지 마다 다 사용될 것이다.

 

이러한 Student 클래스를 클라이언트에서 요청이 올 때마다 새로 만들어서 사용한다고 가정해본다면?

 

클라이언트가 10번 요청하면 10개의 오브젝트가 생성되고 600번 요청하면 600개의 오브젝트가 생성될것이며 결국 서버에 부하가 오게 될것이다. 그래서 스프링은 각각의 빈들은 싱글톤으로 관리하고, 멀티 스레드에서 이를 공유하며 사용 할 수 있게 해주는 것이다.

 

 

 

 

댓글0