본문 바로가기

programming/Gukbi

국비 교육 43일차 - 오라클 연결 웹 프로젝트, servlet, HTML (input, attribute)

728x90
반응형

오늘 하루동안 이것 저것 많이도 배웠다. 일단은 오전에 오라클을 웹에 연결하는걸 배웠는데 계속 하던 DAO파일을 이용해서 뿌려서 그런지 엄청 어려운 느낌은 아니었다.

 

물론 내가 첨부터 다시 하라고하면 못한다...

 

일단 오라클에 연결을해서 데이터를 가져와야 하기 때문에,

오라클에 어떤 데이터가 있는지 확인을 먼저 해주고 VO파일을 만들어 준다. 

 

/*
 *  MNO         NUMBER(4)     
	TITLE       VARCHAR2(100) 
	GENRE       VARCHAR2(100) 
	POSTER      VARCHAR2(200) 
	ACTOR       VARCHAR2(300) 
	REGDATE     VARCHAR2(100) 
	GRADE       VARCHAR2(50)  
	DIRECTOR    VARCHAR2(100) 
 */

 오라클에서 DESC로 데이터형을 확인해준 뒤 가져온다. 이걸 보고 데이터형과 getter/setter를 만들어주면 된다. 

 

public class MovieVO {
	private int mno;
	private String title;
	private String genre;
	private String poster;
	private String actor;
	private String regdate;
	private String grade;
	private String director;
	
	
	public int getMno() {
		return mno;
	}
	public void setMno(int mno) {
		this.mno = mno;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getGenre() {
		return genre;
	}
	public void setGenre(String genre) {
		this.genre = genre;
	}
	public String getPoster() {
		return poster;
	}
	public void setPoster(String poster) {
		this.poster = poster;
	}
	public String getActor() {
		return actor;
	}
	public void setActor(String actor) {
		this.actor = actor;
	}
	public String getRegdate() {
		return regdate;
	}
	public void setRegdate(String regdate) {
		this.regdate = regdate;
	}
	public String getGrade() {
		return grade;
	}
	public void setGrade(String grade) {
		this.grade = grade;
	}
	public String getDirector() {
		return director;
	}
	public void setDirector(String director) {
		this.director = director;
	}

 VO를 다 만들어 줬으면 이걸 토대로 DAO파일을 만들어 준다. 

 

package com.sist.dao;
import java.util.*; // Collect Data and send to browser
import java.sql.*; // JDBC => connect to DataBase
public class MovieDAO {
		// 1. 데이터 베이스 연결 객체
	private Connection conn;
		// 2. 오라클이 실행하기 위해서는 SQL문장을 전송
	private PreparedStatement ps; // PL/SQL - CallableStatement (함수호출)
		// 3. 오라클 주소 설정
	private final String URL="jdbc:oracle:thin:@localhost:1521:XE";
		// 4. 연결하기 위한 드라이버 설치
	public MovieDAO()
	{
		try
		{
			Class.forName("oracle.jdbc.driver.OracleDriver");
		}
		catch (Exception e) {
			
		}
	}
		// 5. 오라클 연결 conn hr/happy
	public void getConnection()
	{
		try 
		{
			conn=DriverManager.getConnection(URL, "hr", "happy");
		} 
		catch (Exception e) {
			
		}
	}
		// 6. 오라클 종료 exit
	public void disConnection()
	{
		try
		{
			if(ps!=null) ps.close();
			if(conn!=null) conn.close();
		}
		catch (Exception e)
		{
			
		}
	}
	// 오라클 연결시 필수 사항
	// 영화와 관련된 SQL문장 전송 => 데이터를 받는다 
	// 1. 영화 목록 출력 => 1페이지 20개를 출력 1개당 MovieVO에 저장 => ArrayList<MovieVO>
	public ArrayList<MovieVO> movieListData(int page) // 매개변수 => page는 사용자 전송
	{
		ArrayList<MovieVO> list = new ArrayList<MovieVO>(); // list=> MovieVO를 20개를 채운다
		try
		{
			// 1. 연결
			getConnection();
			// 2. sql문장
			String sql="SELECT mno, title, poster, director,num "
					+"FROM (SELECT mno, title, poster, director, rownum as num "
					+"FROM (SELECT mno, title, poster, director "
					+"FROM movie ORDER BY mno ASC))"
					+"WHERE num BETWEEN ? AND ?"; // 인라인뷰 => 페이징 기법
			ps=conn.prepareStatement(sql);
			// 2-1. ?에 값을 채운다
			int rowSize=20;
			int start=(page*rowSize)-(rowSize-1);
			int end=(page*rowSize);
			
			ps.setInt(1, start);
			ps.setInt(2, end);
			/*
			 * 	1page => 1~20 1*20 -19 => 1
			 * 	rownum은 1번부터 시작한다
			 */
			// 3. sql문장 실행 요청
			// 4. 결과값을 받아온다
			// 결과값은 메모리에 저장 => ResultSet
			ResultSet rs=ps.executeQuery(); // executeUpdate()=>COMMIT이 첨부되어 있음
			// SELECT => 결과값을 읽어온다 = executeQuery(), INSERT, UPDATE, DELETE=> 실행 (COMMIT)
			// 5. 결과값을 MovieVO에 설정 => ArrayList에 저장
			while(rs.next())
			{
				MovieVO vo=new MovieVO(); // 20개를 메모리에 따로 저장
				vo.setMno(rs.getInt(1));
				vo.setTitle(rs.getString(2));
				vo.setPoster(rs.getString(3));
				vo.setDirector(rs.getString(4));
				list.add(vo); // list=>20개의 VO가 저장된다
			}
			rs.close();
		} 
		catch (Exception ex) {
			// error print
			System.out.println(ex.getMessage());
		}
		finally
		{
			// 종료
			disConnection();
		}
		return list;
	}
	// 1-1. 총페이지 구한다
	public int movieTotalPage()
	{
		int total=0;
		try
		{
			// 1. 연결
			getConnection();
			// 2. SQL문장
			String sql="SELECT CEIL(COUNT(*)/20.0)"
					+ "FROM movie"; // 올림 함수 1938/20.0 나머지는 올려줌
			// 3. SQL문장 실행 요청
			ps=conn.prepareStatement(sql);
			ResultSet rs=ps.executeQuery();
			rs.next(); // 데이터 출력위치에 커서 변경
			// 4. 결과값을 받는다 
			total=rs.getInt(1);
			rs.close();
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		finally
		{
			// 닫기
			disConnection();
		}
		return total;
	}
	// 2. 상세보기
	public MovieVO movieDetailData(int mno)
	{
		MovieVO vo=new MovieVO();
		try 
		{
			// 1. 연결
			getConnection();
			// 2. sql문장 제작
			String sql="SELECT mno, poster, title, director,"
					+ "grade, genre, actor, regdate "
					+"FROM movie "
					+"WHERE mno=?";
			ps=conn.prepareStatement(sql);
			// 2-1. ?에 값을 채운다
			ps.setInt(1, mno);
			// 3. sql문장 실행 요청
			ResultSet rs=ps.executeQuery();
			// 4. 결과값을 MovieVO에 채워준다
			rs.next();
			vo.setMno(rs.getInt(1));
			vo.setPoster(rs.getString(2));
			vo.setTitle(rs.getString(3));
			vo.setDirector(rs.getString(4));
			vo.setGrade(rs.getString(5));
			vo.setGenre(rs.getString(6));
			vo.setActor(rs.getString(7));
			vo.setRegdate(rs.getString(8));
			rs.close();
		} 
		catch (Exception ex) {
			// 오류 점검
			System.out.println(ex.getMessage());
		}
		finally
		{
			disConnection();
		}
		return vo;
	}
	 
}

 이제 어떤 sql문장을 써서 보내야 할지는 감이 잡히는거 같다. 그리고 getConnection(), disConnection()도 사용이 꽤 익숙해졌다. 반복의 힘은 역시 중요한거 같다. 사실 여기까지 이해했으면 웹에다가 실제로 뿌려주는건 그렇게 어렵진 않았다. 

 

그래도 다른 버전으로 연습을 해봐야 진짜 내가 이해한거다 생각이 들것 같아서 주말을 이용해서 다른 데이터로 비슷한 파일을 만들어 보려고 한다. 

 

 

이렇게 먼저 VO, DAO 파일을 만들어 줬으면 그 다음에는 SERVLET파일을 만들어서 웹에 뿌려주는 연습을 했다.

Servlet이라는 파일은 자바에서 바로 웹으로 뿌려줄수 있게 만드는 파일이라고 한다. 

 

package com.sist.main;

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import com.sist.dao.*; // 오라클 연결 => 데이터를 가지고 온다

@WebServlet("/MovieListServlet")
public class MovieListServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// request : 사용자가 보내준 데이터를 받는 경우 => BufferedReader
		// response : 처리결과를 브라우저로 전송 => OutputStream
		
		// 1. 전송 => 형식 (브라우저에서 실행 => HTML, XML)
		response.setContentType("text/html;charset=EUC-KR");
		// 브라우저로 전송하는데 html을 보낸다 (단 한글이 있다) => euc-kr (대소문자 구분이 없다)
		// xml로 전송 => text/xml, json => text/plain => AJAX (JavaScropt and XML) / 실시간 - 화면 변경이 없다
		
		// 2. 누구에게 보내는지 설정 
		PrintWriter out=response.getWriter(); 
		
		// 서버에 요청한 유저의 메모리 위치 
		String page=request.getParameter("page");
		if(page==null)
			page="1";
		// 1. 현재 페이지
		int curpage=Integer.parseInt(page);
		MovieDAO dao=new MovieDAO();
		// 2. 총페이지
		int totalpage=dao.movieTotalPage();
		// 3. 영화정보 20개 => ArrayList 
		ArrayList<MovieVO> list=dao.movieListData(curpage);
		out.write("<html>");
		out.write("<head>");
		out.write("<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css\">");
		out.write("</head>");
		out.write("<body>");
		out.write("<div class=container>");
		out.write("<div class=row style=\"margin:0px auto;width:800px\">");
		out.write("<center>");
		out.write("<h1>영화 목록</h1>");
		out.write("<table class=\"table table-hover\">"); //class, id => css
		out.write("<th>번호</th>");
		out.write("<th></th>");
		out.write("<th>영화명</th>");
		out.write("<th>감독명</th>");
		
		for(MovieVO vo:list) // 실제 데이터 출력
		{
			out.write("<tr>");
			out.write("<td>"+vo.getMno()+"</td>");
			out.write("<td align=center><img src="+vo.getPoster()+" width=30 height=30 </td>");
			out.write("<td><a href=MovieDetailServlet?mno="+vo.getMno()+">"+vo.getTitle()+"</a></td>");
			// web에서는 다른 클래스에 값을 전송시에 ?뒤에 값을 설정해서 보낸다
			/*
			 * ?뒤에 붙여서 전송하는 방법 ====> GET
			 * 숨겨서 보내는 방법 (ID, PWD) ===> POST
			 */
			out.write("<td>"+vo.getDirector()+"</td>");
			out.write("</tr>");
		}
		out.write("<tr>");
		out.write("<td colspan=4 align=center>");
		out.write("<a href=MovieListServlet?page="+(curpage>1?curpage-1:curpage)+">이전</a>&nbsp;");
		out.write(curpage+" page / "+totalpage+" page&nbsp;");
		out.write("<a href=MovieListServlet?page="+(curpage<totalpage?curpage+1:curpage)+">다음</a>");
		out.write("</td>");
		out.write("</tr>");
		
		out.write("</table>");
		out.write("</div>");
		out.write("</div>");
		out.write("</center>");
		out.write("</body>");
		out.write("</html>");
	}

}

