• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

안녕하십니까? 도메인 설계시 인터페이스, 추상클래스 에 대한 의견을 듣고 싶습니다.

20.09.13 01:20 작성 조회수 1.32k

15

안녕하십니까? 강의 영상 모두 결제해서 잘 보고 있습니다.

바로 본론부터 말씀 드리면,  회사에서 여러개의 프로젝트를 준비하고 있고 그중 자주 쓰이는 공통적인 기능을 ( 회원, 게시판 등 )  만들어 놓고 프로젝트마다 재활용하여 시간을 단축하자는 의견이 나왔습니다. 그래서 JPA 에서 사용하는 entity 도 인터페이스와 추상클래스를 사용해서 설계를 해보라고 해서 진행중에 있습니다.

들어가기 앞서, 스프링 프로젝트의 코드를 살펴보면 인터페이스를 잘 사용해서 설계를 잘 했다고 생각하고 있습니다.그러나 데이터베이스와 직접적인 연관이 없는 코드라서 자유롭게 쓸수 있었던것 같은데요. JPA 를 쓰고 있는 입장에서 인터페이스와 추상클래스를 사용해서 다형성을 구현할려고 할때마다 한계에 자꾸 봉착하는 느낌이 듭니다. 결국 도메인 클래스는 CRUD 가 중요한데, 인터페이스로는 실제 구현된 클래스가 뭔지 알수 없어 사용하기가 난감합니다.

Item 과 Book 과 같이 강하게 결합 하는것에 대해서는 어느정도 수긍이 갑니다만, 거의 대부분은 그렇게 강하게 연결되는 경우가 잘 없는거 같아서요. 인터페이스를 쓰는경우도 잘 못본거 같습니다. 실무에서는 인터페이스와 추상클래스를 어느 정도 까지 사용하는지궁금합니다.

답변 3

·

답변을 작성해보세요.

24

안녕하세요. 구본수님

추가로 고민하시는데 도움이 될까 해서 글을 하나 남겨드려요^^

객체 지향 설계에서 사실 가장 중요한게 바로 인터페이스 입니다. 그런데 이 인터페이스가 왜 중요한가 그 이유를 알아야 합니다. 바로 인터페이스를 변경하지 않고 그 구현체를 바꿀 수 있는게 객체지향 설계의 가장 큰 강점입니다.

그런데 반대로 이야기하면 이 인터페이스가 흔들리면 어떻게 될까요? 인터페이스를 구현하는 객체들도, 또 인터페이스를 호출하는 클라이언트 객체도 모두 인터페이스에 의존하게 됩니다. 따라서 인터페이스에 조그마한 변경이라도 발생되면, 인터페이스를 구현해야 하는 모든 구현 클래스도 다 변경해야 하고, 추가로 인터페이스를 호출하는 코드도 모두 변경해야 합니다.

인터페이스를 안정적으로 가져갈 수 있다면, 그러니까 모두가 인터페이스에 맞추어 요구사항이 나오고 개발을 할 수 있다면 말씀하신데로 확장성있는 설계도 가능합니다. 예를 들어서 스프링 시큐리티나 기술 프레임워크 들을 보면 해당 인터페이스에 맞추어 다른 개발을 할 수 있습니다. 그런데 중요한게 있습니다. 모두 인터페이스에 맞추어서 개발을 했다는 것입니다.

그런데 도메인 업무는 다릅니다. 회원, 상점, 상품, 주문 같은 경우를 떠올려보면 쇼핑몰 회사마다 다 비슷하다고 생각하지만, 사실은 완전히 다른 도메인입니다. 사실 처음 가정부터가 잘못된 것이지요. 회원도 모든 회사가 같은 회원이라는 표준을 가지고 있는게 아닙니다. 비슷한 모양일뿐 완전히 다른 기능을 합니다. 주문 같은 경우도 단순히 주문이라는 인터페이스만 있으면 될 것 같지만, 회사가 100개 있으면 100개 모두 주문의 인터페이스가 다 다릅니다.

예를 들어서 제가 다니는 회사 같은 경우도 주문을 한번 호출하면 단순히 주문 인터페이스 하나로 끝나지 않습니다. 주문의 모든 라이프사이클을 마치려면 수 많은 인터페이스를 호출해야 하고, 외부 시스템 호출만 수십번 이상 필요합니다. 그만큼 엄청나게 복잡합니다.

