스프링3(http프로토콜)

손원진·2023년 2월 13일
0

[SPRING]

목록 보기
5/15

전통적인 서버 클라이언트 구조

특징
서버에서 데이터를 처리 -> 자료 중복 및 자료 불일치 문제 해결

문제점

  • 애플리케이션 변경 시 재배포 필요

애플리케이션 서버 도입

특징

비즈니스 로직을 전문으로 처리하는 서버를 둠 -> 애플리케이션서버
클라이언트 실행 결과 출력만을 담당 -> 씬 클라이언트(thin client)가능
애플리케이션 서버에서 DBMS 접근 -> 보안 강화
기능 추가 또는 변경 시에 서버쪽만 변경 -> 배포가 쉬움

서버에서 데이터를 처리하고 비즈니스 로직을 처리하고 UI를 생성

특징 * 웹 표준 기술을 활용하여 클라이언트와 서버간 통신

  • 클라이언트 애플리케이션을 배포할 필요 없음
  • 소켓 프로그래밍과 멀티 스레드 프로그래밍에서 탈출
  • 리눅스, 멕킨토시, 윈도우등 어떤 클라이언트 서버간에 운영체계가 달라도 HTTP프로토콜만 있으면 통신이 가능해진다.

웹 애플리케이션 구조

기존에 Socket프로그래밍, thread프로그래밍에서 진행하는 일을 웹서버가 대신 처리해주고 웹 어플리케이션은 계산기 프로그램을 예로들때 계산만 진행하는 역할을 한다. 대신 http프로토콜이 해석할 수 있도록 값을 전달해야한다.

직접 생성 html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>계산기</h1>
<form action="calc" method="post">
<input type="text" name="v1" style="width: 50px;">
<select name="op">
	<option value="+">+</option>
	<option value="-">-</option>
	<option value="*">*</option>
	<option value="/">/</option>
	<option value="%">%</option>
</select>
<input type="text" name="v2" style="width: 50px;">
<input type="submit" value="=">
</form>
</body>
</html>

Servlet

package lesson01.servlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

@WebServlet("/calc")
@SuppressWarnings("serial")
public class CalculatorServlet extends GenericServlet {

	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
    
		String operator = request.getParameter("op");
		int v1 = Integer.parseInt(request.getParameter("v1"));
		int v2 = Integer.parseInt(request.getParameter("v2"));
		int result = 0;

		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();

		switch (operator) {
        
		case "+":
			result = v1 + v2;
			break;
		case "-":
			result = v1 - v2;
			break;
		case "*":
			result = v1 * v2;
			break;
		case "/":
			if (v2 == 0) {
				out.println("0 으로 나눌 수 없습니다!");
				return;
			}

			result = v1 / v2;
			break;
		case "%":
			result = v1 % v2;
			break;
		}

		out.println(v1 + " " + operator + " " + v2 + " = " + result);
	}

}

위처럼 서버에 애플리케이션 배포 및 실행하기에 기능변경 및 추가가 용이합니다.

웹애플리케이션 서버는 클라이언트로 부터 요청을 받으면 업무 로직에 따라 DBMS서버를 사용하여 데이터를 처러, 클라이언트의 접근을 제어하며 무효한 접근을 차단, 함께처리할 작업이 있으면 트렌젝션* 으로 묶어서 처리함

HTTP 프로토콜의 이해

HTTP는 무엇이고 웹서버와 웹 브라우저가 어떤형식으로 데이터를 주고받을까?

HTTP프로토콜이란?

웹 브라우저와 웹서버 사이에 데이터를 주고받는 규칙, 웹 브라우저에 통신에 따라서 웹서버가 응답을 해줌

데이터의 방식

웹 브라우저와 웹서버가 사용하는 통신의 종류
둘사이에 통신을 감시하는 모니터링 프로그램을 HTTP프록시라고 합니다.

HTTP프록시를 사용하여 둘사이 주고 받는 데이터를 직접 알아보기.