 솔직히 이렇게 쓰면 조금 헷갈리긴 헸는데, 그래도 for문을 써서 데이터를 한번에 쫙 뿌려준다는게 좀 혁명적으로 느껴졌다. 현재 페이지와 마지막 페이지를 구해서 연결이 되도록하는 코딩도 재미있었다. 

 

 아무래도 코딩을 처음 접한 언어 자체가 JavaScript였기 때문에 프론트에 익숙해서 백엔드가 어떤 역할인지, 또 무슨 재미인지 잘 몰랐는데 이번에 재미를 좀 느낀거 같다

 아 이런게 백앤드가 하는 역할이구나를 알게 되어서 좀 흥미로웠던거 같다. 

 

어차피 이번 코딩은 주말에 한 번 더 해볼거기 때문에 일단은 한번 눈으로 짚어보고 이해안되는 부분만 더 자세히 복습하고 넘어가도록 하겠다. 

 

 위의 코딩은 메인페이지에 뿌려주는 전체 리스트 코딩이고, 다음은 상세보기 페이지 코딩이다. 

 

package com.sist.main;

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import com.sist.dao.*; // 오라클 연결 => 데이터를 가지고 온다

@WebServlet("/MovieListServlet")
public class MovieListServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// request : 사용자가 보내준 데이터를 받는 경우 => BufferedReader
		// response : 처리결과를 브라우저로 전송 => OutputStream
		
