Item 76. 가능한 한 실패 원자적으로 만들라
1. 들어가기
보통 일반적으로 예외가 발생하면 그 객체는 정상적으로 사용할 수 없습니다.
하지만 예외가 발생해도 객체를 여전히 정상적으로 사용할 수 있다면 아주 멋질 것입니다.
이러한 특성을 실패 원자성(failure-atomic)이라고 합니다.
이번에는 이 실패 원자성에 대해 알아보겠습니다.
2. 실패 원자성 (failure-atomic)
실패 원자성이란, 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지하는 것입니다.
이 실패 원자성은 시스템의 안정성, 성능 그리고 신뢰성을 향상시키는데 필수적인 특성입니다.
그럼 이러한 실패 원자성은 어떻게 만드는 것일까요?
3. 실패 원자성을 만드는 방법
-
불변 객체로 설계한다.
불변 객체는 태생적으로 실패 원자적입니다.
메서드가 실패하면 새로운 객체가 만들어지지 않지만, 불안정한 상태에 빠지지는 않기 때문입니다.
-
유효성 검사를 한다.
객체의 내부 상태를 변경하기 전에 유효성 검사를 하면 잠재적 예외의 가능성을 걸러낼 수 있습니다.
public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; return result; }
-
임시 객체를 사용한다.
데이터를 임시 자료구조에 저장해 작업하는 게 더 빠르다면 이 방법을 사용하는 것이 좋습니다.
예를 들어 어떤 정렬 메서드는 정렬 수행 전 입력 리스트의 원소들을 배열로 옮겨 담는 작업이 있는데
임시 객체인 배열을 사용하면 원소들에 훨씬 빠르게 접근할 수 있기에
성능을 높일 수도 있고 정렬에 실패하더라도 입력 리스트는 변하지 않는 장점이 있습니다.
-
복구 코드를 작성한다.
작업 도중 발생하는 실패를 가로채 복구 코드를 작성하여 작업 전 상태로 되돌리는 방법입니다.
주로 내구성을 보장해야 하는 자료구조에 사용하는데 자주 쓰이는 방법은 아닙니다.
4. 실패 원자성을 보장하기 어려운 경우
앞서 실패 원자성을 만드는 방법에 대해 설명했지만,
경우에 따라서는 실패 원자성을 보장하기 어려운 경우가 있습니다.
-
일관성이 깨진 경우
두 스레드가 동기화 없이 같은 객체를 동시에 수정하는 경우 일관성이 깨질 수 있습니다.
ConcurrentModificationException
을 잡아냈다고 해서 여전히 쓸 수 있는 상태라고 가정하면 안됩니다.추가적인 Lock 기법이나 동기화 도구가 필요합니다.
-
Error가 발생한 경우
Error는 복구할 수 없으므로 실패 원자성을 보장하려는 시도는 필요가 없습니다.
메서드 명세에 기술한 예외라면 설혹 예외가 발생하더라도 객체의 상태는 메서드 호출 전과 동일해야 합니다.
만약 이 규칙을 지키지 못한다면 실패 시 객체 상태를 API 설명에 명시해야 합니다.
📕 개인 기록용 블로그입니다.
😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
댓글남기기