proxy를 두는이유 - 클라이언트와 서버사이에 통신을 중계해주는 프로그램을 말합니다. 빠른 전송을 위해 응답결과를 캐시에 저장해두고, 외부서버에서 데이터를 꺼내는 것이 아닌 캐시에서 바로 저장된 정보를 전달하기 떼문에 클라이언트는 빠른 응답을 받을 수 있습니다.

외부로 전달되는 데이터를 검사하여 특정 단어가 포함된 자료의 송수신을 차단할 수 있습니다.

www.charlesproxy.com을 사용하여 직접 설치

프록시를 사용하여 http프로토콜로 접근했을 때 서버의 요청 정보와 응답정보를 받을 수 있다.

자바프로그램을 이용해서 웹서버가 정말 응답을 하는지 알아보자


package lesson02.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class SimpleHttpClient {

	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("www.hani.co.kr", 80);
		BufferedReader in = new BufferedReader(
				new InputStreamReader(socket.getInputStream()));
		PrintStream out = new PrintStream(
				socket.getOutputStream());

		//1. 요청라인
		out.println("GET / HTTP/1.1");

		//2. 헤더정보
		out.println("Host: www.hani.co.kr");
		out.println("User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0)"
				+ " AppleWebKit/537.36 (KHTML, like Gecko)"
				+ " Chrome/30.0.1599.101 Safari/537.36");
		//3. 공백라인
		out.println();

		String line = null;
		while((line = in.readLine()) != null) {
			System.out.println(line);
		}

		in.close();
		out.close();
		socket.close();
	}

}

웹서버에 기본 포트번호는 80이기 때문에 80포트번호를 적고, 주소를 적는다.
그리고 서버에게 수행할 작업을 알려주는 요청라인을 보냅니다. 요청형식은 get, 원하는 자원은 서버루트 폴더에 있는 기본문서 / 사용할 프로토콜은 http 버전은 1.1입니다.

이렇게 첫번 째 라인에서는 응답상태 정보 두번째라인부터 공백라인 전까지에 헤더등 공백라인 다음에는 html로된 본문데이터가 옵니다. 이렇게 통신규약에 맞추어 데이터를 보내고 받는다면 누구든지 해당 프로토콜의 클라이언트나 서버를 만들 수 있습니다. (반복문을 만들고 요청을 계속해서 보내는 것이 바로 d-doss공격 서버를 정신 못차리게 하는 것)

Get 요청

get요청으로 하면 parameter이름과 =값으로 나오게된다.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
	"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lesson 2 - GET 메서드</title>
</head>
<body>

<h3>GET 요청 1: 웹 브라우저의 주소창에 주소를 입력 후 실행할 때</h3>

<h3>GET 요청 2: 링크를 클릭할 때</h3>
<p>
<a href="http://www.google.com">구글</a><br>
<a href="http://www.facebook.com">페이스북</a><br>
</p>

<h3>GET 요청 3: 입력폼의 method 속성을 GET으로 지정했을 때</h3>
<form action="CalculatorServlet" method="get">
	<input type="text" name="v1" size="4"> 
	<select name="op">
		<option value="+">+</option>
		<option value="-">-</option>
		<option value="*">*</option>
		<option value="/">/</option>
	</select> 
	<input type="text" name="v2" size="4"> 
	<input type="submit" value="="><br>
</form> 
</body>
</html>

method를 get요청으로 전달했을 때 http프로토콜에서 입력 창이 proxy를 통해서 나오는 것을 확인해 봤습니다. get요청의 특징은 다음과 같습니다.

검색할 때 검색결과를 알려줄 때 url을 보내주면 바로 상대방이 조회가 가능하다.

post요청

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
	"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>POST 요청</title>
</head>
<body>

<h3>POST 요청 1 - 로그인 폼</h3>
<p>
로그인 폼은 입력값 노출을 방지하기 위해 POST를 사용해야 한다.
</p>
<form action="LoginServlet" method="post">
아이디: <input type="text" name="id"><br>
암호: <input type="password" name="password"><br>
<input type="submit" value="로그인">
</form>
 