		// 1. 전송 => 형식 (브라우저에서 실행 => HTML, XML)
		response.setContentType("text/html;charset=EUC-KR");
		// 브라우저로 전송하는데 html을 보낸다 (단 한글이 있다) => euc-kr (대소문자 구분이 없다)
		// xml로 전송 => text/xml, json => text/plain => AJAX (JavaScropt and XML) / 실시간 - 화면 변경이 없다
		
		// 2. 누구에게 보내는지 설정 
		PrintWriter out=response.getWriter(); 
		
		// 서버에 요청한 유저의 메모리 위치 
		String page=request.getParameter("page");
		if(page==null)
			page="1";
		// 1. 현재 페이지
		int curpage=Integer.parseInt(page);
		MovieDAO dao=new MovieDAO();
		// 2. 총페이지
		int totalpage=dao.movieTotalPage();
		// 3. 영화정보 20개 => ArrayList 
		ArrayList<MovieVO> list=dao.movieListData(curpage);
		out.write("<html>");
		out.write("<head>");
		out.write("<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css\">");
		out.write("</head>");
		out.write("<body>");
		out.write("<div class=container>");
		out.write("<div class=row style=\"margin:0px auto;width:800px\">");
		out.write("<center>");
		out.write("<h1>영화 목록</h1>");
		out.write("<table class=\"table table-hover\">"); //class, id => css
		out.write("<th>번호</th>");
		out.write("<th></th>");
		out.write("<th>영화명</th>");
		out.write("<th>감독명</th>");
		
