초보 개발자의 성장기

genieus와 함께하는 JAVA - 불변객체와 가변객체 본문

BackEnd 지식

genieus와 함께하는 JAVA - 불변객체와 가변객체

개발자 김케빈 2021. 12. 13. 00:45

기술면접을 볼 때나 코드 리뷰를 할 때

불변객체와 가변객체라는 말을 많이 듣는 경우를 많이 봤습니다.

그래서 이번에는 자바에서 중요한 개념으로 사용되는

불변객체와 가변객체에 대해 알아보겠습니다!


 

1. 불변객체

불변객체의 뜻을 먼저 설명하면 class의 instance가 생성된 이후 객체 내부 상태가 변하지 않고 유지되는 객체를 의미합니다.

즉, 한번 객체가 만들어지면 수정이 불가능합니다.


그러면 불변객체를 사용할까요?


-> 그 이유는 안정성 때문입니다. 불변객체는 multi-thread 환경에서도 안전하다는 특징이 있습니다.
다수의 thread가 불변객체에 접근하여 수정하려고 해도 불변객체의 특성 상 수정이 불가능합니다.

또한, 객체 자체가 변경이 되면 안되게 설계할 때도 사용하고 있습니다.

따라서, 객체의 값이 할당될 때 마다 새로운 메모리 주소를 가지고 있습니다. (메모리 누수와 성능저하 유발 ㅠㅠ)
즉, 같은 메모리 공간을 가질 수 없습니다. (== Heap 영역에서 객체의 값을 바꿀 수 없음!!)

그렇다면 불변객체를 어떻게 사용하면 될까요?

(1) 기본적으로 자바에서 불변객체로 정의한 클래스들이 있습니다. String, Boolean, Integer, Float, Long

(2) 모든 클래스 변수를 final로 만들어 불변객체로 사용할 수 있습니다.

(3) 모든 클래스의 변수의 setter 메서드 선언을 안함으로써 불변객체로 생성할 수 있습니다.

(4) class를 상속하지 못하게 만들어 사용할 수 있습니다.  class를 final로 만들거나 생성자를 private로 생성합니다.

위 4가지 방법을 사용함으로써 불변객체를 생성할 수 있습니다.

 

2.  가변객체

가변객체란? 불변객체와 반대로 객체 내부 상태가 언제든 변할 수 있는 객체를 의미합니다.

가변객체는 
가변객체는 불변 객체와 달리 multi-thread 환경에서 안전하지 않습니다.
따라서, multi-thread 환경에서 가변 객체를 사용할 때는 별도의 동기화 처리를 활용하여 사용해야 합니다. 

 

가변 객체의 클래스는 어떤 것이 있을까요? List, Dict, Set, Map, StringBuffer, StringBuilder

 

3.  불변객체인 String와 가변객체인 StringBuffer & StringBuilder

결론부터 말하겠습니다.

불변객체인 String은 참조 값을 변경할 때 마다 새로운 객체를 생성해줘야 합니다. (각자 객체들이 서로 다른 메모리 공간 보유)
하지만 StringBuffer와 StringBuilder는 참조 값을 변경하더라도 새로 객체를 만드는 것이 아니라 기존 할당된 값을 수정합니다.
즉, 문자열 변경과 연산을 하는 경우 기존의 버퍼 크기를 늘리거나 줄이면서 유연하게 동작하게 됩니다.


그렇다면 두 클래스의 차이는 무엇일까요?

StringBuffer같은 경우는 multi-thread 환경에서 사용이 가능하도록 모든 주요 메서드들이 synchronized 처리(동기화 처리)
되어있지만 StringBuilder는 아닙니다.
만약 multi-thread환경에서 안전하게 String 객체를 보장하려면 StringBuffer를 사용해야합니다.
굳이 multi-thread 환경을 고려하지 않고 single-thread 환경에서 사용한다면 성능이 뛰어난 StringBuilder를 사용하면 됩니다.
왜냐하면 StringBuilder는 동기화 처리가 되어있지 않아 동기화 처리 과정이 필요가 없어 single-thread에서 뛰어난 성능을 보여줍니다.

Comments