티스토리 뷰

Item50에서는 적시에 방어적 복사본을 만들라 한다

defensive copy를 만들어야 하는 이유는 미성숙한 & 악의적인 클라이언트의 잘못된 접근을 막기 위함이다

secure coding의 한 종류로써 사용하는 쪽에서 무슨 짓을 하든 객체의 불변성, 안전성이 위협 받지 않도록 하는 것이다

상식적으로 보면 이런 일이 과연 일어날까 싶지만

대규모 프로젝트의 경우 초기 인원들이 끝까지 남아 소프트웨어 생명주기 전체를 관리하는 일은 흔치 않을 것이다

그렇다면 작성한 사람과 관리하는 사람이 다를 것이고 어떤 의도로 코드를 작성했을지 알 길이 없다

 

책에 등장하는 Date를 인스턴스 변수로 가지는 Period의 예로 보면 Date 자체가 불변을 보장하지 못 하는 클래스라

단순하게 Date에 setXX 메서드를 이용해 손 쉽게 Period의 불변성을 깨트릴 수 있다

자바8 이후로 작성하는 코드에는 Instant, LocalDate, LocalDateTime 등을 사용하면 해결할 수 있지만

다양한 라이브러리에서 Date를 사용하고 있고 하위 호환성을 지켜주기 위해 여전히 지원하고 있기 때문에 문제가 될 수 있다

이와 같은 상황에서 Date를 쓰지만 불변성을 보장해 줄 수 있는 방법이 방어적 복사본이다

 

방어적 복사본을 만들 때 신경 써야 하는 부분은 두 가지다

1. 생성자

2. getter

 

생성 시에는 인스턴스 변수를 매개변수로 들어오는 놈으로 할당해야 하는데

비지니스적으로 옳지 못한 값이 들어올 수 있으니 입력 유효성 검증을 때려줘야 한다

이 때 주의할 점으로 검사 후 할당이 아니라 할당 후 검사를 해줘야 한다는 점이다

오묘한 병렬 프로그래밍에 의해서 검사 시점에는 제대로 된 값으로 통과했지만

검사 - 할당 사이 찰나의 순간에 매개변수 입력 값이 수정될 수 있기 때문이다

이를 TOCTOU (time-of-check / time-of-use) 공격이라고 한다

상식적으로 생각할 때 ns 단위 처리로 끝날 부분까지 신경 써야 하나 싶지만 저런 식으로 될 수도 있다는 것이 문제다

대부분 문제 없지만 만에 하나 잘못된 값으로 생성 시 어떤 데이터가 잘못 된건지 찾기 매우 힘들어지기 때문이다

 

다음은 getter로 인스턴스 변수를 가져올 때 발생할 수 있는데 생성 시 열심히 방어적 복사본으로 유효성 검증도 끝내놨지만

순수한 형태의 getter로 반환해버리면 가변 클래스인 Date를 그냥 반환 해버린다

클라이언트 측에서는 Date를 얻어온 후 setYear 등의 메서드로 원본 값을 바꿔버릴 수 있게 된다

따라서 getter로 반환할 때도 원본 필드를 복사해서 새로운 값으로 반환해줘야 현재 있는 값을 보여주지만

참조 관계는 끊긴 인스턴스를 반환할 수 있다

 

병렬 프로그래밍을 신경 쓰면서 코드를 작성하기란 매우 어려운 것 같다

그냥 불변 클래스 LocalDateTime 쓰자..

댓글
링크
글 보관함
«   2024/12   »
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 31
Total
Today
Yesterday