Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

아이템 76: 가능한 한 실패 원자적으로 만들라 #72

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 아이템 76: 가능한 한 실패 원자적으로 만들라

- 작업 도중 예외가 발생해도 그 객체는 여전히 정상적으로 사용할 수 있는 상태는 참 멋지다.
- 일반화해 이야기하면, 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지해야 한다.
- 이러한 특성을 실패 원자적이라고 한다.

## 메서드를 실패 원자적으로 만드는 방법
- 메서드를 실패 원자적으로 만드는 방법은 다양하다.
- 이어지는 글에서 방법을 하나씩 살펴보자.

## 실패 원자적으로 만드는 방법 1: 불변 객체
- 가장 간단한 방법은 불변 객체로 설계하는 것.
- 불변 객체는 태생적으로 실패 원자적이다.
- 메서드가 실패하면 새로운 객체가 만들어지지는 않을 수 있으나 기존 객체가 불안정한 상태에 빠지는 일이 없기 때문

## 실패 원자적으로 만드는 방법 2: 코드 배치 수정
- 실패할 가능성이 있는 모든 코드를 객체의 상태를 바꾸는 코드보다 앞에 배치할 수 있다.
```java
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
element[size] = null;
return result
}
```
- 위의 코드가 이와 비슷한 취지라고 볼 수 있다.

## 실패 원자적으로 만드는 방법 3: 객체의 임시 복사본에서 작업을 수행
- 객체의 복사본에서 작업을 수행하고 작업이 성공적으로 완료되면 원래 객체와 교체하는 방식이다.
- 데이터를 임시 자료구조에 저장해 작업하는 것이 더 빠를 때 쓰기 좋은 방식이다.

## 실패 원자적으로 만드는 방법 4: 복구 코드를 이용한 롤백
- 작업 도중 발생하는 실패를 가로채는 복구 코드를 작성하여 작업 전 상태로 되돌리는 방법이다.
- 자주 쓰이는 방법은 아니다.

## 실패 원자성을 챙길 수 없는 경우
- 실패 원자성은 일반적으로 권장되는 덕목.
- 하지만 항상 달성할 수 있는 것은 아니다.
- 예를 들어 두 스레드가 동기화 없이 같은 객체를 동시에 수정한다면 그 객체의 일관성이 깨질 수 있음.
- 따라서 `ConcurrentModificationException`을 잡아냈다고 해서 그 객체가 여전히 쓸 수 있는 상태라고 가정해서는 안된다.
- 그리고 실패 원자적으로 만들 수 있더라도 항상 그리해야 하는 것도 아니다.
- 실패 원자성을 달성하기 위한 비용이나 복잡도가 아주 큰 연산도 있기 때문.
- 메서드 명세에 기술한 예외라면 설혹 예외가 발생하더라도 객체의 상태는 호출 전과 똑같이 유지돼야 한다는 것이 기본 규칙이다.
- 이 규칙을 지키지 못한다면 실패 시의 객체 상태를 API설명에 명시해야 한다.
- 이것이 이상적이지만 아쉽게도 지금의 API문서 상당 부분이 잘 지키지 않고 있다.