2 분 소요

서론

우아한 테크코스에서 활동하시고 BDD 소모임 임원진인 아마란스님께서 조영호 님이 발표하신 “우아한객체지향”이라는 영상을 공유해 주셨습니다. 이 영상 보고 객체지향 설계를 바라보는 새로운 눈을 얻었습니다. 또 배울 게 없을까 싶어서 찾아본 결과 “애플리케이션 아키텍처와 객체지향”이라는 영상을 찾았습니다.

이 영상에서는 영화 예매 시스템을 예시로 절차지향 코드와 객체지향 코드, Service 레이어에 관해서 자세히 설명해 주십니다. 제 첫 프로젝트인 KEEPER R2 프로젝트에서 간단한 CRUD는 JPA의 더티체킹을 사용하기 때문에 반강제적으로 도메인에 로직을 넣어 객체지향적으로 코드를 작성했습니다. 하지만 조금만 복잡한 기능인 경우에는 어플리케이션 로직을 Service 레이어에 몰아넣었습니다. 또, 우테코 프리코스를 진행하면서 순수 자바 언어로 어플리케이션을 만들기 때문에 JPA의 더티체킹 기능이 없어 모든 로직을 Service 레이어에 몰아넣었습니다.

아래에서는 평소 제가 작성하던 절차지향적 코드에 대해서 알아보고 어떻게 객체지향 코드로 변경시킬 수 있는지에 대해서 알아보겠습니다. 또, Service 레이어의 역할과 이상적인 Service 레이어의 코드에 대해서 알아보겠습니다.

객체 지향 언어를 사용했지만 절차 지향적으로 코드를 짠다.

조영호 님께서는 절차적인 코드는 “데이터와 프로세스가 따로 논다”고 말씀하셨습니다. 이 말을 이해하기 위해서는 어떤 요구사항을 처리하기 위해서 평소 제가 어떤 과정으로 코드를 작성하는지 보여드리면 이해하기 쉬울 것입니다.

영화 예매 시스템에서 예매 기능을 구현해달라고 요구 사항이 들어왔을 때 저는 아래와 같은 과정을 거쳤습니다.

  1. Database ERD을 그리고 Entity로 DB와 매핑합니다.
  2. Dao와 Service 레이어를 만듭니다.
  3. Service 레이어에서 기능을 구현할 때 어떤 데이터가 필요한지 생각하고 Dao를 통해서 일단 가져옵니다.
  4. 이 데이터를 가지고 어떤 알고리즘을 거치야 하는지 고민하고 구현합니다.
  5. 최종적으로 완성한 예매 인스턴스를 생성 후 데이터베이스에 저장합니다.

위의 과정은 아래의 사진을 보시면 더욱 쉽게 이해할 수 있습니다.

절차지향이미지

절차지향이미지

절차지향이미지

절차지향이미지

데이터와 프로세스가 따로 논다는 느낌을 아시겠나요? 일단 기능 구현에 필요한 데이터를 준비하고 알고리즘(process)을 거친 후 데이터베이스에 저장하는 과정을 거치는 것을 확인할 수 있습니다.

이런 스타일은 Service에서 모든 컨트롤을 하기 때문에 중앙 집중식 제어 스타일이라고 합니다.

절차지향이미지

객체 지향 언어로 객체지향 코드를 짜보자.

반대로 객체지향인 코드는 “데이터와 프로세스가 같이 논다”고 말씀하셨습니다. 객체들이 메시지를 주고받으면서 협력해야 하는데, CRC Card를 사용하면 객체들의 책임과 역할을 정의할 수 있고, 협력 관계를 한눈에 쉽게 파악할 수 있습니다.

CRCCard

CRC Card를 사용해서 책임을 할당할 때는 이 책임을 수행하는 데 필요한 데이터를 가장 밀접하게 사용하는 객체에 할당해야 합니다.

이렇게 CRC Card를 사용해서 도메인 모델을 잘 설계했을 때, 우리는 과연 도메인 모델만 가지고 어플리케이션을 짤 수 있을까요? 객체들이 메시지를 전달하면서 협력하기 위해서는 기본적인 데이터를 데이터베이스에서 읽어서 객체에게 밀어 넣는 과정이 꼭 필요합니다. 이 과정을 진행하기 위해 필요한 것이 Service 레이어입니다. Service 레이어에서는 데이터베이스에서 데이터를 읽는 작업과 어플리케이션 로직이 끝나고 생성된 객체를 데이터베이스에 저장하는 작업을 합니다.

ServiceLayer

위의 코드는 가장 이상적인 Service Layer입니다. 데이터베이스에 데이터를 읽고 도메인 객체에게 위임하고 그 결과를 데이터베이스에 저장하는 과정을 거칩니다. 도메인 로직을 처리하기 위한 사전준비와 예외 처리를 하는 것이 가장 적절한 모습입니다.

순수한 도메인에 어플리케이션 로직을 넣지 않는 이유는 넣는 순간 디펜던시가 생기고 결합도가 높아지면서 응집도가 떨어지기 때문입니다. 따라서 객체지향 설계를 한다면 Service 레이어를 도입은 필수이고 도입함으로써 트랜잭션의 범위를 잡고 도메인 로직의 재사용을 촉진할 수 있습니다. (예를 들어 어드민 툴을 만들 때 서비스 플로우는 다르지만, 하위에 있는 도메인 로직은 재사용이 가능합니다)

마치며

절차지향 코드가 무엇인지 예시 코드를 통해서 알아봤습니다. 절차지향 코드를 객체지향 코드로 진화시키기 위해서 CRC Card 사용법에 대해서 알아봤고 CRC Card를 통해서 객체의 협력, 책임, 역할을 쉽게 설계할 수 있었습니다. 그리고 객체지향 코드로 설계할 때 데이터를 조회하고 밀어넣는 과정이 필요하기 때문에 Service 계층이 있어야 하고 가장 이상적인 코드도 살펴봤습니다.

다음은 조영호님께서 강의해주신 영상을 바탕으로 2주차 프리코스 - 자동차 경주 게임을 설계해보고 리팩토링 해보도록 하겠습니다.

(모든 PPT 사진과 글의 바탕은 “객체지향의 사실과 오해” 책을 지으신 조영호님의 강의에서 참고했습니다)

참고

https://www.slideshare.net/baejjae93/ss-55571345

https://www.youtube.com/watch?v=26S4VFUWlJM