무늬만 계층형 아키텍처
“DAO 단에서 화면에 필요한 데이터를 미리 다 준비해서 가져온다.”
Dao, Service, Controller가 별개의 클래스로 구성되어 있고 또 인터페이스까지 만들어 놨다고 해서 계층형 아키텍처를 지키고 있는 아니다.
나도 잘 몰랐거나 오해했던 내용을 사부님과 이야기 나누며 다시 개념을 정리하고 있다. 이야기의 시작은 OSIV 패턴을 사용하는게 게층형 아키텍처를 위반한 것이냐 아니냐 였다. 나는 위반했다는 입장이었고, 사부님은 아니라는 것이었다. 결론부터 말하자면 내가 틀렸다.
우선 나의 생각은 이랬다. 어떤 블로거의 글처럼, 뷰 단에서 DB 쿼리가 발생할 수 있으니 DAO 계층에서 할 일을 뷰 단에서 한 것이나 마찬가지이고, 그래서 계층형 아키텍처가 깨졌다고 주장했다.
하지만 사부님은 간단하게 반론을 제기했다. 그렇다면 Transparent Persistence(TP) 기술 자체가 계층형 아키텍처를 위반한 것이라는 건데, 예를 들어 서비스 계층에서 Lazy loading하는 것도 그럼 계층형 아키텍처 위반이냐?
오히려 내 생각에 반전을 일으키는 말씀을 하셨다. TP 때문에 오히려 계층형 아키텍처가 굳건해 진다는 것이다. TP가 없었다면 오히려 도메인 객체만 전달하는게 아니라, 서비스나 컨트롤러 혹은 뷰 단에서 필요한 데이터를 전달하게 되는 것이고, 그렇게 되면 계층 간에 필요한 데이터가 무엇인지 분명히 알고 있어야 하기 때문에 그로인한 결합도가 생긴다는 것이다. 맞는 말이다. 계층 간에 주고받는 데이터가 구체적일 수록 변경에 민감하게 반응하게 될 것이다. 결국 겉으로만 분리되어 있고 실제로는 데이터를 중심으로 강하게 결합된 구조가 된다. 화면에서 보여줄 데이터가 바뀌면 결국 컨트롤러, 서비스, DAO 전부 바뀌게 되는 것이다. 그런데 JPA를 사용하면 얼마든지 TP가 가능하기 때문에 도메인 객체만을 주고 받게 되고, 그렇게 되면 데이터 중심의 개발 방법에 비해서 변경될 여지가 적다. 결국 유지보수성이 뛰어나다.
결국 TP는 계층형 아키텍처의 취지에 완벽하게 부합하는 것이다. 그리고 OSIV는 TP를 뷰 랜더링 시점까지로 연장시켜줄 뿐, 어차피 거의 기본적으로 서비스 계층의 오퍼레이션 마다 TP가 적용되고 있다. 그리고 애초에 뷰단에서 쿼리가 날아갔을 때 뷰단에서 JDBC Connection 객체를 가지고 코딩한 것도 아니고 그저 도메인 객체 그래프를 가지고 네비게이션 했을 뿐 아닌가? 코드 레벨에서 전혀 계층형 아키텍처를 위반하지도 않았다.
이야기는 계속 이어져서, 데이터 중심 개발 방법과 도메인 중심 개발 방법의 차이점과 특징에까지 이르렀다. 그리고 도메인 중심 개발 방법에서도 도메인 계층을 벗어날 때 DTO를 사용하자는 집단과 그러지 말고 그냥 도메인 객체 그대로 쓰자는 집단의 주장과 흐름까지도 이야기를 들었다.
“화면에서 어떤 데이터를 보여줄지 DAO가 다 알고 그에 맞게 SQL을 미리 다 짠다면 이미 DAO가 뷰 단과 강한 결합이 생겼다는 증거다. 이런건 계층형 아키텍처가 아니다.”
데이터 중심 개발을 하면 위에서 예를 든 것처럼 계층간의 결합도가 높아서 변경될 여지가 많다. 하지만 모든 계층에서 도메인 객체를 사용한다면 이야기는 달라진다. 모든 데이터는 이미 도메인 객체에 들어가서 메모리에 들어가 있다는 가정하에 도메인 객체를 네비게이션 하면서 비즈니스 로직을 처리하고 뷰에서 랜더링을 하는 것이다. 따라서 필요한 데이터가 도메인 객체 네비게이션으로 참조할 수 있는 한도 내에서는 전혀 코드를 변경할 필요가 없다.
“DAO, Service, Controller, 뷰를 전부 도메인 모델만 공유한 상태에서 각자 다른 팀에서 개발한다고 가정하고 코딩을 하면 도메인 중심 개발 방법에 가장 잘 맞는 형태의 코드가 나올 것이다.”
결국 OSIV로 얻을 수 있는 장점은 다음과 같다.
1. 개발 속도 향상
2. 이상적인 계층 구조 확보
3. 적절한 엔티티 캐시 활용
그러나 전제가 더 중요하다. “도메인 중심 개발 방법”을 적용했을 때에야 이런게 의미가 있지, 앞서 말한것처럼 “데이터 중심 개발 방법”을 사용하면서 하이버네이트나 OSIV를 사용하겠다는 것은 권장하지 못할 시도인것 같다. 그래가지고는 오히려 하이버네이트에 대한 악담과 비화만 늘어날 뿐이다.
사부님이 권장하는 하이버네이트 개발 스타일은 다음과 같다.
1. Entity 캐싱을 하고 join fetch 없이 개발
2. 매번 같이 다니는 연관 관계면 아에 매핑을 eager fetching으로 튜닝
3. 가끔씩 같이 다닌다면 런타임시 join fetch
도메인 중심 개발을 할 때 DTO를 쓰자는 입장은 화면단에서 도메인 객체에 setter 호출로 데이터를 조작할 수 있다는 것을 위험하다고 여겨서 함수형 언어에서 주로 사용하는 immutable한 객체를 만들어 넘기도록 DTO를 권장했다. 심지어 OSIV를 사용하는 경우에는 PT에서 도메인 객체를 수정하면 DB에 update 쿼리가 날아가기까지 했었다. 하지만.. 아드리안 콜리어가 등장해서 Aspectj 한줄로 뷰단에서는 setter 호출 불가, DAO 호출 불가 정책을 만들어 적용할 수 있다는 사실을 전파하자. 요즘은 DTO 사용하자는 집단이 조용해짐. 그냥 도메인 객체를 여러곳에서 사용하는 것으로… 고고씽…
위의 내용은 토비의 스프링 9장에 잘 나와있기도 하다. 722페이지부터 읽어보면 될듯하다. 이미 책으로 써주셨는데, 채팅으로 저자 직강을 듣고나니 감회가 새롭다. 문제다. @_@;; 점점 바보가 되가나봐…