스프링 공부를 했는데, VO, DTO, Entity, DAO, Repository 개념을 이해하고 정리해야할 필요가 있을 것 같다. 일단 내가 이해한 토대로 작성했기 때문에, 틀린 부분이 있을지도 모른다! (틀린 부분이 있으면 댓글로 알려주시면 감사하겠습니다.)
일단 DB가 있다. DB에는 데이터가 담긴다. 그러면 그 데이터를 스프링 내에서 사용하기 위한 객체가 필요할 것이다. 여기에서 VO, DTO, Entity를 비교해볼 수 있다.
순수하게 값 자체를 의미하는 것이 VO(Value Object)다. VO는 값을 저장하기만 하여, immutable하다. 객체들의 주소가 달라도 값이 같으면 동일하게 여긴다. setter 메소드는 가지지 않고, getter과 그 외 비즈니스 로직도 구현할 수 있다. equals, hashCode 메소드를 오버라이딩 해줘야된다.
데이터를 계층들끼리 주고받아야 할 것이다. 그게 DTO(Data Transfer Object)다. getter/setter 메소드를 포함하고 그 외는 포함하지 않는다. 즉, 비즈니스 로직을 포함하지 않는다. setter을 사용하면 가변 메소드, setter 없이 생성자를 이용해 초기화하는 경우에는 불변 메소드로 사용할 수 있다. -> view와 DB 계층의 철저한 분리를 위해 DTO를 사용한다.
Entity의 경우에는 실제 DB 테이블과 매핑되는 핵심 클래스다. 테이블 내에 존재하는 컬럼만 속성으로 가져야 한다. 테이블 생성, 스키마 변경에 기준이 된다. id로 구분되고, 비즈니스 로직을 포함할 수 있다. controller의 request/response 클래스로 절대 사용해서는 안된다. (Domain으로 패키지를 생성하기도 하는듯) (참고. Entity의 경우 JPA의 Entity와 DDD의 Entity 개념이 혼용돼서 쓰이기도 하는 것 같은데 정확한 차이는 잘 모르겠다... 참조할만한 글)
VO, DTO, Entity 를 통해서 DB를 스프링에서 사용할 수 있게 됐다. 하지만 이걸로는 데이터를 사용할 수 있게 된 거고, 상위계층에서 뭘 하다보면 DB에 접근을 할 필요가 있을 것이다. 쿼리도 날리고 해야되지 않겠나. 음. 그런데 계층끼리 데이터를 주고받는 건 DTO가 하니까, 상위계층에서 DB에 접근하는 것도 DTO가 하는 일 아닌가? 얼핏 그렇게 생각할 수도 있겠지만. 아니다. DTO는 데이터 교환용 이다. getter/setter 메소드만 있다고 하지 않았나? 그러니까, 상위계층에서 DB에 CRUD 기능 구현하는 등등을 하려고 접근하기 위해서는 DB와 상위 계층 사이에, DB에 실제로 접근하고 결과를 상위 계층에 넘겨주는 뭔가 하나의 계층이 더 필요할 거다. (바로 접근하면 결합성이 너무 높아지고 레이어, 즉 웹 어플리케이션의 아키텍처가 깨지기 때문에 안된다.) 그 계층이 바로 DAO다. 오라클에 올라와있는 시퀀스 다이어그램인데, 이걸 보면 감이 잡힐지도 모르겠다. Transfer Object가 DTO다.
어쨌든, 그러면 DAO가 뭔 일을 하는지는 어느정도 알겠다. 그런데 인터넷을 보다보면 Repository라는 개념이 보인다. DAO와 혼용되기도 한다. 이 둘의 차이는 뭘까? 일단 둘 다 하는 역할은 비슷해 보인다. DAL(Data Access Layer)의 구현이라고 한다. 사실 이 부분을 잘 모르겠어서 글을 많이 읽어봤는데, 아직도 정확하게는 이해를 못했다. 하지만 이해한 바로는 다음과 같다.
음. 뭔가 이상하다. DAO는 Infrastructure layer, Repository는 Domain layer라니? 하는 일은 다를 게 없어 보이는데. Repository는 일종의 컬렉션이다. -> Repository의 interface는 Domain layer에 있으나, 구현은 Infrastructure layer에 있다. 영구 저장소의 API를 이용하여 구현하는 것이다. 이렇게 되면서 domain, infrastructure의 의존성이 뒤집히게 되고(DIP) -> infrastructure에서 domain 레이어를 알아도 상관없으며, entity를 영속성 로직에 포함시킬 수 있는 것. 의존성이 역전되어있기 때문에 entity를 가져와서 영속성 로직을 수행할 수 있는 것이다. (그러면 DAO는 Entity를 바로 컨트롤하면 안 되나? 그렇다고 한다... DTO를 이용해야만 한다...)
포스팅1과 포스팅2, 포스팅3를 참조하였는데, 쭉 읽어보면 도움이 될 듯하다. (포스팅 4도 있는데, 이 글은 어려워서 아직 잘 이해하지 못했다.) DAO를 이용해 Repository를 구현할 수 있다고 하는데, 이 부분은 사실 잘 모르겠다. 아무튼 하는 역할은 비슷하지만 개념에 있어 차이가 있다(DAO는 데이터와 가깝고, Repository는 도메인 개체에 가깝다)고 생각하면 될 것 같다.
그러면 이제 VO, DTO, Entity, DAO, Repository 개념들은 이해했다. 마지막으로 스프링 계층구조가 남았다. 스프링을 Web(Controller) - Service - Repository(DAO) 구조로 볼때, 다음과 같이 개념을 구분할 수 있다.
개념은 쉽다. 특히 MVC 패턴을 안다면 더 쉽게 이해할 것이다. 그런데 여기서 의문이 생길 수 있다. DAO를 통해 DB에 접근할 수 있는데, Controller에서 DAO에 바로 접근하면 안되나? Service가 굳이 필요한가?