본문 바로가기
ETC/독후감

읽은 책 소감 - 객체지향 시스템 디자인 원칙 (마우리시오 아니체 저)

by Nahwasa 2025. 7. 13.

  ‘이펙티브 소프트웨어 테스팅’의 저자 ‘마우리시오 아니체’의 신간 ‘객체지향 시스템 디자인 원칙’ (2025-06-25 출판)을 읽어봤다.

좌 : 객체지향 시스템 디자인 원칙 / 우 : 이전작 이펙티브 소프트웨어 테스팅

 

  책을 한 문장으로 정리해보자면 다음과 같다.

“결합도를 낮추고 추상화하는 법 알려줄께!”

 

  영어 원제는 ‘Simple Object Oriented Design’ 인데, 한국어로 번역하면서 ‘객체지향 시스템 디자인 원칙’이라는 다소 거창한 제목이 붙었다. 개인적으로 원제가 더 이 책의 성격을 잘 드러낸다고 느꼈다.

 

  기본적으로 클린 아키텍처, DDD에 대한 지식이 있어야 수월하게 읽을 수 있는 책이다. 애그리거트 루트 등의 관련 용어가 별다른 설명 없이 자주 나온다. 또한 좀 더 공통화해서 설명하느라 배경지식이 없으면 뭘 말하는지 알기 힘들 수 있어 보인다. 즉, 클린 아키텍처나 DDD 이런 것에 대해 설명해주는 책이 아니라 그걸 활용하고 고민하는 사람을 위한 책이다.

 

  전반적으로 핵심 주제인 결합도, 추상화, 모듈화 등의 내용이 꽤 깊이 있는 편이다. 책이 얇은만큼 다양한 케이스를 다루진 않는다.  다만 여기서 ‘깊이’는 다소 어려울 수 있다는 얘기이다ㅋㅋ. 완전 신입이라면 읽다가 꽤 막힐 수 있다. 우선 읽은 후 1~2년정도 뒤에 실무에서 설계의 고통을 좀 겪고 다시 보면 새로운게 보여서 더 좋은 책이 될 것 같다. 그럼에도 신입에게도 추천할만 하다. 비록 처음부터 완전히 이해하긴 힘들 수 있지만, 현재 자신이 이 책을 어느정도 이해할 수 있냐를 기준으로 이후 공부 방향을 설정하면 좋아보인다.

 

  아쉬웠던점은 이것도 좋고, 저것도 좋다 방식의 서술이 많았다. 물론 다 맞는 말이고 정론이다. 설계는 트레이드오프의 예술이므로 그때그때 다른 것도 맞다. 오히려 이런 방식을 선호하는 사람들도 많을 것 같다. 반면 4장 등에서 저자는 A도 좋고 B도 좋지만, 본인은 B를 더 선호한다 식의 표현도 몇 번 사용했다. 결국 이런 류의 책은 비슷한 종류의 책들이 많다. 다양한 책을 읽는 이유는 결국 서로 다른 저자의 생각의 차이점을 보고싶은거기 때문이다. 따라서 난 좀 더 편향적이고 명확한 입장을 가진 책을 좋아한다. 좀 더 많은 부분에서 저자의 선호를 드러내줬으면 더 좋았을것 같다.

 

  또 내용의 깊이에 비해, 코드 예시는 좀 얇아서 아쉬웠다. 대부분의 코드에서 이런 부분도 추가해줬으면 더 좋았을텐데 생각하면서 봤다.

 

  몇몇 나와 의견이 다른 부분은 있지만, 대부분의 내용에 대해 동의하고 객체지향 설계에 대해 편향 없이 잘 설명한 책이라고 생각한다. 그냥 개발자라면 한번쯤 읽어볼만한 책인 것 같다. 여담으로, 헥사고날 아키텍처를 ‘육각형 아키텍처’로 번역한건 뭔가 재밌었다.

 


 

  이 책을 읽으며 LLM에게 각 장의 핵심 주제에 기반한 질문을 생성하게 하고, 내가 답변한 후 LLM이 평가하는 방식으로 사고를 확장해봤었다. 이 내용은 별도 글로 정리할 예정이다. 예시로 하나만 올려보면 다음과 같다. 대략 30개정도 질문에 대해 내 생각을 적고 LLM과 토론했다.

 

