일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 1px border
- 10px
- github
- es6
- npm
- 컴포넌튼
- 데이터베이스 #try #이중
- Props
- 0.25px border
- 서버리스 #
- 0.5px border
- 당근마켓
- 0.75px border
- ES5
- ZOOM
- entity
- TS
- font-size
- Strict
- 전역변수
- 타입스크립트
- 으
- jwt
- &연산
- Websocket
- TypeScript
- angular
- 클론코딩
- 문서번호
- literal
- Today
- Total
복잡한뇌구조마냥
[JAVA] Effective Java - 다 쓴 객체 참조를 해제하라 (7) 본문
✅ 요약
Java는 가비지 컬렉터(GC)가 메모리를 자동으로 관리해주지만, 프로그래머의 실수로 인해 메모리 누수(Memory Leak) 가 발생할 수 있습니다. 특히, 다 쓴 객체를 참조한 채로 계속 유지하면 GC가 회수하지 못해 성능 저하와 OutOfMemoryError로 이어질 수 있습니다. 이를 방지하기 위해 다 쓴 참조는 명시적으로 해제하거나, 유효 범위를 벗어나게 하여 참조를 제거해야 합니다.
🔍 1. 왜 메모리 누수가 발생할까?
Java는 명시적인 free() 호출이 없기 때문에, 객체가 더 이상 사용되지 않더라도 참조만 유지되면 GC가 회수하지 않습니다.
즉, 다음과 같은 경우는 모두 메모리 누수로 이어질 수 있습니다:
- 컬렉션(List, Map 등)에 넣은 뒤 제거하지 않음
- 콜백이나 리스너 등록 후 해제하지 않음
- 캐시 사용 후 청소하지 않음
객체의 생존 여부는 “사용 여부”가 아니라 “참조 여부”로 결정된다.
🧼 2. 해결 방법 – 참조 해제
💡 명시적으로 null 처리
사용이 끝난 객체의 참조를 null로 설정하면, 더 이상 참조하지 않음을 명확히 할 수 있습니다.
someResource = null;
단, 무조건 null 처리하는 습관은 오히려 코드 가독성을 해치고, NullPointerException을 유발할 수 있으므로 꼭 필요한 경우에만 사용하는 것이 좋습니다.
💡 가장 좋은 방법: 유효 범위 밖으로 밀어내기
가능하다면, 객체의 스코프(유효 범위)를 최소화하는 것이 가장 자연스러운 참조 해제 방법입니다.
예: 지역 변수는 메서드 종료 시 자동으로 GC 대상이 됨.
🧊 3. 캐시 사용 시 주의할 점
📌 캐시도 메모리 누수의 주범
캐시에 데이터를 저장한 뒤 제거하지 않으면 불필요한 객체들이 계속 남게 됩니다.
✅ 해결책 1: WeakHashMap 사용
WeakHashMap은 키에 대한 참조가 약(weak)하기 때문에, GC가 회수할 수 있으며, 더 이상 사용하지 않는 엔트리는 자동으로 제거됩니다.
Map<Key, Value> cache = new WeakHashMap<>();
✅ 해결책 2: LinkedHashMap의 removeEldestEntry() 오버라이드
캐시의 크기를 제한하거나, 오래된 데이터를 제거하는 방법입니다.
LinkedHashMap<String, Object> cache = new LinkedHashMap<>(16, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
return size() > MAX_CACHE_SIZE;
}
};
✅ 해결책 3: 더 복잡한 캐시는 java.lang.ref 패키지 활용
SoftReference, WeakReference, PhantomReference 등을 사용해 메모리 상황에 따라 유연하게 캐시를 제어할 수 있습니다.
🔄 4. 리스너/콜백 관리도 중요
콜백이나 이벤트 리스너를 등록한 뒤 해제하지 않으면 계속 쌓이기만 하며 메모리 누수가 발생합니다.
이런 경우에도 약한 참조(WeakReference)를 사용하면 GC가 수거할 수 있습니다.
🧠 5. 디버깅과 예방이 핵심
- 메모리 누수는 즉시 드러나지 않기 때문에, 수년간 발견되지 않다가 갑자기 OutOfMemoryError를 일으킬 수 있습니다.
- 힙 프로파일러(VisualVM, Eclipse Memory Analyzer 등)를 사용해 누수를 확인할 수 있습니다.
- 리뷰와 정적 분석 도구, 테스트를 통해 평소에 예방하는 습관이 중요합니다.
✍️ 마무리
Java는 메모리를 자동으로 관리하지만, 개발자가 직접 메모리 관리를 신경 써야 하는 경우도 있습니다.
특히, 다 쓴 객체의 참조를 해제하지 않으면 성능 저하와 치명적인 에러로 이어질 수 있기 때문에, 이를 방지하는 습관을 길러두는 것이 중요합니다.
“명확한 생명주기 관리 = 안정적인 프로그램 운영”
'BE > JAVA' 카테고리의 다른 글
[JAVA] JSP ( Java Server Pages ) (0) | 2025.08.07 |
---|---|
[JAVA] Effective Java - clone 재정의는 주의해서 진행하라 (13) (4) | 2025.08.03 |
[JAVA] 반복문 간결하게 쓰는 법 - 람다와 메서드 참조로 리팩토링 (2) | 2025.07.29 |
[JAVA] 구성 ( Composition ) (0) | 2025.07.29 |
[JAVA] 스트림 ( Stream ) (0) | 2025.07.28 |