Hyokyun Yim bio photo

Hyokyun Yim

Koreatech Computer Science Engineering undergraduate 4 grade.

Facebook Github

간단한 도서검색 프로그램을 작성하면서 JDBC와 MVC Pattern에 대해 이해하고 이를 바탕으로 Spring의 DI개념에 대해서 이해해 보자

Overview

Database 세팅

  1. MySQL 이용 - v5.7 , MySQL Workbench UI 툴 이용
  2. ID/PW : root/cps431
  3. 데이터가 저장돌 데이터베이스를 생성 library 스키마 생성
  4. 새로운 사용자가 방금 만든 데이터베이스를 사용할 수 있도록 권한부여
  5. 생성된 데이터베이스에 Table을 만들어서 데이터를 집어 넣어는다.
  6. 한빛미디어 IT계열 책에대한 정보를 사용하여 테이블로 만듬.

데이터베이스를 Access 하는 자바 프로그램 작성(아주 무식한 방법)

  1. Project를 생성하고 클래스를 만들어서 main method 내에서 모든걸 처리!!
  2. Maven을 사용하여 MySQL 라이브러리를 주입 Dependency Injection
  3. 콘솔창으로 입력을받고 데이터베이스 로직 처리를 한 후 결과를 출력

package book;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		//프로그램 작성
		// 1. 입력을 받아요
		// 책 제목에 대한 keyword를 받는다.
		System.out.print("키워드를 입력하세요 =>");
		
		//도스창으로부터 입력을 받기위해 Scanner 객체 생성
		//Scanner 객체로 도스창으로부터 입력을 하나씩 받는다. 
		Scanner s = new Scanner(System.in);
		String keyword = s.nextLine();
		
		
		// 2. 로직 처리를 해요
		// 데이터베이스 처리를 해요!!
		try{
			//2-1. 드라이버 로딩
			//자바프로그램이 MySQL에 접근하기 위해서 필요한 라이브러리를 불러들인다.
			//pom.xml 에 MySQL에 대한 dependency를 입력해서 라이브러리를 다운로드 받는다.
			Class.forName("com.mysql.jdbc.Driver");
			System.out.println("Driver loading Success");
			
			
			//2-2 실제 데이터베이스에 접속
			//어떤 데이터베이스에 접속할 건지, 아이디와 패스워드가 필요
			String url = "jdbc:mysql://localhost:3306/library";
			String id = "root";
			String pw = "cps431";
			Connection con = DriverManager.getConnection(url,id,pw);
			System.out.println("Database loading Success");
			
			//2-3.SQL문을 실행하기 위한 Statement를 생성한다.
			String sql ="select btitle,bauthor from book where btitle like ?";
			PreparedStatement pstmt = con.prepareStatement(sql);
			
			//sql문에 내가 원하는 문자열을 넣는 작업
			//첫번째 물음표에 , keyword를 넣는다.
			//% 와일드문자는 0개이상의 문자를 의미한다. 즉 keyword를 포함하고 있는 문자열을 ?에 넣는다.
			pstmt.setString(1,"%"+ keyword + "%"); 
			
			
			//2-4 Statement 실행!!
			//수행한 쿼리문의 결과를 가져옴
			//rs 는 테이블 라인을 가리키는 포인터. 한칸씩 내려가면서 라인을 가리킴
			ResultSet rs = pstmt.executeQuery();
			
			//2-5 결과처리
			//반복 해서 rs.next() 를 수행하고
			//btitle 컬럼명의 열의 문자열을 가져와라.
			while(rs.next())
			{
				System.out.println("책 제목:" + rs.getString("btitle"));
			}
		
			//2-6 사용한 리소스 정리
			rs.close();
			pstmt.close();
			con.close();
			
			
		}catch(Exception e){
			//만약 오류가 생기면 오류 출력
			System.out.println(e);
		}
		
	
	}

}


  • rs는 테이블의 라인을 가리키는 포인터이다.
  • 한라인 씩 내려가면서 가리킴

  • rs.next()로 한라인 내려간후 지정된 컬럼명의 문자열을 가져옴

  • 검색명 java로 수행을 하면 위 사진과 같이 결과가 나온다.