해당 내용은 ['객체지향 시스템 디자인 원칙'을 읽으며 정리한 내 생각 - LLM과의 Q&A 기반 사고 확장] 글에 있다.

 

이하 ‘5장 - 추상화 잘 디자인하기’ 관련 LLM의 질문 및 내 초기 답변이다. 이런식의 질문, 답변을 모아둔 글이다.

 

✅ Q1. 현재 사용하는 소프트웨어 시스템에서 잘 디자인된 확장 지점을 얼마나 자주 접하는가?

배경:

책 5장에서는 추상화와 확장 지점을 설계 시점에 의도적으로 고려해야 한다고 강조했지.

하지만 실무에선 보통 다음 중 하나야:

  • 처음부터 확장을 고려하고 구조를 설계한 경우 (적절한 전략/템플릿 메서드/이벤트 기반 설계 등)
  • 처음엔 단순하게 시작했지만, 나중에 리팩터링하며 추상화 지점을 잡은 경우
  • 아예 추상화 없이 구현되다가 조건 분기만 늘어나며 망가진 경우

너는 객체지향 설계에 신경을 많이 쓰는 편이고, OCP 기반 구조를 중시하는 만큼

네가 직접 만든 구조에는 어느 정도 의도적인 확장 지점이 있을 가능성이 높다고 생각해.

질문:

너가 설계한 시스템 중에서,

(예: 다양한 조건의 배지 발급, 전입 예약 타입 분기, 알림 방식에 따른 로직 분리 등)

초기에 추상화를 염두에 두고 설계해서 이후 유지보수가 쉬웠던 구조가 있어?

반대로, 다른 사람이 짠 코드에서 “확장 지점이 잘 만들어져 있다”고 느낀 경험은?

무엇이 그렇게 느끼게 만들었는지도 궁금해.

 

