불변 객체와 가변 객체가 메모리 관리에 미치는 영향
F-Lab : 상위 1% 개발자들의 멘토링
AI가 제공하는 얕고 넓은 지식을 위한 짤막한 글입니다!

서론
객체 지향 프로그래밍에서 객체의 속성은 크게 불변성(immutable)과 가변성(mutable)으로 나뉩니다. 불변 객체는 생성 후에 상태가 변하지 않으며, 가변 객체는 상태 변경이 가능합니다. 이 두 가지 유형의 객체는 메모리 관리 측면에서 서로 다른 영향을 미칩니다. 이번 포스트는 불변 객체와 가변 객체가 메모리 관리, 특히 가비지 컬렉션(GC)에 어떠한 영향을 미치는지 알아보고자 합니다.
왜냐하면 불변 객체는 주로 수명이 짧아 GC의 청소 대상이 되기 쉽고, 가변 객체는 오랫동안 참조되며 메모리에 남아 있을 가능성이 크기 때문입니다.
불변 객체를 사용하는 것은 메모리 측면에서 어떤 장단점이 있으며, 성능적인 이점이 존재하는지 확인해 보겠습니다. 또한, JVM에서의 메모리 관리 구조인 영 제너레이션(Young Generation)과 올드 제너레이션(Old Generation)에 대해서도 설명하겠습니다.
결론적으로 불변 객체가 메모리 관리에서 제공하는 이점과 그 제한점을 이해할 수 있을 것입니다.
불변 객체와 가변 객체의 기본 이해
불변 객체는 객체 생성 이후 내부 상태를 변경하지 못하는 객체입니다. 자바에서는 대표적으로 String 클래스가 불변 객체로 구현되어 있습니다. 모든 메서드 호출 이후 새로운 객체를 반환하며, 원본 객체는 그대로 유지됩니다.
가변 객체는 상태가 변할 수 있는 객체로, 리스트나 맵 등이 이에 속합니다. 객체의 메서드 호출을 통해 그 내부 상태를 수정할 수 있습니다.
불변 객체는 사고하기에 안전하고 멀티스레드 환경에서 동기화를 필요로 하지 않는 장점이 있지만, 객체 할당이 자주 발생하여 메모리 사용량이 증가할 수 있습니다.
가변 객체는 상태 변경에 용이하며, 여러 번 데이터 변경시 메모리 할당을 최소화할 수 있습니다. 그러나 상태가 변할 수 있으므로 멀티스레드 환경에서 동기화 처리가 필요합니다.
왜냐하면 불변 객체는 생성시 모든 데이터가 초기화되기 때문에 thread-safe하며, 가변 객체는 상태를 변경하는 과정에서 데이터 정합성이 깨질 수 있기 때문입니다.
불변 객체가 메모리에 미치는 영향
불변 객체는 JVM에서 메모리 관리 측면에서 이점을 가집니다. 그 수명이 짧아 영 제너레이션 공간에서 주로 관리됩니다. GC는 이 공간을 효율적으로 청소하고, 짧은 수명 객체의 청소 주기는 자주 이루어집니다.
왜냐하면 영 제너레이션 공간은 짧은 수명의 객체에 최적화되어 있어, 가비지 컬렉션의 빈도 및 속도를 빠르게 해 성능 향상을 이루기 때문입니다.
불변 객체가 졸업하지 않고 바로 제거되면, 올드 제너레이션 공간의 부하를 줄일 수 있습니다. 이는 가비지 컬렉션 시 스톱 더 월드(STW) 시간을 줄이는 역할을 하게 됩니다.
불변 객체의 단점은 메모리 파편화를 야기할 수 있다는 점입니다. Java는 공간 재사용을 꾀하지만, 잦은 메모리 할당과 해제를 반복하다 보면 파편화가 발생할 수 있습니다.
이러한 단점에도 불구하고, 불변 객체는 메모리 관리를 효율적으로 하려는 많은 시스템 설계에 사용됩니다. 이는 안정성과 유지보수성 측면에서 중요한 이점을 제공합니다.
가변 객체의 메모리 활용 전략
가변 객체는 상태 변경이 자유롭다는 장점 때문에 메모리 관리 전략이 달라집니다. 초기화 시점에서 메모리를 할당받아야 하며, 필요에 따라 동적으로 메모리를 증설해야 합니다.
왜냐하면 가변 객체는 중간에 삽입이나 삭제가 빈번히 발생할 수 있으며, 이로 인해 메모리 내부 정렬 및 관리 작업이 필요하기 때문입니다.
올드 제너레이션에서는 메모리를 많이 사용하는 객체가 오랫동안 남아 있을 가능성이 큽니다. 이는 가비지 컬렉션 시에 STW 시간이 길어지는 원인이 됩니다.
가변 객체에 대한 메모리 관리 최적화는 객체의 사용 패턴을 깊이 이해하는 것이 우선되며, 필요에 따라 객체 수명을 조절하여 메모리 사용의 효율성을 높여야 합니다.
이러한 전략적 측면에서 불변 객체와 가변 객체 각각의 장점을 이용하여 적절한 균형을 찾는 것이 많은 시스템 구현에서 관건이 됩니다.
결론
객체지향 프로그래밍에서 불변 객체와 가변 객체의 사용은 메모리 관리 및 성능 최적화의 중요한 결정 요소입니다. 각각의 객체는 고유한 장단점을 가지고 있으며, 시스템의 요구사항에 따라 적절하게 선택되어야 합니다.
왜냐하면 가비지 컬렉션의 효율성, 메모리 사용량, 스레드 안전성 등이 불변/가변 객체의 선택에 큰 영향을 미치기 때문입니다.
불변 객체는 안전하고 직관적인 구조를 제공하면서도 메모리 파편화의 이슈가 있을 수 있어, 사용 시 주의가 필요합니다.
가변 객체는 메모리와 CPU 사이의 적절한 트레이드 오프를 필요로 하며, 어떤 경우에는 오랜 수명이 시스템 성능에 부정적인 영향을 미칠 수도 있습니다.
결국 프로젝트의 성격, 동작 환경, 성능 요구 사항 등을 고려하여 불변성과 가변성의 선택을 해야 하며, 이는 개발 초기 단계에서 깊이 고려되어야 하는 부분입니다.
이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.




