본문 바로가기
교재 실습/자바 웹 개발 워크북

62. DAO 만들기 (1)

by Jint 2022. 7. 6.

이번 절에서는 서블릿이 하는 일 중에서 일부 기능을 분리한다. 완전하지는 않지만 MVC 아키텍처의 구색을 갖추게 되었다. 서블릿으로부터 분리해야 하는 기능은 데이터베이스와 연동하여 데이터를 처리하는 부분이다. 이렇게 데이터 처리를 전문으로 하는 객체를 'DAO(data access object)'라고 부른다(그림 1).

그림 1 (DAO의 분리)

DAO는 데이터베이스나 파일, 메모리 등을 이용하여 애플리케이션 데이터를 생성, 조회, 변경, 삭제하는 역할을 수행한다. DAO는 보통 하나의 DB 테이블이나 DB 뷰에 대응한다. 물론 여러 개의 테이블을 조인(join)한 데이터를 다루기도 한다.

업무 로직에서 데이터 처리 부분을 분리하여 별도의 객체로 정의하면, 여러 업무에서 공통으로 사용할 수 있기 때문에 유지보수가 쉬워지고 재사용성이 높아진다(그림 2).

그림 2 (업무 로직을 수행하는 객체들의 DAO 공유)

이번 절에서는 회원 관리 예제에서 서블릿이 하던 데이터 처리 부분을 분리하여 DAO로 정의해본다.

 

1. DAO 사용하기

MemberListServlet 클래스에서 데이터 처리 로직을 분리하여 MemberDao 클래스를 정의한다. 다음 그림은 회원 목록 출력에 대한 MVC 구조도이다(그림 3).

그림 3 (DAO가 적용된 후의 회원 목록 조회 시나리오)

① 웹 브라우저에서 회원 목록을 요청한다.

② MemberListServlet 클래스는 회원 목록 데이터를 얻기 위해 MemberDao 클래스의 메서드를 호출한다.

③ MemberDao 클래스는 데이터베이스로부터 회원 정보를 가져온다.

④ MemberDao 클래스는 결과 레코드의 개수만큼 Member 객체를 만들어 서블릿에게 반환한다.

⑤ MemberListServlet 클래스는 MemberDao 클래스로부터 받은 회원 목록을 MemberList.jsp에게 전달한다.

⑥ MemberList.jsp는 회원 목록 데이터를 가지고 화면을 생성한다. 그리고 다시 제어권을 MemberListServlet 클래스에게 넘긴다.

⑦ MemberListServlet 클래스는 웹 브라우저의 요청에 대해 응답을 완료한다.

(그림 3에서 MemberList.jsp에서 Header.jsp와 Tail.jsp를 인클루딩 하는 내용은 생략했다.)

 

2. DAO 생성

web05 프로젝트에 spms.dao 패키지를 생성하여 MemberDao 클래스를 생성한다.

package spms.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import spms.vo.Member;

public class MemberDao {
	Connection connection;

	public void setConnection(Connection connection) {
		this.connection = connection;
	}
	
	//회원 목록 SELECT DAO
	public List<Member> selectList() throws Exception {
		Statement stmt = null;
		ResultSet rs = null;

		try {
			stmt = connection.createStatement();
			rs = stmt.executeQuery(
					"SELECT MNO,MNAME,EMAIL,CRE_DATE" + 
					" FROM MEMBERS" +
					" ORDER BY MNO ASC");

			ArrayList<Member> members = new ArrayList<Member>();

			while(rs.next()) {
				members.add(new Member()
					   .setNo(rs.getInt("MNO"))
					   .setName(rs.getString("MNAME"))
					   .setEmail(rs.getString("EMAIL"))
					   .setCreatedDate(rs.getDate("CRE_DATE"))	);
			}
			return members;
		} catch (Exception e) {
			throw e;
		} finally {
			try {if (rs != null) rs.close();} catch(Exception e) {}
			try {if (stmt != null) stmt.close();} catch(Exception e) {}
		}
	}
}

MemberListServlet 클래스에 있던 데이터베이스 연동 코드를 MemberDao 클래스의 selectList() 메서드 안으로 옮겼다. selectList() 메서드의 목적은 데이터베이스로부터 회원 정보를 가져와서 값 객체 Member에 담고, 그 Member 객체의 목록을 컨트롤러에게 반환하는 것이다.

//회원 목록 SELECT DAO
public List<Member> selectList() throws Exception {
    ...
    ArrayList<Member> members = new ArrayList<Member>();
    ...
    return members;
    ...
}

selectList() 메서드의 리턴 타입이 List 인터페이스인 것을 주목한다. selectList() 메서드에서 실제로 리턴하는 것은 ArrayList 객체인데 리턴 타입은 List인 것은 프로그래밍의 유연성 때문이다.

메서드의 리턴 타입이나 매개변수 타입을 특정 클래스로 명시하게 되면, 반드시 그 클래스(서브 클래스 포함)의 객체를 주고 받아야 하기 때문에, 유연성이 떨어진다. 이런 이유로 메서드를 호출하는 쪽과 그 메서드를 만드는 쪽 모두 유연성을 높이고자, 구체적인 클래스를 사용하기 보다는 주로 인터페이스를 사용한다.

 

- Connection 객체 주입

MemberDao 클래스에서 또 주목할 것은 connection 인스턴스 변수와 셋터 메서드이다. MemberDao 클래스에서는 ServletContext에 접근할 수 없기 때문에, ServletContext에 보관된 DB Connection 객체를 꺼낼 수 없다. 이를 해결하기 위해, 외부로부터 Connection 객체를 주입받기 위한 셋터 메서드와 인스턴스 변수를 준비하였다.

Connection connection;

public void setConnection(Connection connection) {
    this.connection = connection;
}

당연히 selectList()가 호출되기 전에, Connection 객체가 먼저 설정되어야 한다. 이렇게 작업에 필요한 객체를 외부로부터 주입 받는 것을 '의존성 주입(DI, Dependency Injection)'이라고 부른다. 다른 말로 '역제어(IoC, Inversion of Control)'라고도 부른다.

이 셋터 메서드를 호출하는 것은 MemberListServlet 클래스이다. MemberListServlet 클래스에서 MemberDao 클래스를 사용할 것이기 때문이다.

 

참고도서 : https://freelec.co.kr/book/1674/

 

[열혈강의] 자바 웹 개발 워크북

[열혈강의] 자바 웹 개발 워크북

freelec.co.kr

'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글

64. ServletContextListener와 객체 공유 (1)  (0) 2022.07.09
63. DAO 만들기 (2)  (0) 2022.07.07
61. JSTL 사용하기 (6)  (0) 2022.07.05
60. JSTL 사용하기 (5)  (0) 2022.07.04
59. JSTL 사용하기 (4)  (0) 2022.07.03

댓글