Java Immutable Collection 만들기 완벽 이해하기
Java 실무에서 정말 자주 등장하는 중요한 개념이 바로:
Immutable Collection (불변 컬렉션)
입니다.
특히 최근 Java와 Spring 실무에서는:
- 사이드 이펙트 방지
- 멀티스레드 안정성
- 함수형 프로그래밍
- 방어적 복사(Defensive Copy)
- DTO 안정성
때문에 불변 객체/불변 컬렉션 사용이 매우 중요해졌습니다.
초보 시절에는 보통:
수정 못 하게 막는 List?
정도로 이해하기 쉽습니다.
하지만 실제로는:
- 읽기 전용 Wrapper
- 진짜 Immutable
- shallow copy
- defensive copy
- thread-safe 설계
까지 연결됩니다.
이번 글에서는:
- Immutable Collection이란?
- unmodifiableList()
- List.of()
- 진짜 불변과 가짜 불변 차이
- Defensive Copy
- 실무 설계 전략
까지 깊게 정리해보겠습니다.
1. Immutable이란?
Immutable object 는:
생성 이후 상태를 변경할 수 없는 것
입니다.
2. Immutable Collection이란?
즉:
추가/삭제/수정 불가능한 Collection
입니다.
예:
List<String> list =
List.of("A", "B");
현재:
list.add("C");
불가능.
3. 왜 중요할까?
핵심 이유:
사이드 이펙트 방지
입니다.
4. mutable Collection 문제
예:
public List<String> getNames() {
return names;
}
호출한 쪽에서:
names.add("Hacker");
가능.
즉 내부 상태 오염 가능.
5. 이것이 캡슐화 깨짐
외부에서:
객체 내부 상태 직접 수정
가능한 상황.
6. 그래서 Immutable 필요
목표:
읽기만 허용
입니다.
7. 가장 오래된 방식
대표:
Collections.unmodifiableList()
8. 예시
List<String> origin =
new ArrayList<>();
origin.add("Java");
List<String> immutable =
Collections.unmodifiableList(origin);
9. 이제 수정 시도
immutable.add("Spring");
결과:
UnsupportedOperationException
발생.
10. 그런데 중요한 문제
매우 중요합니다.
현재 이것은:
진짜 Immutable 아님
입니다.
11. 왜 아닐까?
원본 수정 가능.
origin.add("Spring");
하면:
System.out.println(immutable);
결과:
[Java, Spring]
변경됨.
12. 즉 Wrapper일 뿐
읽기 전용 View 제공
하는 것.
13. 이것이 shallow immutable
즉:
겉만 수정 불가
인 상태.
14. Java 9 이후 등장: List.of()
매우 중요.
List<String> list =
List.of("A", "B");
15. 특징
진짜 불변 Collection
입니다.
16. 수정 시도
list.add("C");
↓
UnsupportedOperationException
17. 차이점
중요.
원본 자체 수정 불가능
합니다.
18. Set.of(), Map.of()도 존재
Set.of(...)
Map.of(...)
전부 immutable.
19. List.of() 특징
| immutable | O |
| null 허용 안 함 | X |
| thread-safe 읽기 유리 | O |
20. null 금지
예:
List.of("A", null)
↓
NullPointerException
발생.
21. 왜 null 금지할까?
목표:
더 안전한 Collection
입니다.
22. 불변 컬렉션 장점
매우 중요.
| 장점 | 설명 |
| 사이드 이펙트 감소 | O |
| thread-safe 유리 | O |
| 디버깅 쉬움 | O |
| 상태 추적 쉬움 | O |
23. 함수형 프로그래밍과 연결
Functional programming 에서는:
상태 변경 최소화
매우 중요.
즉 Immutable 선호.
24. 멀티스레드 환경에서도 중요
mutable 객체는:
동시 수정 위험
존재.
Immutable은:
읽기만 가능
하므로 안전성 증가.
25. Defensive Copy란?
매우 중요한 실무 개념.
26. 문제 상황
class User {
private List<String> roles;
public List<String> getRoles() {
return roles;
}
}
현재:
내부 상태 노출
문제 존재.
27. 해결: Defensive Copy
public List<String> getRoles() {
return List.copyOf(roles);
}
28. 의미
복사본 반환
입니다.
즉 외부 수정 방지.
29. 생성자에서도 중요
예:
public User(List<String> roles) {
this.roles = List.copyOf(roles);
}
30. 왜 필요할까?
외부에서:
roles.add(...)
해도 내부 상태 보호 가능.
31. copyOf()란?
Java 10 이후 추가.
대표:
List.copyOf()
Set.copyOf()
Map.copyOf()
32. 특징
immutable 복사본 생성
입니다.
33. shallow copy 주의
매우 중요.
예:
List<User>
복사해도:
User 객체 자체는 공유
가능.
34. 즉 Collection만 불변
내부 객체까지 immutable 아님.
35. 진짜 완전 Immutable 조건
Collection 불변
+
내부 객체도 불변
이어야 함.
36. 불변 객체 설계 예시
final class User {
private final String name;
}
37. final만으로 충분할까?
아님.
내부 mutable 객체 주의
필요.
38. Arrays.asList() 주의점
매우 유명한 함정.
Arrays.asList("A", "B")
39. 완전 immutable 아니다
예:
list.set(0, "X");
가능.
40. 왜 그럴까?
고정 크기 List일 뿐.
즉:
size 변경만 금지
입니다.
41. 실무에서 많이 쓰는 패턴
대표:
return Collections.unmodifiableList(list);
또는:
return List.copyOf(list);
42. 어떤 걸 더 추천할까?
현대 Java에서는 보통:
List.copyOf()
List.of()
더 선호.
43. 성능 관점
Immutable은:
복사 비용
존재 가능.
하지만 대부분:
안정성 이점이 훨씬 큼
44. Spring에서도 매우 중요
Spring Framework DTO/Response 설계에서도 immutable 선호 증가.
특히:
- record
- final field
- List.copyOf()
조합 많이 사용.
45. 실무에서 자주 하는 실수
1) unmodifiableList를 진짜 immutable로 착각
원본 수정 가능.
2) shallow copy 문제 무시
내부 객체 변경 가능.
3) getter에서 mutable Collection 그대로 반환
캡슐화 깨짐.
4) Arrays.asList를 immutable로 착각
완전 불변 아님.
46. 핵심 흐름 요약
mutable collection
↓
defensive copy
↓
immutable wrapper/create
↓
외부 수정 차단
47. 가장 중요한 핵심 한 줄
진짜 Immutable Collection은
“외부에서 상태 변경이 절대 불가능해야 한다”
입니다.
48. 정리
Immutable Collection은 단순 읽기 전용 List가 아닙니다.
실제로는:
- 캡슐화
- 멀티스레드 안정성
- 함수형 프로그래밍
- Defensive Copy
- 불변 객체 설계
전체와 연결되는 매우 중요한 Java 설계 개념입니다.
특히 실무에서는:
- List.of()
- List.copyOf()
- unmodifiableList 차이
- shallow copy 문제
- immutable DTO 설계
를 정확히 이해하는 것이 매우 중요합니다.
다음 글에서는:
ConcurrentHashMap 기초
를 synchronizedMap 차이, CAS, segment 구조, 동시성 처리 원리까지 포함해서 깊게 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java 람다 표현식(Lambda) 완벽 이해하기 (0) | 2026.05.27 |
|---|---|
| Java ConcurrentHashMap 기초 완벽 이해하기 (0) | 2026.05.27 |
| Java Wildcard (<? extends T>, <? super T>) 완벽 이해하기 (0) | 2026.05.27 |
| Java Generic(제네릭) 기초 완벽 이해하기 (0) | 2026.05.27 |
| Java Iterator와 Iterable 완벽 이해하기 (0) | 2026.05.27 |
댓글