		for(MovieVO vo:list) // 실제 데이터 출력
		{
			out.write("<tr>");
			out.write("<td>"+vo.getMno()+"</td>");
			out.write("<td align=center><img src="+vo.getPoster()+" width=30 height=30 </td>");
			out.write("<td><a href=MovieDetailServlet?mno="+vo.getMno()+">"+vo.getTitle()+"</a></td>");
			// web에서는 다른 클래스에 값을 전송시에 ?뒤에 값을 설정해서 보낸다
			/*
			 * ?뒤에 붙여서 전송하는 방법 ====> GET
			 * 숨겨서 보내는 방법 (ID, PWD) ===> POST
			 */
			out.write("<td>"+vo.getDirector()+"</td>");
			out.write("</tr>");
		}
		out.write("<tr>");
		out.write("<td colspan=4 align=center>");
		out.write("<a href=MovieListServlet?page="+(curpage>1?curpage-1:curpage)+">이전</a>&nbsp;");
		out.write(curpage+" page / "+totalpage+" page&nbsp;");
		out.write("<a href=MovieListServlet?page="+(curpage<totalpage?curpage+1:curpage)+">다음</a>");
		out.write("</td>");
		out.write("</tr>");
		
		out.write("</table>");
		out.write("</div>");
		out.write("</div>");
		out.write("</center>");
		out.write("</body>");
		out.write("</html>");	
	}

}

 근데 보다보니까 페이지를 지정해주는 부분이 이해가 안가는거 같다. 

 

