실패 원자성
- 호출된 메서드가 예외 발생으로 인해 실패하더라도 객체가 메서드 호출 전 상태를 유지하는 특성
- 실패 원자성이 보장되면 Checked Exception을 던졌을 때 호출자가 오류 상태를 복구할 수 있으므로 유용함
메서드를 실패 원자적으로 만드는 방법은 총 네 가지가 있으며 다음과 같습니다.
- 불변 객체로 설계
- 매개변수 유효성 검사
- 복사본에 로직을 수행 후, 성공적으로 수행이 완료될 경우에만 원본 객체와 Swap
- 작업 도중의 에러를 가로채는 복구 코드를 작성하여 롤백
1. 불변 객체로 설계
- 불변 객체는 생성 시점에 고정되어 절대 변하지 않기 때문에 태생적으로 실패 원자적
- 메서드가 실패하면 새로운 객체가 생성되지 않을 수 있으나 기존 객체가 불안정한 상태에 빠지는 일은 없음
2. 매개변수 유효성 검사
- 가변 객체의 메서드를 실패 원자적으로 만드는 가장 흔한 방법은 작업 수행에 앞서 매개변수의 유효성을 검사하는 것
- 객체의 내부 상태를 변경하기 전 잠재적 예외의 가능성 대부분을 걸러낼 수 있는 방법
- 비슷한 취지로 실패 가능성이 있는 모든 코드를 객체의 상태를 바꾸는 코드보다 앞에 배치하는 방법도 존재
- 계산을 수행해 보기 전 인수의 유효성을 검사해 볼 수 없을 때 앞서의 방식에 덧붙여 쓸 수 있는 기법
- ex) TreeMap은 원소들을 어떤 기준으로 정렬하며 TreeMap에 원소를 추가하려면 해당 원소가 TreeMap의 기준에 따라 비교할 수 있는 타입임을 보장해야 함
- 엉뚱한 타입의 원소를 추가하려들면 트리를 변경하기 앞서, 해당 원소가 들어갈 위치를 찾는 과정에서 ClassCastException 예외 던짐
3. 복사본에 로직을 수행 후, 성공적으로 수행이 완료될 경우에만 원본 객체와 Swap
- 데이터를 임시 자료구조에 저장해 작업하는 것이 더 빠를 때 적용하기 좋은 방식
- ex) 정렬 메서드에서는 정렬을 수행하기 전에 입력 리스트의 원소들을 배열로 옮겨 담음
- 배열을 사용하면 정렬 알고리즘의 반복문에서 시간복잡도 O(1)으로 원소들에 훨씬 빠르게 접근할 수 있음
- 혹시나 정렬에 실패하더라도 입력 리스트는 변하지 않는 효과도 덤으로 얻음
4. 작업 도중의 에러를 가로채는 복구 코드를 작성하여 롤백
- 주로 (디스크 기반의) 내구성을 보장해야 하는 자료구조에 쓰이는데, 자주 쓰이는 방법은 아님
실패 원자성을 보장할 수 없거나 필요 없는 케이스
- 실패 원자성은 일반적으로 권장되는 덕목이지만 항상 달성할 수 있는 것은 아님
- ex) 멀티 쓰레드 환경에서 동기화 없이 같은 객체를 동시에 수정할 경우 해당 객체의 일관성이 깨질 수 있음
- 따라서, ConcurrentModificationException을 잡아냈다고 해서 그 객체가 여전히 쓸 수 있는 상태라고 가정해서는 안됨
- Error는 복구할 수 없으므로 AssertionError에 대해서는 실패 원자적으로 만들려는 시도조차 할 필요 없음
- 실패 원자적으로 만들 수 있더라도 실패 원자성을 달성하기 위한 비용이나 복잡도가 아주 큰 연산일 경우 보장하지 않아도 됨
- ex) 대용량 파일을 정렬하거나 검색할 때는 전체 파일을 메모리에 로드하는 것은 불가능할 수 있으며, 대신 파일을 여러 조각으로 나누어 처리해야 할 수 있음
- 이러한 작업을 수행할 때 실패 원자성을 보장하는 것은 매우 어려울 수 있음
결론
- 메서드 명세에서 기술한 예외라면, 예외가 발생하더라도 발생하기 전의 객체와 동등한 상황 즉 실패 원자성을 보장해야 함
- 그러나, 실패 원자성을 담보할 수 없다면 예외 이후 객체의 상황을 API 설명에 명시해야 함
참고
이펙티브 자바
반응형
'JAVA > Effective Java' 카테고리의 다른 글
[아이템 78] 공유 중인 가변 데이터는 동기화해 사용하라 (0) | 2024.03.29 |
---|---|
[아이템 77] 예외를 무시하지 말라 (2) | 2024.03.29 |
[아이템 75] 예외의 상세 메시지에 실패 관련 정보를 담으라 (0) | 2024.03.29 |
[아이템 74] 메서드가 던지는 모든 예외를 문서화하라 (0) | 2024.03.28 |
[아이템 73] 추상화 수준에 맞는 예외를 던지라 (0) | 2024.03.27 |