배움 __IL/TIL 1기

TIL : 49번째- 230213 [2-2-월]

Mo_bi!e 2023. 2. 13. 21:08

I. 지난시간 정리

1. 웹 개발 관련

1)

자바는 웹개발과 다른게 없다. 입출력만 다르게 하면된다.

역사적으로 서버는 페이지 만들어주는 것임 (동적인 페이지를 만들어주는)

웹서버 에다가 프로그래밍이 붙은 것이다.

 

2)

웹서버라는 것이 문서를 주는 것임

프로그램을 실행해서 얘가 만든 문서를 불러와 주는 것, 즉 실행 전에는 문서가 없음 (동적문서)

동적이라 함은 요청할 때 실행할 때를 동적이라고 한다

메모리가 실행할 때 만들어지면 동적 메모리 / 메뉴도 실행? (동적 메뉴) / 페이지 실행(동적 페이지)

 

동적 문서 만들 때 에는 out.write()로 다 만들지 않음

출력은 IO작업인데, 오래걸리는 작업인데, DB연결을 함 -> 이거 문제임

데이터 가져오는 코드, 출력코드가 섞여있음

화면 고칠 때와 출력 고치는 경우 모두 전체를 봐야해서 지역화된 코드블럭이 없어서 찾기도, 해결도 어렵다

 

3)

코드를 문서출력데이터 서비스 부분을 나누는 것이 필요함

그래서 위는 문서출력 / 아래는 데이터 가져오기로 지난시간에 했음

 

우리는 메모리 CPU 작업은 빠르나, IO는 느린데,

그래서 연산 먼저하고 출력 나중에 하는게 바람직하다

 

4)

또 다른 방법은 코드 출력 하는 것은 고능력보다는 누군가에게 맡기기가 가능한데

이 부분만 잘라서 별도의 파일을 만들 수있다.

출력담당 하는 코드만 만들어줘 (누군가가!) / 하면 나는 제어만 하면된다.

 

5)

우측 출력담당 영역을 VIEW영역이라고 한다 / 좌측 controller 는 사용자와 직접적으로 조작 영역이다

이렇게 나누면 좋긴한데, 좌측 결과를 우측에 주어야한다.

 

이렇게 좌측 결과물을 우리는 모델이라고 한다.

 

이 3가지 요소를 만드는것이 트렌드이다.

MVC 라고한다.

 

 

6)

이러면 어떻게 model 이 전달하느냐이다

하나는 리디렉션/ 포워딩 이다

이거에 대해서 해보자

 

II. 웹개발 

1. Redirecting와 Forwarding

(1) 리다이렉팅

<ListController2.java>

package com.newlecture.web.controller.menu;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.newlecture.web.entity.Menu;
import com.newlecture.web.service.MenuService;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/menu/list2")
public class ListController2 extends HttpServlet{
	
	private MenuService service;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		NList menus = new NList();
//		GList<Menu> menus = new GList<>(); // 이런 형식의 콜렉션 만들어달라 부탁한 것
		List<Menu> menus = new ArrayList<>();
		
//		resp.setCharacterEncoding("UTF-8"); 
//		resp.setContentType("text/txt; charset=utf-8");
		resp.setContentType("text/html; charset=utf-8");
		
		PrintWriter out = resp.getWriter();
		
		out.print("hello");
		
		String query = "";
		String sql = String.format("select * from member where nicname like '%s'", "%"+query+"%") ;
		
		try {
			// java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
			Class.forName("oracle.jdbc.driver.OracleDriver");
			String url = "jdbc:oracle:thin:@oracle.newlecture.com:1521/xepdb1";
			Connection con = DriverManager.getConnection(url, "NEWLEC", "rland");
			
			Statement st = con.createStatement();
			ResultSet rs = st.executeQuery(sql);
			
//			Menu[] menus = new Menu[100];
			
//			List<Menu> list = new ArrayList<>();
			
			
					
			// 필터링, 집계, 정렬
			while(rs.next())	// 서버의 커서를 한칸 내리고 그 위치의 레코드를 옮겨 오는 것. -> 레코드 하나가 저장되는 공간은?
			{
				
				int id = rs.getInt("id");
				String name = rs.getString("name");
				String nicName = rs.getString("nicname");

				Menu menu = new Menu(id, name, 1000, "");
				
				menus.add(menu);
				
			}
			
			con.close();
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		resp.sendRedirect("listview");
		
//		======================================================
		
//		out.write("<!DOCTYPE html>");
//		out.write("<html>");
//		out.write("<head>");
//		out.write("<meta charset=\"UTF-8\">");
//		out.write("<title>Insert title here</title>");
//		out.write("</head>");
//		out.write("<body>");
//		out.write("<h1>메뉴 목록</h1>");
//		out.write("<table>");
//		out.write("<tr>");
//		out.write("<td>번호</td>");
//		out.write("<td>이름</td>");
//		out.write("<td>가격</td>		");	
//		out.write("</tr>");
//		
//		for(int i=0; i<menus.size(); i++) {
////			Menu m = (Menu) menus.get(i);
//			Menu m = menus.get(i); 
//			out.write("<tr>");
//			out.write("<td>"+m.getId()+"</td>");
//			out.write("<td>"+m.getName()+"</td>");
//			out.write("<td>5000</td>	");		
//			out.write("</tr>");
//		}
//		
//		out.write("</table>");
//		out.write("</body>");
//		out.write("</html>");
	}
}

