Controller, Service, DAO
셋을 이해하려면 먼저 MVC패턴이 왜 등장했는지부터 알아봐야 한다.
1. MVC 패턴
기존의 서블릿과 JSP 방식은 하나의 파일에 비지니스 로직(서비스 호출) 과 뷰 렌더링(HTML)이 모두 존재 했다.
즉, 하나의 파일에 자바코드와 HTML 코드가 전부 들어가 있었다. 그러다 보니 코드의 복잡성이 올라가고 결국 유지보수가 어려워 졌다.
이러한 문제를 해결하기 위해 MVC(Model View Controller)패턴이 도입되었다.
View(HTML)와 Controller(비지니스 로직)을 분리하였다.
그래서 view에서 HTTP 요청을 보내면 Controller가 비지니스 로직(회원가입, 상품주문 등)을 수행하였다. 그리고 view 렌더링에 필요한 데이터는 Model에 담았다.
덕분에 뷰는 화면을 렌더링 하는 일에 집중 할 수 되었고 모델에 담겨있는 데이터를 사용해서 화면을 그리는 역할만을 수행하게 되었다.
2. Controller, Service
Controller는 비지니스 로직을 수행한다.
회원가입페이지에서 가입 버튼을 누르면 내 아이디와 비밀번호가 DB저장된다.
로그인을 할때도 DB에 내 아이디를 조회하여 내 아이디가 있으면 로그인에 성공하고 없으면 로그인에 실패한다.
즉 Controller는 현재 두가지 일을 하는 것이다.
- HTTP요청을 받아서, 뷰에 전달할 데이터를 모델에 담아 렌더링 한다.
- 비지니스 로직을 수행한다.
물론 두가지 일을 Controller 하나가 수행하면 되지만, 결국 유지보수가 어려워진다.
프로그램은 보통 협업을 하다보니 여러사람과 코드를 공유하고 커뮤니케이션을 해야한다.
다른 개발자가 내 비지니스 로직을 수정 하고 싶은데, 1번과 2번의 코드가 같이 있으면 어떤게 비니지스 로직인지 알아보기가 어려울 것이다.
따라서 Service라는 비지니스 로직을 수행하는 역할을 하는 클래스를 새로 만들고, Controller는 서비스를 호출만 하도록 하여 기능을 분리한 것이다.
정리하자면, Controller는 현재 HTTP요청을 받아 서비스를 호출하고, Model에 데이터를 담아 뷰를 렌더링 하게된다.
서비스가 비지니스로직을 수행하게 되었다.
3. Service, DAO
데이터를 관리하기 위해서 DB와 프로그램을 연결해야 하는 것을 모두가 알 것이다.
이때, DB에서 데이터를 등록, 수정, 삭제, 조회 등을 하기 위해서는 SQL이 필요하다.
우리가 흔히 아는 select sql문이다.
select * from Member M
회원가입을 하기 위해서는 DB에 insert 쿼리를 날려야 한다.
JDBC를 이용하여 자바코드로 DB에 쿼리를 날릴 수 있다.
즉 데이터베이스에 접근하기 위해서는 JDBC를 사용해야 한다.
JDBC는 매우 복잡하고, 객체지향적이지 못하다. JDBC의 여러 문제점을 해결한 것이 바로 JPA기술이다. JPA는 간단한 등록, 조회, 삭제 등은 자바의 리스트에 데이터를 넣고, 수정하고, 삭제하는 것과 같이 동작하도록 편의를 제공해준다.
따라서 JPA를 사용하여 DB에 접근하는 것이라고 생각하면 편하다.
설명이 길었는데, 서비스에서는 비지니스로직을 수행한다.
즉, 회원가입을 하면 DB에 insert 쿼리를 날린다.
뿐만 아니라, 서비스에서는 주문을 하거나, 주문을 취소하는 등 여러 가지 기능을 제공해야 한다.
여기서 문제는 주문을 하는것이 하나의 SQL쿼리로 되는 것이 아니다.
주문을 하기 위해서는 주문을 하는 회원과 상품을 DB에서 조회해야 한다.
또한, 해당 회원과 상품을 받아서 Order(주문객체)를 생성해야 한다.
이후 주문객체를 DB에 저장해야 한다. DB에 저장하는 이유는 회원이 자신의 주문내역을 보고싶을때 보여주기 위해서이다.
또한 상품주문 로직에서만 회원, 상품을 조회하는 것이 아니라
상품목록을 보여주는 서비스에서도 상품을 조회하고,
회원목록을 보여주는 서비스에서도 회원을 조회한다.
즉 여러 서비스에서 반복적인 SQL이 발생한다.
따라서 서비스와 DAO는 분리해야 하는 것이다.
DAO는 Data Access Object의 약자로 데이터에 접근하는 오브젝트를 의미한다.
우리가 흔히 아는 레포지토리가 DAO에 해당한다.
DAO에서 회원 등록, 조회 쿼리,
상품 등록, 조회 쿼리 등을 메서드로 만들어서 클래스(레포지토리)로 보관하면,
서비스계층에서 얻는 이익이 매우 많아진다.
메서드로 만들어서 반복적인 SQL문 작성을 줄일수 있게 되고, 메서드 이름 만으로 해당 메서드가 무슨 역할을 하는지, 서비스가 어떻게 동작하는 지 한눈에 알아보기 쉽게 된다.
즉, Controller, Service, DAO는 역할을 나눈 것이다.
Controller의 비지니스로직 수행을 Service 계층으로 넘기고, 서비스에서는
비지니스 로직을 수행하되 DB접근을 DAO로 넘김으로써 각자 자신의 기능만을 수행하도록 만든 것이다.
이러한 방식은 앞서 말했듯이 유지보수에 매우 좋은 모델이다.
역할을 나눌 수록 협업하는 개발자가 코드를 보기 쉽게된다.
또한, 서비스 기능을 추가하는 것은 뷰 렌더링과는 아무 관련이 없다.
서비스 기능을 추가하는데 뷰 렌더링 코드를 봐야할 필요가 없는 것이다.
서비스 기능에 문제가 생기면, 서비스 계층만을 보면 되고, 뷰렌더링 기능에 문제가 생기면 Controller만 보면된다.
DB쿼리를 수정하고 싶으면 DAO를 수정하면 된다.
서비스 기능을 추가하고 싶은데, 뷰렌더링과 비지니스 로직, DB접근 쿼리가 전부 Controller에 담겨 있다면, 매우 유지보수하기 어려운 코드일 것이다.
4. 딜레마
역할을 세분화하는 것은 좋지만, 적당함이 중요하다.
예를들어, DB에 데이터를 저장하는 쿼리는 JPA에서 em.persist();를 사용한다. 해당 쿼리를 DAO에 save()라는 이름의 메서드 추상화 했다고 가정해보자.
서비스 계층에서 join()이라는 회원가입 비지니스로직을 수행하는 메서드를 만들었다. 해당 메서드 내부에서 DAO.save()만을 호출하고 로직이 끝날 수 있다.
그렇게 되면 join은 결국 em.persist();를 호출하는데 save()메서드로 가야하는 번거로움이 생길 수 있다.
즉, 한번에 갈 것을 두번에 걸쳐 가게 되는 것이다.
실무에서는 기능이 매우 복잡하기 때문에 서비스에서 단순히 DAO 메서드만 호출하는 경우는 거의 없지만, 이러한 경우에는 서비스를 거치지 않고 Controller에서 바로 DAO의 save()메서드를 호출해야 한다.
하지만 이렇게 되면 Controller는 Service와 연관관계 매핑이 되는게 아니라 DAO(레포지토리)와 연관관계를 맺게 된다.
그렇다고 안좋은 코드가 아니다.
중요한 것은 연관관계가 한방향으로만 맺어져야 한다는 것이다.
Controller -> Service -> DAO -> DB 가 정석이지만,
Controller -> DAO -> DB 또한 같은 한방향 연관관계 매핑에 해당된다.
따라서 서비스를 거치지않고 Controller가 DAO와 연관관계를 맺는 것도 가능하다.
'Spring boot > Spring MVC 1' 카테고리의 다른 글
[Spring MVC] 8. @PathVariable VS @RequestParam (0) | 2023.01.25 |
---|---|
[Spring MVC] 7. 스프링 MVC - 웹 페이지 만들기 (0) | 2023.01.25 |
[Spring MVC] 6. 스프링 MVC - 기본 기능 (0) | 2023.01.25 |
[Spring MVC] 5. 스프링 MVC - 구조 이해 (0) | 2023.01.25 |
[Spring MVC] 4. MVC 프레임워크 만들기 (0) | 2023.01.25 |
[Spring MVC] 3. 서블릿, JSP, MVC 패턴 (0) | 2023.01.25 |
[Spring MVC] 2. 서블릿 (0) | 2023.01.25 |
[Spring MVC] 1. 웹 애플리케이션 이해 (0) | 2023.01.25 |