MVC Pattern 을 이용해서 위의 프로그램을 작성해 보자.

  • 위에서 작성한 프로그램은 JDBC(Java로 데이터베이스를 Access 하는 방법)의 기초적인 방법을 사용하였음.
  • Java언어의 탈을 쓴 절차적인 프로그래밍일 뿐이다.
  • 따라서 위의 프로그램은 객체지향프로그래밍의 가장 큰 특징인 유지보수성과 재활용성이 없다.

Layered Model

  • 프로그램을 입력/출력 부분(Controller) <-> 로직 처리부분(Service) <-> 데이터베이스 처리 부분(DAO) 으로 나눠버린다.
  • 각 계층을 역할별로 나누고, 인접한 계층끼리만 인터렉션을 수행하자. -> 유지보수성이 좋아진다. 즉 DB가 바끼면 DAO만 보면되고, 로직이 바뀌면 Service만 보면된다.
  • 이렇게 프로그램을 짜는것을 MVC Pattern이라고 한다.
  • Controller , Service, DAO ,DTO 도 각각 클래스로부터 만들어진 하나의 인스턴스이다.
  • 데이터베이스로부터 뽑아낸 데이터를 저장하기위한 객체를 DTO라고 하며 이 객체를 이용하여 데이터를 전달한다.
  1. 입력, 출력 : Controller
  2. 로직 : Service
  3. 데이터베이스 처리 : DAO(Data Access Object)
  4. 데이터 전달 객체 : DTO(Data Transfer Object), VO(Value Object), DO(Domain Object), Entity -> 깊숙히 들어가면 약간의 의미가 다르긴하지만 보통 같다고 보고 4가지 용어로 말한다.

실제 웹 어플리케이션 에서의 MVC Pattern

  • DOS창에서는 Conctoller 내에서 같이 구성 하였지만 , 웹에서는 html,jsp로 사용자의 입력,출력을 수행하는 View를 구성하고 Controller에 연결되는 식으로 되어있다.
  • Model은 즉 로직 처리부분과, DTO를 말한다.
  • Controller는 View와 Model의 중개자 역할을 수행함.

기존 프로그램을 MVC Pattern 으로 수정해보자.

//Main
import Controller.BookController;

public class Main {

	public static void main(String[] args) {
		
		//BookController를 하나 생성 
		new BookController();
		
	}

}

//Controller

package Controller;

import java.util.ArrayList;
import java.util.Scanner;

import DTO.BookDTO;
import Service.BookService;

public class BookController {
		
		//반복 사용되는 자원들은 필드로 잡아서 사용하는게 효율적이다.
		Scanner s;
	
		public BookController()
		{
			//controller 생성 
			System.out.print("책 제목을 입력하세요=>");
			s = new Scanner(System.in);
			String keyword = s.nextLine();
			
			//입력은 다 받았다. 이제 입력받은 값을 이용해서 로직처리 해야함
			//그런데 Controller는 로직처리를 하지않는다. 즉 딱 입력과 출력만 Controller에서 수행s
			//로직을 처리하는 instance는 Service라고 불리는 놈을 이용한다. -> Class를 새로만들어 인스턴스 생성
			BookService service = new BookService();
			ArrayList<BookDTO> list = service.findBookbyKeyword(keyword);
			
			//로직에서 처리한 list를 출력처리
			for(BookDTO dto : list)
			{
				System.out.println(dto.getBtitle() + ", " + dto.getBauthor());
			}
		}
}


//Service 

package Service;

import java.util.ArrayList;

import DAO.BookDAO;
import DTO.BookDTO;

//Service 는 로직을 처리하는 객체를 만들기위한 class
public class BookService {

	public ArrayList<BookDTO> findBookbyKeyword(String keyword) {
		
		
		//로직처리 수행(더하고, 빼고, 반복문 돌리고 등등..) -> 다만 우리가 수행할 코드는 로직수행이 필요없음 검색만하면됨. 
		//따라서 바로 데이터베이스 처리가 필요하다. -> 그런데 데이터베이스 처리는 무조건 DAO에서 수행
		//dao 인스턴스 생성
		BookDAO dao = new BookDAO();
		//dao로 keyword를 넘김
		ArrayList<BookDTO> list = dao.select(keyword);
		return list;
	}

}