<ListView.java>

package com.newlecture.web.controller.menu;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.newlecture.web.entity.Menu;
import com.newlecture.web.service.MenuService;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/menu/listview")
public class ListView extends HttpServlet{
	
	private MenuService service;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html; charset=utf-8");
		
		PrintWriter out = resp.getWriter();
		
//		======================================================
		
		out.write("<!DOCTYPE html>");
		out.write("<html>");
		out.write("<head>");
		out.write("<meta charset=\"UTF-8\">");
		out.write("<title>Insert title here</title>");
		out.write("</head>");
		out.write("<body>");
		out.write("<h1>메뉴 목록</h1>");
		out.write("<table>");
		out.write("<tr>");
		out.write("<td>번호</td>");
		out.write("<td>이름</td>");
		out.write("<td>가격</td>		");	
		out.write("</tr>");
		
//		for(int i=0; i<menus.size(); i++) {
//			Menu m = (Menu) menus.get(i);
//			Menu m = menus.get(i); 
			out.write("<tr>");
//			out.write("<td>"+m.getId()+"</td>");
//			out.write("<td>"+m.getName()+"</td>");
			out.write("<td>5000</td>	");		
			out.write("</tr>");
//		}
		
		out.write("</table>");
		out.write("</body>");
		out.write("</html>");
	}
}

1)

이거를 추가하기

resp.sendRedirect("listview");

이런방식으로 해서 listview에다가 줄 수있다.

 

2)

이것은 response 도구(출력도구)에 포함되어있다

왜 출력도구를 가지고, Redirection을 했을까? 두번째 서블릿을 직접호출하는 것이 아니다.

얘는 서블릿은 호출한 적이없다. 즉 응답만 해주었다 다른 곳으로 가라고

예컨데 동사무소에 등본 받으로 옴, 문서를 준것이 아니라 다른 부서로 가라고 응답하는 것이다.

 

코드를 보면 list2를 요청했는데 listview로 response 한다.

(list2 주소 : http://localhost:8080/webPrj/menu/list2) -> (listview 주소: http://localhost:8080/webPrj/menu/listview)

 

3)

서블릿은 사용자 요청이 오면 그때 메모리 올라가고, 리턴된다

이때 끝이난다. 응답을 하고 죽어버린다. 서블릿이 가진 메모리는 사라지는 것이다

 

 

(2) 포워딩

req
.getRequestDispatcher("listview")
.forward(req, resp);

forward 방법은 서버를 요청한다

나한테 다시 요청하라고 하는게 아니라, 걔가 결과물을 가지고 걔가 바로준다

 

디스패처는 내가 서블릿상 다른 요소를 요청할 때 디스패처라고한다.

프로그램은 자체적으로 request 등의 절차를 거친다.

 

(3) 정리

포워딩은 앞것과 달리 직접 실행한 결과를 알려준다

완전히 다른 것이다.

 

차이는 서버에서 서버로 요청하고, 결과를 돌려주는 것이다.

두개의 서블릿이 살아있는 것이다.

 

출력되는 내용이 이어 질 수있고, 입력값이 공유 될 수있다.

 

2. 리다이렉트와 포워딩

(1) 서버상 데이터 저장하기 위한 저장소

-서버는 저장소가 5가지이다.

세션, 쿠기, 쿼리스트링, 리퀘스팅, 피드필딩

 

<서버상 데이터 저장하기 위한 저장소 : JSP의 기본객체> 꼭 암기 

페이지저장소, 리퀘스트저장소, 세션저장소, 어플리케이션 저장소

 

page 저장소 : PageContext

request 저장소 : HttpServletRequest

session 저장소 : HttpSession

application 저장소 : ServletContext

4가지 저장소는 사용범위 따라 다르다

 

1) page

서블릿 한페이지 잠깐 저장하려면 배열이나 컬렉션 쓰면 되나, 얘들을 이용해도된다

 

2) request

두개 서블릿 사이 데이터 공유 원할 때 리퀘스트이다. 포워드 관계에서 주로 쓴다 (A->B로 포워딩)

 

