Development/Java

데이터 서비스 클레스 분리, DB 연결 정보 분리 #6

evagrim 2022. 8. 29. 21:35

 

 


<서비스 클래스 분리하기>


DAO(data access object)를 예로들어 app을 서비스 중에 데이터베이스만을 교체해야 하는 경우가 생길 수 있다
JDBC를 사용 중에 JPA로 바꾸던가 mybatis를 사용한다던가
이러한 경우에 해당 클래스들을 모듈화(인터페이스화) 시켜 컴파일 되지 않은 문서형 설정 파일에서 쉽게 교체할 수 있도록 만들어줄 필요가 있다

본래는 DAO를 따로 만들어 DB에 관련된 코드를 작성하고
사용하는 클레스를 둬야 하지만 DI의 작업 방식이 xml에서 annotation으로 변화하는 과정을 확인하기 위한 연습중이므로 서비스 클레스에서 직접 jdbc를 사용한다고 가정한다
그러기 위해서 pom.xml에 ojdbc 설치


<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.7.0.0</version>
</dependency>


Service 클레스를 인터페이스화 하기 전에 먼저 spring스럽게 클레스를 dispatcher-servlet.xml에서 객체화 시켜서 컨트롤러에 꼽아본다


<bean id="noticeService" class="com.newlecture.web.service.jdbc.NoticeService">

<bean name="/notice/list" class="com.newlecture.web.controller.notice.ListController">
     <property name="noticeService" ref="noticeService" />
</bean>


property name="noticeService"는 setNoticeService() 메소드를 불러오는 부분이므로 ListController에서 noticeService를 set 해주는 setter를 만들어준다


public class ListController implements Controller {

private NoticeService noticeService;


public void setNoticeService(NoticeService noticeService) {
this.noticeService = noticeService;
}

@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub

ModelAndView mv = new ModelAndView("notice.list");
//mv.setViewName("/WEB-INF/view/notice/list.jsp");
List<Notice> list = noticeService.getList(1, "TITLE", "");
mv.addObject("list", list);

return mv;
}

}


NoticeService에서 사용하는 서비스 메소드를 사용해서 클레스가 제대로 연결이 되는지 확인해본다
(view도 서비스 메소드를 사용할 수 있게 수정)



<잘 되면 서비스 클래스 분리를 시작한다>

하위 패키지를 생성해 NoticeService에 기능적으로 분류될 클레스들을 만든다
(DAO를 예로들었으니 JDBCNoticeService, JPANotceService 등)

인터페이스로 사용될 껍데기 NoticeService를 만든다


public interface NoticeService {

List<Notice> getList(int page, String field, String query) throws ClassNotFoundException, SQLException;
int getCount() throws ClassNotFoundException, SQLException;
int insert(Notice notice) throws SQLException, ClassNotFoundException;
int update(Notice notice) throws SQLException, ClassNotFoundException;
int delete(int id) throws ClassNotFoundException, SQLException;

}

이 NoticeService 멀티탭(인터페이스)에 꼽을라면 위와 같은 요구를 충족해야함

 

NoticeService를 인터페이스 삼아 요구 사항들을 야무지게 구현한 클레스를 만들어준다


public class JDBCNoticeService implements NoticeService {
public List<Notice> getList(int page, String field, String query) throws ClassNotFoundException, SQLException{ 이렇게 이렇게 돌아가게 만들거임 }



이제 dispatcher.servlet.xml 에서
<bean id="noticeService" class="com.newlecture.web.service.jdbc.NoticeService">

<bean id="noticeService" class="com.newlecture.web.service.jdbc.JDBCNoticeService">
이렇게만 바꿔주면 만들어놓은 NoticeService를 마음대로 바꿔줄 수 있게 된다



<연결 정보 분리하기>


서비스 배포시에 컴파일된 바이너리 코드를 배포하는데 그 안에 DB의 ip나 id,pw가 있으면 마음대로 변경할 수가 없다. 변경할 때마다 서버 내리고 컴파일하고 빌드해서 재배포 할 수는 없는 노릇이니 이러한 데이터들도 dispatcher-servlet.xml로 빼줄 수 있다

연결 정보가 들어있던 클레스에 DataSource를 import 해준다


import javax.sql.DataSource;


DataSource에 마우스를 가져다 대면 Interface 타입인 것을 알 수 있다
(DataSource 타입을 실제로 객체화 시킬 수는 없다)


public class JDBCNoticeService implements NoticeService {
// private String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
// private String uid = "";
// private String pwd = "";
// private String driver = "oracle.jdbc.driver.OracleDriver";

private DataSource dataSource;

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

//Class.forName(driver);
//Connection con = DriverManager.getConnection(url,uid, pwd);
Connection con = dataSource.getConnection();


멤버선언과 setter를 만들어주고 서비스 메소드들에서 기존의 DB와의 연결 정보를 전달하던 부분은 삭제하고, dataSource 인터페이스에 설정된 연결 정보를 가져오는 방식으로 변경한다
이제 dataSource에 정보를 설정해줘야 하므로 dispatcher로 간다


<bean id="noticeService" class="com.newlecture.web.service.jdbc.JDBCNoticeService">
  <property name="dataSource" ref="dataSource" />
</bean>


property name에 만든 setter를 넣고 ref에는 아래 만들 dataSource의 id를 넣는다


<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521/xepdb1" />
<property name="username" value=""/>
<property name="password" value=""/>
</bean>


driverClassName, url, username, password은 DataSource를 implement해서 객체화한 org.springframework.jdbc.datasource.DriverManagerDataSource 클레스에서 만들어지는 setter 들이다

(이름이 정해져 있단 소리. 못바꿈)
value에 연결 정보를 넣으면 분리 완료

dispatcher에서 사용하는 org.springframework.jdbc.datasource.DriverManagerDataSource 객체는 spring-jdbc 라이브러리에서 가지고 있는 녀석이므로 없다면 pom.xml에 추가해준다


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>


이제 xml 설정만 바꾸면 소스코드 필요없이 DB의 연결정보를 변경할 수 있게 되었다