Mutable vs Immnutable
Mutable
- 생성된 후 내부 값이 변경 될 수 있는 객체
- ex)
HttpServleResponse, StringBuilder, List, Map, Date, Entity
Immnutable
- 한 번 생성되면 내부 값이 변경될 수 없는 객체
- ex)
String, Integer, LocalDateTime, BigDecimal
예시
Mutable
public class CustomFilter extends OncePerRequestFilter {
protected void doFilterInternal(... HttpServletResponse response, ...) {
...
makeResponse(response);
return;
}
private void makeResponse(HttpServletResponse response) throws IOException {
CustomException exception = new CustomException(ExceptionCode.NOT_LOGGED_IN);
CommonResponse<String> result = new CommonResponse<>(exception.getExceptionCode().getStatus(), exception.getMessage());
response.setStatus(result.getCode());
response.setContentType("application/json; charset=UTF-8");
String json = objectMapper.writeValueAsString(result);
response.getWriter().write(json);
response.flushBuffer();
}
}
- 동일한 하나의 객체 내부 속성 값이 변경
- 같은 객체를 계속 수정
Immutable
String s = "hello";
s.toUpperCase();
- s 자체가 바뀌는게 아니라 새로운 String이 만들어지고 반환됨
번외
스레드 안전→ Immutable 선호
- 서로가 값을 바꾸지 못함
- Lock, Synchronized 필요 없음
- 캐싱, 공유 안전
mutable 객체는 위험한 이유
- 예상 못한 결과
- lost update
- 데이터 불일치
JPA Entity가 Mutable
- JP가 제공하는 여러 기능은 객체의 값이 변경되는 것을 전제로 만듦
Dirty Chcking (변경 감지)
community.update(request)
- community Entity 필드 변경
- JPA가 Heap의 Entity 정보를 감시
- 바뀌면 Update 실행
1차 캐시 & 동일성 보장
Community c1 = repo.findById(1L);
Community c2 = repo.findById(1L);
System.out.println(a == b);
- 이 객체들이 변경되면 동일 객체에 직접 반영되도록 의도된 구조
정리
단순 비교
| mutable 객체 | immutable 객체 |
|---|
| 값 수정 가능 | 값 수정 불가 |
return 필요 없음 → 내부 상태가 바뀌면 그 객체가 곧 결과 | 값 변경하려면 새 객체를 만들어야 함 |
HttpServletResponse, Entity, List | String, LocalDateTime, Integer |
스레드 비교
| 스레드 안전성 | immutable | mutable |
|---|
| 안전성 | 매우 높음 | 낮음 |
| 공유 | 쉬움 | 위험 |
| Lock 필요 | 없음 | 필요 |
| 성능 | 좋음 | 나쁠 수 있음 |
객체 종류 비교
| 객체 종류 | mutable 여부 | 이유 |
|---|
| 엔티티(Entity) | mutable | Dirty Checking, 연관관계, 변경 편의 |
| DTO / Value Object | immutable | 응답, 요청, DDD의 ValueObject는 안전하게 공유 가능 |