Service와 DAO객체의 구현
Spring 기반의 MVC Model2 패턴
클라이언트: 웹 어플리케이션인 웹브라우저 <- 웹브라우저를 사용하는사람 : 이용자,클라이언트
웹브라이저 : 크롬,엣지,사파리,익스플로어
자원요청 : 페이지요청,데이터사용 요청등
서버 : 웹 어플리케이션을 제작하는 사람의 컴퓨터 - 서버컴퓨터
(서버안에 Spring이 있으므로 서버안에 스프링 안에 컨테이너가 동작)
클라이언트 측에서 서버쪽으로 자원(resource)요청(request)을 지속적으로 보낼때
Spring컨테이너가 프레임워크(서버) 안쪽에서 작동하고있습니다.
서버안에서는 받은 요청을 DispatcherServlet이 처리를 합니다
DispatcherServlet이 요청을 받은 후 HandlerMapping,Adapter를 통해 컨트롤러에 연결을 해줍니다
RequestMapping GetMapping PostMapping 들의 uri 정보를 가지고 해당 컨트롤러에 연결을 해줍니다.
컨트롤러 메서드 안쪽에서 JDBC로직을 돌린다면 DB 서버와 연동을 수행할 수 있습니다.
이렇게 되면 컨트롤러의 할 일이 너무 많아지게 됩니다.
컨트롤러가 데이터 중간처리, 데이터 정제처리 + DB 의 SQL처리까지 다 하게되면 일이 과부화되며
계층으로 나누지 않는다면 유지보수, 코드유지보수나 모듈화 관점에서도 좋지가 않으므로 서버와 DB 사이에 중간계층을 두게됩니다.
실질적으로는 컨트롤러에서는 데이터베이스서버까지 들어가서 데이터들을 다룰수있는 로직이 필요합니다
MVC구조라는 데이터소스 계층(DB)을 사용할수 있는구조에 대한 공수를 투입해야합니다.
Controller에서 DataBase에 접근하여 작업을 수행하기위해서는 Service계층과 DAO라고 부르는 Repository계층을 구현해야합니다.
Repository계층에 대해서()
DB(데이터소스)계층과 연결을 할 때 Repository라는 저장소를 두게 됩니다.
Repository는 흔히 Model이라고 하는데 스프링에서는 Repository라고 부릅니다.
Repository를 구성하는 클래스는 DAO DTO VO가 되며 이들을 통해서 DB와 연결을 합니다.
DB연동로직(JDBC)은 DAO에서 insert,update,delete,select를 전담하게 됩니다.
DB를 사용하는것은 아무래도 온전하게(안정성) 데이터를 보관하고 관리하는 측면에서 유리하기때문에
프로그램에 필요한 데이터들은 DB에 보관해두고 데이터내용을 입력,수정,삭제 하거나 읽는작업들을 수행해야합니다.
이런작업들을 Repository계층에서 수행하여 Controller의 부담을 줄이게 합니다.
그리고 SQL의 변동이라던가 어떠한 특정 처리의 변동이 일어난다면 DAO안에서 해결할 수 있습니다.
즉, Repository계층에는 DataAccessObject라는 DAO를 만들어서 DB연동을 수행하게 하고
Controller와 DAO사이에 어떤 데이터를 추가적인 데이터 정제나 관리가 필요하다면
또 어떤 다른 여러 DAO를 호출할수 있을때 서비스계층에서 잡다한 작업을 처리하도록 합니다.
Controller와 DAO간의 중간계층이 하나 더 생성되는데 이것을 Service계층 이라고 합니다
Service의 역할은 무엇인가?
게시글을 select하기 위해서 게시물 목록요청이 서버로 들어오게되면
서버 안의 SpringContainer의 DispatcherServlet이 BoardController를 찾아주고
Controller계층의 BoardController에 매핑된 메서드에 의해서 어떠한 Service가 호출되고
Service에서 Repository계층인 DAO 메서드를 호출하면
DAO에서 DB에 접근하여 어떤 목록리스트를 가져오게됩니다.
이때 다시 목록 리스트를 가지고 역순으로 Service - Controller에 보내주면
Controller는 View리졸버를 통해서 뷰페이지를 찾아준다음 JSTL,EL을 활용하여
뷰페이지에 DB정보들을 담아 화면에 응답해줍니다.
만약에 DB로부터 글목록을 받아왔을때 DB로부터 받아온 글 정보 중에 글등록 날짜 가
2019-2019-07-14-22:..... 밀리초단위 까지 가져왔다면 사용자한테는 년월일 많다면 시분초까지 보여주면 되기때문에
가공을합니다.
혹은 신규글 처리에 대해서 new 마크를 붙여주고 싶다면 (하루 이내에 등록된 게시물은 new를 붙혀줍니다.)
이런 로직처리를 Repository계층에서 하게되면 JDBC하기도 바쁜데 그것까지 할수없고 또 Controller쪽에서는 페이지에대한 정보 요청,모델 등을 세팅하기도 바쁩니다.
서비스쪽에서 데이터 정제작업을 합니다.
예를들어 Insert를 할 때도 회원아이디에 공백이 들어갔다면 DB에 들어가기전에 제거를 하는역할?도 하기도 합니다.
중간처리를 해주는 중간계층 역할을 Service에서 합니다
계층을 이렇게 나눠버리면 역할이 확실하게 구분되면서 코드를 유지,보수 하기가 편해집니다.
하나의 클래스에 다 맡기기보다는 중간에 계층을 좀더 나누어 역할을 분담하자는것이
MVC패턴의 모듈화(코드쪼개기)입니다.
계층들이 구현되있을텐데 계층간에는 서로간에 상호 의존성이 부여되어 있어야 작용합니다.
Controller는 Service없이 DAO에 접근할수 없으므로 Controller는 Service에 의존적입니다. 서로 의존관계가 설정되있습니다.
Service는 DAO가 없으면 DB에 접근할 수 없어 작업을 할수 없으므로 Service는 DAO와 의존성관계를 가집니다.
서로서로 의존성 주입을 사용하는 자동빈등록 이라던가 자동 의존성주입을 활용합니다.
DAO와 Service를 구현할때는 바로 클래스를 구현해도 되지만 일반적으로 인터페이스를 통해 추상메서드들 정의해두고 메서드의 구체화는 클래스에서 합니다.
이렇게되면 좀더 추상화된 객체구성을 할수 있게됩니다.
기본적으로 인터페이스는 new연산자로 객체생성을 할수 없습니다.
@Controller
public class Controller{
Service service = new ServiceImpl();
}
인터페이스로 객체를 생성하기 위해서는 인터페이스(Service)를 구현,상속 받은 하위클래스(ServiceImpl)를 new연산자를 사용하여 객체를 생성합니다.
이는 인터페이스에 선언된 추상메서드를 구현 상속받은 클래스에서 구현할 메서드에 대한 코드를 구체화 해주기 때문입니다.
하지만 이것은 구식방법입니다.
스프링에서는 객체를 빈으로 등록하여 관리할수있도록 @Componet라는 어노테이션을 사용하여 빈으로 등록합니다.
@Component를 모든 클래스에 사용하여도 무관하지만, 가독성과 의미를 맞출수 있도록 같은 뜻과 기능을 가진 @Controller, @Repository, @Service 어노테이션을 사용합니다.
이 어노테이션들은 모두 @Component 어노테이션을 상속받고 있습니다.
@Component는 주로 일반적인 클래스에 선언합니다.
(Service, Repository 계층이 아닌 Controller나 Service,DAO에서 의존관계를 가져 객체를 주입해야 할때 / 일반적인 클래스를 객체화하여 주입하기 위해 스프링컨테이너에 빈 등록을 할때 쓰이는것같습니다.)
@Controller
public class Controller{
@Autowired
private Service service;
}
@Componet와 같은 스프링 컨테이너에 빈 등록 기능을 해주는 @Controller어노테이션을 등록해줌으로써 빈 등록을 해 주며
@Autowired 어노테이션을 사용하여 등록된 빈을 불러와 객체를 주입시킵니다.
이것을 자동 의존성 주입이라고 합니다.
Controller는 Service인터페이스에 의존성을 가지고있으며, Controller와 Service인터페이스는 의존관계에 있다.
라고 말합니다.
public interface Service {
}
구현할 기능을 추상메서드로 추상화 합니다
Controller와 ServiceImpl클래스간의 중간매개체 역할을 합니다.
클래스와 클래스간의 마모도를 감소시켜주기 위해 한번 거쳐가는 곳입니다.(미끄럼틀타듯 미끄러지듯)
톱니바퀴와 톱니바퀴사이의 마모를 억제해주는 윤할제 역할에 비유할 수 있습니다.
@Service
public class ServiceImpl implements Service{
@Autowired
private Dao dao;
}
@Componet와 같은 스프링 컨테이너에 빈 등록 기능을 해주는 @Service어노테이션을 등록해줌으로써 빈 등록을 해 주며
@Autowired 어노테이션을 사용하여 등록된 빈을 불러와 객체를 주입시킵니다.
이것을 자동 의존성 주입이라고 합니다.
ServiceImpl클래스는 Dao인터페이스에 의존성을 가지고있으며, ServiceImpl클래스와 Dao인터페이스는 의존관계에 있다.
라고 말합니다.
Service 인터페이스에 선언된 추상메서드를 구체화 하여 Controller와 DAO를 연결해주는 중간 매개체 역할을 합니다.
실질적인 기능보다는 추가적인 기능(Dao의 기능을 도와주는 보조역할) 기능을 이곳에서 구현합니다. (오버라이딩)
public interface Dao{
}
Service인터페이스와 마찬가지로 구현할 기능을 추상메서드로 추상화 합니다.
인터페이스를 사용하여 ServiceImpl클래스와 DaoImpl클래스간의 중간매개체 역할을 합니다.
클래스와 클래스간의 마모도를 감소시켜주기 위해 한번 거쳐가는 곳입니다.(미끄럼틀타듯 미끄러지듯)
톱니바퀴와 톱니바퀴사이의 마모를 억제해주는 윤할제 역할에 비유할 수 있습니다.
@Repository
public class DaoImpl implements Dao{
}
Controller가 호출한 메서드가 중간에 Service를 거쳐 이곳으로 왔습니다.
사용자가 요청한 작업의 실질적인 기능을 이곳에서 구현합니다. (오버라이딩)
빈 등록을 설정하려면 servlet-context.xml에서
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 어노테이션을 활용하여 자동으로 빈 등록을 하게 해주는 설정태그 -->
<context:component-scan base-package="빈등록을 할 클래스들의 패키지 경로" />
</beans:beans>
<context:component-scan base-package="">태그를 등록합니다
base-package 속성에 빈 등록을 할 클래스들의 패키지 경로를 입력합니다
프로젝트를 생성할 때 정의한 artifactId+groupId가 됩니다.
이것은 @Component 및 상속받은 Component어노테이션들을 자동으로 빈 객체로 등록해주며 @Autowired가 선언된 레퍼런스에 객체를 주입 시켜줍니다.
이 태그로 인해 빈 등록과 등록된 빈을 의존성주입해주는 작업들이 함께 맞물려 돌아갑니다.