결국 고민하시는 방법이 어려운 이유는 회사마다 요구하는 요구사항이 완전히 다르고, 그래서 인터페이스 안정화가 매우 어렵기 때문입니다. 제 경험을 간단히 말씀드리면, 어떤 쇼핑몰은 테이블이 10개 정도로 정리되지만, 어떤 쇼핑몰은 테이블이 1000개 입니다. 인터페이스는 완전히 다릅니다. 따라서 이런 경우는 추상화 보다는 구체화로 들어가야 합니다. 그리고 해당 도메인 로직 안에서 인터페이스로 안정화 하면 좋은 부분이 있으면 인터페이스를 도입해야 합니다. 예를 들어서 회사의 할인 정책이 있는데, 이 부분을 확장성 있게 인터페이스와 구현으로 나누는 것 등이지요.

핵심은 안정적인 인터페이스 설계가 가능한 부분은 인터페이스로 다형성과, 구현체를 바꿀 수 있는 이점을 얻을 수 있지만, 안정적인 인터페이스 설계가 불가능한 부분은 해당 도메인에 맞게 구체적으로 개발하는 것이 더 좋다 생각합니다.

감사합니다^^

22

안녕하세요. 구본수님 좋은 질문입니다.

결론부터 이야기하면 추상화를 이용한 객체 지향 설계가 잘 맞는 곳이 있고, 데이터 중심의 자료구조를 사용하는 곳이 더 잘 맞는 곳이 있습니다.

- 먼저 JPA의 엔티티는 인터페이스 자체를 지원하지 않습니다. 순수 자바 코드로 인터페이스를 만들고 구현하는 것은 가능하지만, JPA를 통해서 해당 인터페이스를 읽거나 하는 것은 불가능합니다.

- JPA가 제공하는 Item과 Book과 같은 상속 관계도 일반적인 경우에 제공되는 것이 아니라, 관계형 데이터베이스의 슈퍼타입 서비스타입으로 설계된 경우에 한해서 객체 상속관계를 사용할 수 있습니다.

- 정리해보면 JPA의 엔티티는 태생적으로 관계형 데이터베이스의 테이블과 매핑하기 위해 존재합니다. 따라서 완전히 순수한 객체 지향 개발을 하기는 어렵습니다. 어느정도는 객체지향 개발이 가능하지만, 테이블 자체가 데이터 중심의 설계이기 때문에 엔티티는 객체와 데이터 중심 설계 둘 사이에 놓이게 됩니다.

- 개발은 크게 인터페이스와 메시지 중심의 객체지향 설계 방법과, 데이터 중심의 설계 방법이 있습니다. 어떤 경우는 객체지향 설계 방법이 잘 맞지만, 어떤 경우는 데이터 중심의 설계 방법이 더 잘 맞습니다. 그리고 하나의 프로젝트 안에서도 둘이 공존합니다. 어떤 것이 더 우월하다기 보다는 상황에 따라 더 잘 맞는 것이 있습니다. 이 부분은 클린코드 책 6. 객체와 자료 구조에서 잘 설명합니다.

- 앞서 고민하신 스프링 관련 부분은 객체지향 설계 방법이 잘 맞을꺼에요. 그런데 엔티티는 비즈니스 데이터를 기반으로 설계되기 때문에 인터페이스와 메시지 중심의 객체지향 설계 방법만으로 개발하기는 쉽지 않습니다. 당장 사방에서 필요한 비즈니스 데이터들을 달라고 할 테니까요. 그런데 이 필요한 비즈니스 데이터가 프로젝트 마다 조금씩 다를 것인데, 그러면 결국 인터페이스 자체가 달라질 수 밖에 없습니다. 인터페이스로 설계하는 것 자체가 인터페이스는 잘 변하지 않아야 한다가 전제인데, 프로젝트 마다 데이터가 다를 것이고, 그러면 인터페이스 자체가 달라지니 결과적으로 잘 맞지 않습니다. 물론 이 부분도 조회용 공통 인터페이스를 정말 잘 설계하고, 중간에 변환 계층을 두면 어떻게 할 수는 있는데, 배보다 배꼽이 더 클 것이라 생각합니다.

- 엔티티는 엔티티 자체가 특정 비스니스 요구사항에 맞추어 개발된 데이터들을 포함하고 있습니다. 따라서 비즈니스가 조금만 달라져도 재사용이 어렵습니다.

도움이 되셨길 바래요^^

5

구본수님의 프로필

구본수

질문자

2020.09.19

깊은 답변 정말 감사합니다. 이해가 되었습니다.