내 답변:

  최근 했던 프로젝트에서 외부 API를 많이 호출해야 했거든. 하위 이용기관 N개 및 결제 관련, 인증관련, OAuth 관련, 오픈API 등등 많은 외부 API가 필요했어. 이 때 필요한 스펙도 다르고 호출 방식도 조금씩 달랐어.

 

  예를들어 하위 이용기관은 주로 DB 프로시져를 호출하게 되는데, 그 중간에 별도의 에이전트를 두고 프로시져에서 데이터를 받아오는 방식이야. 이 때 프로시져는 CURSOR의 리턴으로 칼럼명에 대소문자를 구분하지 못해. 근데 난 Map으로 대충 받고 내부에서 쓰는 용어로 바꾸긴 싫고, record 형태로 받고 싶었어. 그래서 하위 이용기관 호출하는 부분은 별도의 HTTP 라이브러리를 사용했어. DTO에 값을 매칭시켜주는 부분을 갈아끼울 수 있는 구조로 된걸 쓰려고 한거지.

 

  추가로, 외부 API 호출부는 호출방식에 따라 여러가지 방식이 존재하지만, 그 구현은 널리 퍼트리고 싶지 않았어. 즉, 최대한 한 객체에서 호출에 대한 실제 구현을 책임지게 하고 싶었어. 근데 그렇다고해서 클라이언트가 본인이 쓸 외부 API 호출 방식 외의 것을 알고싶게 하진 않았어. 예를들어 결제 처리를 호출하는 클라이언트가, 인증과 관련된 인터페이스를 알게하고 싶지 않았어. 인터페이스더라도 필요없는걸 알게된다면 그건 캡슐화가 실패한거라 생각해.

 

  그리고 위에서 말한 우리 프로젝트와 이용기관 DB 또는 SAP 사이의 ‘별도 에이전트’ 또한 추상화 대상이었어. 이건 하위 이용기관 DB를 선호할지, SAP을 선호할지, 아니면 HTTP를 선호할지와 관계없이, 우리쪽의 메인 서비스 서버에 영향을 끼치지 않게하는게 주 목적이었어. 따라서 이번엔 한 프로젝트 내의 추상화가 아니라, 멀티 모듈 사이의 추상화가 필요하지. 메인 서비스는 동일한 방식으로 에이전트를 호출하지만, 에이전트는 하위 이용기관이 선택한 방식으로 알아서 DB를 호출하거나, SAP을 호출하거나, HTTP로 호출해줘야 해.

 

  또, 에이전트는 별도 웹페이지에서 동작을 설정할 수 있게 했어. 왜냐면 메인 서버에 API가 추가되거나 수정됬다고 모든 이용기관의 에이전트를 재배포하고싶진 않았거든. 이렇게되면 MyBatis나 JPA는 사실상 쓰기 힘들어져. JDBC 혹은 JCO를 사용해 RAW하게 짜야하지. 그래서 오히려 재밌었어. 마음껏 디자인패턴 넣으면서 POJO하게 짜기 더 쉽거든 ㅋㅋ. 뭐 과하게 넣진 않았고, 자세히 말하긴 뭐하지만 간단히 말해보면 다음과 같아. 호출에 대한 부분은 FACADE 형태로 하나로 빼고, FACADE가 Startegy + Adapter 패턴 느낌으로 다형성으로 호출 모듈을 갈아끼우도록 했어. 서로 다른 방식이더라도 하나의 interface를 상속해서 구현한거지.

 

  그리고 또 DB라 하더라도 여러 DB를 지원해줘야 해. 이 때, DB마다 프로시져의 스팩이 다른 부분이 있어. 예를들어 오라클 DB는 CURSOR를 OUT 파라미터로 여러개 리턴하는게 가능해. 반면에 MySQL은 CURSOR는 OUT 파라미터로 뺄 수 없고, 프로시져 자체의 리턴으로 최대 1개만 리턴하는게 가능해. 근데 이거 외엔 호출방식이 거의 비슷하거든. 그래서 서로 약간씩 차이가 나는 부분만 template method 패턴으로 각 DB 모듈이 abstract를 구현하게 했어.

 

  전체적으로 보면 최근 프로젝트에서 외부 API 호출에 대해 내가 설계한 추상화 지점은

1.외부 API 호출 라이브러리 추상화

2.외부 호출 API의 종류에 따른 추상화 (구현체는 응집도 있게, 클라이언트는 자기가 관련있는 인터페이스만 알게)

3.DTO 매핑 로직에 대한 추상화

4.DB, SAP, HTTP 에 대한 추상화

5.DB 종류에 따라 서로 달라지는 부분에 대한 추상화

이렇게 되겠네.

 

  실제로 외부 API 호출부분이 계속 추가됬지만, 그냥 interface 하나 추가해서 끝날 수 있었고. 저 에이전트도 이후 다른팀으로 운영이 이관된 후 업그레이드가 되었는데 그 경우에도 큰 문제가 없었다고 알고 있어. 뭐 일단 프로젝트 오픈하고 몇십만 이상의 회원이 사용중인데, 아직 오픈이후로 백엔드 한번도 비정상 동작 없었음.

 

  다른 사람이 짠 코드에 대해서는 말할게 많지 않긴해. 애초에 내가 운영업무를 거의 한적이 없거든. 했더라도 내가 만든거 운영팀에 이관되기 전까지 정도만 해봤어. 그래서 실제 업무 중 그런걸 느낀 경험은 잘 없어. 주로 느낀건, 궁금한게 있어서 스프링 자체를 까본 경우라던지, 강의를 볼 대 이럴 때 인것같아. 개인적으로 가장 기억에 남는건 대학교때 리눅스 커널 분석해봤을 때 크게 느꼈어. C언어지만 객체지향 스타일로 짜여져 있는 코드야. C 자체도 raw하다고 하지만, 커널은 더하거든. 파일 시스템을 갈아끼우는 지점을 유연하게 처리한다거나 그런 부분에서 사실 처음 확장지점에 대한 맛을 봤던 것 같아.

댓글