// 서버에 요청한 유저의 메모리 위치 
		String page=request.getParameter("page");
		if(page==null)
			page="1";
		// 1. 현재 페이지
		int curpage=Integer.parseInt(page);

 여기서 그러면 DAO에 있는 page값을 가져온다는거 같은데

public ArrayList<MovieVO> movieListData(int page) // 매개변수 => page는 사용자 전송
	{
		ArrayList<MovieVO> list = new ArrayList<MovieVO>(); // list=> MovieVO를 20개를 채운다
		try
		{
			// 1. 연결
			getConnection();
			// 2. sql문장
			String sql="SELECT mno, title, poster, director,num "
					+"FROM (SELECT mno, title, poster, director, rownum as num "
					+"FROM (SELECT mno, title, poster, director "
					+"FROM movie ORDER BY mno ASC))"
					+"WHERE num BETWEEN ? AND ?"; // 인라인뷰 => 페이징 기법
			ps=conn.prepareStatement(sql);
			// 2-1. ?에 값을 채운다
			int rowSize=20;
			int start=(page*rowSize)-(rowSize-1);
			int end=(page*rowSize);

 여기는 또 page는 사용자 전송이라고 한다. 페이지 관련 매개변수와 그 처리 부분이 조금 잘 이해가 안간다.

이거는 강사님께 한번 여쭤봐야 할것 같다. 

 

 여튼 이 부분을 제외하고는 대충 이해가 가는거 같긴하다. 

 

 

오후에는 다시 HTML을 배웠다. Input태그 여러개와 속성을 배웠다. 이거는 웹에다가 바로바로 띄워서 확인하며 공부할 수 있어서 조금 수월했던거 같다. 

 

<!-- 
	입력관련 태그
	=> 로그인, 회원가입, 글쓰기 ...
	형식)
		<input type="">
				1. type="text"
					한줄 문자열 
				2. type="password"
					한줄 => 비밀번호입력
				3. type="button"
					= button : 기능이 없다
							   (자바스크립트 이용)
					= submit : 입력된 모든 데이터 전송
								지정된 파일로 전송
					= reset : 초기화 (입력값 모두 지울 경우)
				4. toggle button
					============
						= radio
						= checkbox
				5. hidden : 사용자에게 데이터를 보여주지 않을 경우
					게시판 : 수정, 삭제 (게시물 번호를 숨겨서 처리)
				======================================= HTML
				6. 날짜 출력 (IE(x), 크롬, FF) : date
				7. updown(숫자만 출력) => number
				8. range
				======================================= HTML
				9. file : 파일 업로드시 
				10. image => 버튼 (submit)
		= 여러줄 입력
		<textarea> : 소개, 글쓰기 내용 ...
		
		= 목록에서 선택이 가능
			<select> : 콤보박스
 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
	ID:<input type="text" size=10><br>
	PW:<input type="password" size=15><br>
	성별:<input type="radio" name="sex">여자
		<input type="radio" name="sex">여자 <br><!-- 그룹 (name속성) -->
	취미:<input type="checkbox" name="hobby">복싱
		<input type="checkbox" name="hobby">여행
		<input type="checkbox" name="hobby">독서<br>
	업로드: <input type="file"><br><!-- 자료실, 카페, 블로그 -->
	숨김:<input type="hidden" value=admin><br>
	버튼:<input type="button" value="로그인">
		<input type="submit" value="회원가입">
		<input type="reset" value="취소"><br>
	날짜:<input type="date"><br>
	숫자입력:<input type="number" min=1 max="100" value="50"><br>
			<!-- 장바구니, 주문갯수 -->
	
	Range: <input type="range" min="1" max="100"><br>
	image: <input type="image" src="KakaoTalk_20201117_184530963_09.jpg"><!-- 버튼 (submit) -->
	<br>
	<button>글쓰기</button>
	내용 : <textarea rows="10" cols="60"></textarea>
	
</body>
</html>

 이미 수업시간에 많이 연습해봐서 복습을 빡세게 하진 않아도 될 것 같다.

 

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<style type="text/css">
td{
    font-size: 9pt;
    font-family: 맑은 고딕;
}
</style>
</head>
<body>
  <center>
    <h3>회원가입</h3>
    <table border=1 bordercolor=black width=500 
      cellspacing=0 cellpadding=0>
      <tr>
        <td>
          <table border=0 width=500>
           <tr>
            <td width=20% align=right>ID</td>
            <td width=80%>
              <input type=text name=id size=15 readonly="readonly">
              <input type=button value="중복확인">
            </td> <!-- align(정렬) : left -->
           </tr>
           
           <tr>
            <td width=20% align=right>비밀번호</td>
            <td width=80%>
              <input type=password name=pwd1 size=15>
              &nbsp;재입력&nbsp;<input type=password name=pwd2 size=15>
            </td> <!-- align(정렬) : left -->
           </tr>
           
           <tr>
            <td width=20% align=right>이름</td>
            <td width=80%>
              <input type=text name=name size=15>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>성별</td>
            <td width=80%>
              <label><input type=radio name=sex checked="checked">남자</label>
              <label><input type=radio name=sex>여자</label>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>생년월일</td>
            <td width=80%>
              <input type=date name="birthday" size=25>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>우편번호</td>
            <td width=80%>
              <input type=text size=5 readonly="readonly">-<input type=text size=5 readonly="readonly">
              <input type=button value="우편번호검색">
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>주소</td>
            <td width=80%>
              <input type=text name="addr1" size=50 readonly="readonly">
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>상세주소</td>
            <td width=80%>
              <input type=text name="addr2" size=50>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>전화번호</td>
            <td width=80%>
              <select>
                <option>010</option>
                <option>011</option>
                <option>017</option>
              </select>
              <input type=text name=tel1 size=7>-<input type=text name=tel2 size=7>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>소개</td>
            <td width=80%>
              <textarea rows="10" cols="50" name=content></textarea>
            </td>
           </tr>
           
           <tr>
            <td width=20% align=right>취미</td>
            <td width=80%>
              <label><input type=checkbox name=hobby>등산</label>
              <label><input type=checkbox name=hobby>게임</label>
              <label><input type=checkbox name=hobby>낚시</label>
              <label><input type=checkbox name=hobby>운동</label>
              <label><input type=checkbox name=hobby>여행</label>
            </td>
           </tr>
           
           <tr>
             <td colspan="2" align="center">
               <input type=submit value="회원가입">
               <input type=reset value="취소">
             </td>
           </tr>
          </table>
        </td>
      </tr>  
    </table>
  </center>
</body>
</html>

 수업시간에 배운 html을 전부 활용해서 만들어본 회원가입창이다. 

확실히 이걸 하면서 느낀게 프론트보다 백이 더 재밌는거 같기도하다... 

 

일단 더 해봐야 알겠지만

728x90
반응형