3) session

한 사용자가 같으면 같은 사용자는 다 같은 공간을 쓸 수있음

 

4) application

모든 유저, 모든가 사용할수 있는 공간

 

 

(2) request

1)

포워딩 방법에서 setAttribute를 해준다

<ListController2>

	req.setAttribute("menus2", menus);


//		resp.sendRedirect("listview");
    req
    .getRequestDispatcher("listview")
    .forward(req, resp);

ListController2 에서 만든 menus객체를 만들어서 ListView로 setAttribute를 한다.

menus객체를 menus2 이름으로 ListView로 포워딩을 한다.

 

디스패처를 하면서 listview를 포워딩한다.

 

 

 

2)

<ListView>

public class ListView extends HttpServlet{
	
	private MenuService service;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html; charset=utf-8");
		
		PrintWriter out = resp.getWriter();
		
		List<Menu> menus = (List<Menu>) req.getAttribute("menus2");

getAttribute를 해서 menus2의 객체를 받는다.

이를 list클래스의 Menu타입의 menus 인스턴스에 캐스팅을 해준다.

 

3)

for(int i = 0; i < menus.size(); i++) {
    Menu m = menus.get(i);
    out.write("<tr>");
    out.write("<td>"+m.getId()+"</td>");
    out.write("<td>"+m.getName()+"</td>");
    out.write("<td>5000</td>	");		
    out.write("</tr>");
}

menus.get() 은 가변배열인 List에 특정 인덱스를 넣고, 해당 인덱스의 값을 Menu 타입의 참조변수 m 에 대입한다

m으로 getId() 와 getName()을 한다

 

 


1. 보충

(1) 리다이렉팅 / 포워딩 차이 (https://doublesprogramming.tistory.com/63)

 

<공통점>

1) JSP에서 현재 페이지에서 다른페이지로 전환하는 방식이다.

 

<차이점 : 리다이렉팅 VS 포워딩>

1)

URL1에 물어봄, URL1은 URL2에게 요청에 대해서 물어본 뒤에 URL1이 그 요청에 대해서 응답해 줌

이 경우 url은 고정 / req,resp 객체도 변화하지 않음

URL1에 물어봄(요청), URL1은 응답으로 URL2에 물어보라고 함

클라이언트는 다시 URL2에게 요청함

 

2)

What (정의) : redirect 와 forward  객체의 재사용 관점과 URL의 변화여부

  URL 변화 객체 재사용
redirect O X
request X O

 

Why (존재이유) :

redirect 방식 응답은 시스템(session, DB)에 변화가 생기기 때문에 로그인,글쓰기, 회원가입의 경우 쓰기 위해서이고,

forward 방식은 시스템에 변화가 없기 때문에 단순 조회나 검색을 위한 것이다

 

 

 

How (방법) :

resp.sendRedirect("listview");


req
.getRequestDispatcher("listview")
.forward(req, resp);

 

e.g. (예) : 

 

 

 

(2) getRequestDispatcher()

 

What (정의) : 페이지 전환시 forward 방식에서 이용되는 것으로서 dispatcher에게 특정한 처리를 요청하고 그 결과를 얻어오는 기능을 한다.

 

Why (존재이유) : redirection 은 페이지가 전환 될 때마다 객체와 url 이 변화하는 등으로 특정 상태를 유지하기가 어렵다. 쿠키, 세션으로도 가능할 수있으나, 이러한 점은 제한되기도하고, 코드의 알고리즘 유지에도 어려움이 있기 때문이다/

 

 

 

(3) setAttribute / getAttribute

 

What (정의) : JSP의 4가지 기본객체 혹은 서버상 데이터를 저장하기 위한 장소이다. 이러한 객체는 다음과 같은 메소드를 가진다.

Why (존재이유)  : JSP의 페이지 사이 정보를 주고받는 등 공유하기 위해서이고 특히 set,get은 페이지에 값을 줄 수있다.

How (방법) :

 

req.setAttribute("menus2", menus);


List<Menu> menus = (List<Menu>) req.getAttribute("menus2");
// req.getAttribute("menus2")의 리턴타입이 object이기 때문에
// 캐스팅이 가능하다

 

 

 

 

2. 회고 

1) 주말동안 내 마음을 불편하게 했던 것들이 일련의 질문과 추가공부로 해결이 되어서 속이 시원하다 다행이다

 

 

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 51번째- 230215 [2-2-수]  (0) 2023.02.15
TIL : 50번째- 230214 [2-2-화]  (0) 2023.02.14
TIL : 47번째- 230208 [2-1-수]  (0) 2023.02.08
TIL : 46번째- 230207 [2-1-화]  (0) 2023.02.07
TIL : 45번째- 230206 [2-1-월]  (1) 2023.02.06