책의 구성

처음 책을 구매했을 때 제목만 보고 딱딱한 내용을 생각했지만 재밌는 구성을 가지고 있었다. 사업가인 클라핌과 개발자인 테오가 등장하고 크라핌이 테오에게 통합 도서관 관리 시스템 개발을 요청한다. 테오는 요구사항을 만족하는 시스템을 구축하고 그 과정에서 OOP의 단점을 마주하며 해결해나가는 구성을 가진다. 대화 형식으로 진행되다 보니 딱딱하지 않고 내용에 더 집중이 잘 되는 것 같아 구성이 참 마음에 들었다.
OOP 설계와 UML

테오는 개발에 들어가기에 앞서 시스템의 UML 도식을 구성한다. UML 도식에는 포함, 연관, 상속, 사용 4가지 관계가 존재한다. 예시를 몇가지 적어보자면 Library는 Member를 포함한다. 만약 Library가 사라지면 Member도 모두 사라지게 될 것이다. 반면 Book과 Author는 연관관계이다. Book이 사라져도 Author는 남을 수 있고 반대도 성립한다. Librarian과 Member는 User를 상속하여 코드의 중복을 방지한다. 마지막으로 Librarian은 BookItem을 사용하여 BookItem을 추가할 수 있다. 그리 복잡한 시스템이라 생각하지는 않았지만 책에서는 복잡성을 지적한다. 그리고 이 복잡성은 테오 설계의 문제가 아닌 OOP 패러다임 자체의 문제라 말하며 OOP가 복잡도를 증가시키는 4가지 이유에 대해 설명한다.
- 코드와 데이터가 섞여 있다.
- 객체가 변경 가능하다.
- 데이터가 멤버로 객체에 고정된다.
- 코드는 메서드로 클래스에 고정된다.
OOP가 복잡도를 증가시키는 이유
1. 코드와 데이터가 섞여 있다

이전 UML 도식이 복잡한 이유가 뭘까? 책은 코드와 데이터가 모두 들어있기 때문이라 지적한다. 위 그림처럼 코드와 데이터를 제거하고 보면 조금 더 단순한 구조를 확인할 수 있다. 여기서 조금 더 나아가 관계를 기준으로 도식을 나눠보면 어떨까? 관계는 코드 관계, 데이터 관계 2가지로 나뉠 수 있다.
- 데이터 관계 (포함, 연관)
- Library는 여러 Member를 갖는다.
- Member는 여러 개의 BookLending을 갖는다.
- 코드 관계 (상속, 사용)
- Member는 User를 확장한다.
- Librarian은 Member를 사용한다.
- Member는 BookItem을 사용한다.

관계에 따라 2개의 도식으로 분리하니 각 도식은 이전에 비해 단순해 보인다.
2. 객체의 변경 가능성
// 1번
class Member {
isBlocked;
displayBlockedStatusTwice() {
var isBlocked = this.isBlocked;
console.log(isBlocked);
console.log(isBlocked);
}
}
// 2번
class Member {
isBlocked;
displayBlockedStatusTwice() {
console.log(isBlocked);
console.log(isBlocked);
}
}
1번 코드의 displayBlockedStatusTwice의 첫 console.log에서 true가 나왔다면 2번째 console.log의 결과는 true로 고정되어 있다. 이유는 원시 자료형을 사용했기 때문이다. 반면 2번의 경우 멀티 스레드 환경에서 어떤 결과가 나올지 알 수 없다. 이유는 원시 자료형이 아닌 변할 수 있는 객체의 멤버를 사용했기 때문이다.
책에서는 변경 가능성을 이유로 OOP를 지적한다. 이 문제 제기에 대해서는 앞으로 문제를 어떤 방식으로 해결해 나갈지 궁금하다. 원시 자료형을 활용하여 멀티 스레드 환경에서 발생할 수 있는 동시성 문제를 어떻게 해결한다는 거지..? 앞으로가 기대되는 부분이다.
3. 쉽지 않은 데이터 직렬화
시스템의 검색 부분을 구현한다고 가정하자. JSON 형태의 질의 데이터를 역직렬화하여 객체 형태로 바꿔야 할 것이고 또 검색 결과를 JSON 형태로 직렬화를 해야 한다. 이같은 직렬화/역직렬화 작업은 모든 API Endpoint에서 진행돼야 한다. 이같은 직렬화/역직렬화 과정을 위해 OOP에서는 너무 많은 클래스와 코드를 작성해야 한다고 말한다. 그 이유는 OOP에서는 데이터가 클래스에 정의된 경직된 규격에 따라야 하기 때문이다.
(여기에 해결책이 있는 건가? 책의 앞으로가 또 기대되는 부분이다.)
4. 복잡한 클래스 계층 구조

User / Member / Librarian 3가지 클래스의 계층 구조에 대해 살펴보자. 만약 VIP Member가 추가로 필요하고 VIP Member는 BookItem을 추가할 수 있는 기능을 추가해야 한다고 생각해보자. 이미 이전 구현에서 addBookItem이란 메서드는 Librarian에 이미 정의되어 있다. 하지만 OOP에서 코드는 클래스에 구속된다. 즉, addBookItem 메서드는 Librarian 클래스에 고정되어 있다.
만약 이 상황을 해결하기 위해 User를 상속한 userWithBookItemRight 클래스를 만들고 Librarian과 VIP Member는 userWithBookItemRight를 상속하게 한다면 급한 불은 끌 수 있다. 하지만 비슷한 상황이 몇 번 반복된다면 계층 구조는 파악하기 힘들게 변해있을 것이다. 이같은 문제가 발생하는 이유의 근원에는 코드(메서드)가 클래스에 고정되어 있기 때문이다.
문제의 해결책으로 Composite 패턴을 제시하지만 자세한 내용은 뒷 장에서 나올 것 같다.
'도서 > 기술' 카테고리의 다른 글
[책] 데이터 지향 프로그래밍 - 6장 단위 테스트 (2) | 2024.12.14 |
---|---|
[책] 데이터 지향 프로그래밍 - 5장 기본 동시성 제어 (1) | 2024.12.08 |
[책] 데이터 지향 프로그래밍 - 4장 상태 관리 (0) | 2024.12.01 |
[책] 데이터 지향 프로그래밍 - 3장 기본 데이터 조작 (4) | 2024.11.30 |
[책] 데이터 지향 프로그래밍 - 2장 코드와 데이터 분리 (2) | 2024.11.24 |