<h3>POST 요청 2 - 계산기</h3>
<p>
URL에 값이 포함되지 않아서 즐겨 찾기에 추가해도 소용없다.
</p>
<form action="CalculatorServlet" method="post">
	<input type="text" name="v1" size="4"> 
	<select name="op">
		<option value="+">+</option>
		<option value="-">-</option>
		<option value="*">*</option>
		<option value="/">/</option>
	</select> 
	<input type="text" name="v2" size="4"> 
	<input type="submit" value="="><br>
</form> 
</body>
</html>	

post로 지정을해서 프로토콜에서 데이터를 요청하게되면

url에 데이터를 실어서 보내는 것이 아니라 헤더 맨 끝에 데이터를 실어서 보내게됩니다. get방식은 서버에 요청할 때 주소에 데이터 정보가 포함되어있어 상대방에게 url을 전달했을 때 전달한 데이터 그대로의 웹정보가 나오게됩니다.

post 방식 대용량 데이터를 보낼 수 있습니다. (요청라인)url로 데이터를 보내는 것은 요청 정보의 양이 제한되어있지만, 한칸 띄고 보내는 post의데이터 방식은 대용량 데이터를 보내는 것이 가능합니다(메시지본문)라인에 데이터가 나오게됨(http)-프로토콜에 데이터 응답, 요청 방식.

중요.

get메서드와 마찬가지로 post도 데이터를 전달할 때 이름= 값 & 이름 =값 형태를 사용합니다 문자데이터를 보낼 떄는 문제없지만, 이미지나 동영상과 같은 데이터를 보낼 때는 문제가 발생할 수 있습니다. 바이너리 데이터 안에 =이나 & 같은 문자를 포함하고 있을 수 있기 때문입니다.

서버는 &문자로 매개변수를 구분하고 = 문자로 매개변수의 이름과 값을 분리하기 때문에, 만약 이미지데이터에 이런 문자 코드 값을 포함하고 있다면 잘못 해석될 수 있습니다.

파일 업로드

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
	"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일 업로드</title>
</head>
<body>

<h3>파일 업로드 POST 요청: Multipart 인코딩</h3>
<p>
입력폼의 method를 POST으로 지정하고,<br>
enctype 속성의 값을 multipart/form-data로 설정합니다.
</p>
<form action="FileUploadServlet" method="post"
		enctype="multipart/form-data">
사진: <input type="file" name="photo"><br> 
설명: <textarea name="description" cols="50" rows="3"></textarea><br>
<input type="submit" value="추가"><br>
</form> 
</body>
</html>

보면 post타입은 맞는데 encodingType(enctype를) multipart/form-data형식으로 보냅니다.

확인해보면 form-data가 boundary 로 되어있는데 구분자를 ----기준으로 둔 것이고,
아래 확인해보면 form데이터의 이름과 파일 이름을 확인할 수 있습니다. 그아래에는 컨텐츠 타입을 알 수 있고, 한칸띄고 아래부분엔

파일의 데이터값을 확인 할 수 있습니다.

여기서 이해해야하는 부분은 get방식과 post방식은 http프로토콜로 서버에 보내고 받을 때 어떻게 다를까를 이해하는 것이 중요합니다.

정리하자면

get방식 = url(응답방식에)데이터가 포함되어 요청하고 전달받는다.(주로 검색에 사용)

post방식 = url에 데이터가 같이 나오지 않고, url데이터 요청(데이터 정보의 양이 작게 제한되어 있는 데 반해) 상대적으로 보낼 수 있는 데이터 용량이 커 많은 데이터를 전송할 수 있다. 헤더, 응답 데이터가 아닌, 한칸띄고 메시지 정보에 포함되어서 전송됨

파일형식은 서버에서 파일을 찾을 때 &와 =의 데이터 값이 포함될 수 있기때문에 enctype = "multipart/form-data" 형식으로 http프로토콜에 데이터를 전송해야 합니다. boundary로 경계를 구분짓고 여러개의 파일을 보내고, 마지막 boundary에 --가 있으면 파일 데이터의 끝 부분입니다.

ex)

출처

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

profile
매일 한 걸음

0개의 댓글