ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 불변 객체(Immutable Object)와 final을 사용해야 하는 이유
    Programming/Java 2023. 5. 28. 21:20
    반응형

    프로젝트를 진행하며 의존성 주입을 위해 private final을 써왔었다.
    그런데 이 final이라는 것에 대해 제대로 고민하고 다른 객체에 사용해본 적이 없는 것 같아
    Gotcha 프로젝트를 리팩토링하며 배운 내용들을 포스팅해보고자 한다.

    불변 객체(Immutable Object)란?

    : 객체 생성 이후 내부의 상태가 변하지 않는 객체 ➡️ 한 번 생성이 된 불변 객체는 신뢰할 수 있다.
    - read-only 메소드만 제공하며 객체의 내부 상태를 제공하는 메소드를 제공하지 않거나 방어적 복사를 통해 제공

    - Java의 String은 대표적인 불변 클래스로 String Pool이라는 공간에 String 객체를 보관하고 있음
    - 변수에 새로운 값을 할당할 경우 객체의 value가 변하는 것이 아닌 새로운 객체가 생성되어 해당 객체를 참조하게 됨

    String str1 = "Hello World";
    String str2 = "Hello World";
    
    System.out.println("변경전 hashcode : " + str1.hashCode());
    System.out.println("변경전 hashcode : " + str2.hashCode());
    
    str1 = "Hi World";
            
    System.out.println("변경후 hashcode : " + str1.hashCode());
    System.out.println("변경후 hashcode : " + str2.hashCode());

    불변 객체 사용의 장점

    1. Thread-safe하여 스레드 동기화 문제를 방지할 수 있다.

    [불변 객체가 아닐 경우]

    - 아래와 같은 코드가 있고, 2개의 스레드에서 동시에 Money 객체를 생성하고자 할 때,

    money 값이 각 10,000과 500일 경우 시점차에 의해 10,000값을 넣은 객체의 결과가 500이 될 수 있음

    - 로직에는 문제가 없지만 객체가 불변이 아니기 때문에 값이 다른 입력값에 의해 변화되는 상황이 발생하는 것

    public class Money {
    	private int money;
        
        public Money(final int money) {
        	this.money = money;
        }
        
        public void add(final int money) {
        	int addResult = this.money + money;
            this.money = addResult;
        }
    }

    [불변 객체로 바꿔본다면?]

    - 객체의 값은 변하지 않고, plus 메소드를 통해 새로운 객체를 전달하게 함으로써, 객체의 데이터 불변성을 보존할 수 있음

    private final class Money {
    	private final int money;
        
        private Money(final int money) {
        	this.money = money;
        }
        
        public static Money of(final int money) {
        	return new Money(money);
        }
        
        public Money plus(final int money) {
        	return new Money(this.money + money);
        }
    }

    2. 자체로 실패 원자성을 제공한다.

    📍 실패 원자성(Failure-atomic) 이란?
    - 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지하는 특성

    - 가변 객체를 통해 작업하는 도중 예외가 발생하면 해당 객체가 불안정한 상태에 빠질 수 있음(값이 변경된 상태)

    - 불변 객체라면 어떠한 예외가 발생하여도 메소드 호출 전 상태를 유지할 수 있으며, 예외가 발생하더라도 이후 오류가 발생하지 않은 것처럼 다음 로직을 처리할 수 있음

    3. 서비스의 안정성이 높아질 수 있다.

    - 부수효과(변수의 값이나 상태 등 변화가 발생하는 효과)를 피해 오류 가능성을 최소화할 수 있음
    - 오류를 줄여 유지보수성이 높은 코드를 작성할 수 있음
    - 협업에 있어서도 다른 사람이 작성한 함수를 예측 가능하게 하며 안전하게 사용할 수 있게 함

     

     

    참고 사이트

    https://youtu.be/ej-bnXlHk-E

    https://mangkyu.tistory.com/131

    반응형

    댓글

Designed by Tistory.