//DAO

package DAO;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Scanner;

import DTO.BookDTO;

//도서에 관한 Database처리를 하는 instance를 만들기 위한 class
public class BookDAO {

	public ArrayList<BookDTO> select(String keyword) {

		//제네릭을 이용해 BookDTO형 ArrayList만듬
		ArrayList<BookDTO> list = new ArrayList<BookDTO>();

		try{
			//1. 드라이버 로딩
			//자바프로그램이 MySQL에 접근하기 위해서 필요한 라이브러리를 불러들인다.
			//pom.xml 에 MySQL에 대한 dependency를 입력해서 라이브러리를 다운로드 받는다.
			Class.forName("com.mysql.jdbc.Driver");
			
			//2. 실제 데이터베이스에 접속
			//어떤 데이터베이스에 접속할 건지, 아이디와 패스워드가 필요
			String url = "jdbc:mysql://localhost:3306/library";
			String id = "root";
			String pw = "cps431";
			Connection con = DriverManager.getConnection(url,id,pw);	
			
			//3. SQL문을 실행하기 위한 Statement를 생성한다.
			String sql ="select btitle,bauthor from book where btitle like ?";
			PreparedStatement pstmt = con.prepareStatement(sql);
			
			//sql문에 내가 원하는 문자열을 넣는 작업
			//첫번째 물음표에 , keyword를 넣는다.
			//% 와일드문자는 0개이상의 문자를 의미한다. 즉 keyword를 포함하고 있는 문자열을 ?에 넣는다.
			pstmt.setString(1,"%"+ keyword + "%"); 
			
			
			//4. Statement 실행!!
			//수행한 쿼리문의 결과를 가져옴
			//rs 는 테이블 라인을 가리키는 포인터. 한칸씩 내려가면서 라인을 가리킴
			ResultSet rs = pstmt.executeQuery();
			
			//5. 결과처리
			//여기서 얻은 데이터를 어떻게 해서든 Controller 까지 전달하여 출력
			//DTO가 책 1권에 대한 데이터를 담을 수 있으니까.. DTO를 여러개 만들어서 결과로 나온 여러권의 책을 담아서 
			//Controller에게 전달한다!!
			while(rs.next())
			{
				//한 책에대한 정보가 담긴 rs를 dto에 때려박음
				BookDTO dto = new BookDTO();
				dto.setBtitle(rs.getString("btitle"));
				//dto.setBisbn(rs.getString("bisbn"));
				//dto.setBprice( rs.getInt("bprice")  );
				dto.setBauthor(rs.getString("bauthor"));
				
				//한권의 책정보 dto를 리스트에 넣음
				list.add(dto);
				
			}
		
			//6. 사용한 리소스 정리
			rs.close();
			pstmt.close();
			con.close();
			
			
		}catch(Exception e){
			//만약 오류가 생기면 오류 출력
			System.out.println(e);
		}
		
		
		return list;
	}

}

//DTO

package DTO;

//데이터 전달을 목적으로 하는 DTO 객체를 만들기 위한 class
// 내가 전달한 Database의 Table을 근간으로 만든다.
public class BookDTO {

	private String bisbn;
	private String btitle;
	private String bauthor;
	private String bdate;
	private int bpage;
	private int bprice;
	
	//각필드를 사용하기위한 Getter/Setter method 작성
	public String getBisbn() {
		return bisbn;
	}
	public void setBisbn(String bisbn) {
		this.bisbn = bisbn;
	}
	public String getBtitle() {
		return btitle;
	}
	public void setBtitle(String btitle) {
		this.btitle = btitle;
	}

	public String getBauthor() {
		return bauthor;
	}
	public void setBauthor(String bauthor) {
		this.bauthor = bauthor;
	}
	public String getBdate() {
		return bdate;
	}
	public void setBdate(String bdate) {
		this.bdate = bdate;
	}
	public int getBpage() {
		return bpage;
	}
	public void setBpage(int bpage) {
		this.bpage = bpage;
	}
	public int getBprice() {
		return bprice;
	}
	public void setBprice(int bprice) {
		this.bprice = bprice;
	}
	

	
}