<< 학습 목표 >>

1. 리엑트 디버깅 툴을 설치할 수 있다.

2. XX


내가 만든 프로그램이 항상 내가 의도한대로만 동작하면 너무 좋겠지만 대부분은 내가 의도한대로 동작하지 않음

그래서 어디에 문제가 있는지 찾는 과정을 디버깅(debugging)이라고 함

 

디버깅을 하는 고전적이면서 기본적인 방법은 코드 사이 사이에 분기점을 출력하는 것임

Chapter02에서 마지막에 실습했던 주소록 컴포넌트에 분기점을 출력하는 코드를 넣어보자

( 실제 입력하지는 말고 보기만 하기 )

 

위와 같이 console.log 를 사용해 파악하고 싶은 분기점 마다 출력문을 넣어 두면 어디서 문제가 생기는지 파악할 수 있음

소스코드가 간단할 때는 이와 같이 출력문으로 디버깅을 할 수 있지만 일반적인 상황에서는 소스코드가 간단하지 않으므로 출력문으로 디버깅하는데는 한계가 있음

 

보통 개발툴에서는 디버깅툴까지 제공하지만 vs code는 별도로 디버깅툴을 제공하지 않음

vs code에 디버깅툴을 설치할 수도 있지만 우리는 웹 브라우저에 리엑트 디버깅툴을 설치하자


Edge(엣지) 브라우저를 사용할 경우 리엑트 디버깅 툴이 자동으로 설치되지만 어떤 상황에 의해서 설치가 안됬거나 다른 브라우저를 사용해서 설치가 안된 경우가 있으므로 리엑트 디버깅 툴을 설치하는 방법을 알아보자

리엑트 디버깅 툴을 설치하는 방법은 엣지, 크롬 브라우저만 설명함

혹시 다른 브라우저를 사용하는 사람은 두 브라우저 중 하나를 설치하자

 

<< 엣지 브라우저에 리엑트 디버깅 툴 설치 >>

더보기

브라우저 오른쪽 상단에 ... 메뉴(1) 클릭 -> 확장(2) -> [ Mircrosft Edge 추가 기능 웹 사이트 열기 ] (3) 클릭

만약 이미 다른 확장 프로그램이 설치되 있어 아래의 3번과 다른 메뉴라면 [ Mircrosoft Edge 추가 기능 열기 ] (4) 클릭

 

추가 기능 사이트 내 [ react developer tools ] 검색(1) -> 리엑트 디버깅 툴 [ 다운로드 ] (2) -> [ 확장 추가 ] (3)


 

<< 크롬 브라우저에 리엑트 디버깅툴 설치 >>

더보기

브라우저 오른쪽 상단에 ... 메뉴(1) 클릭 -> 도구 더보기(2) -> 확장 프로그램(3)

 

왼쪽 상단에 메뉴 버튼(1) 클릭 -> 메뉴 내 하단에 [ Chrome 웹 스토어 열기 ] (2)

 

chrome 웹 스토어 페이지 내 [ react developer tools ] 검색(1) -> 리엑트 디버깅툴(2) 클릭 -> 

 

리엑트 디버깅툴 chrome에 추가(1) -> 확장 프로그램 추가(2)



이제 엣지나 크롬을 닫고 Chapter02 에서 만든 주소록 컴포넌트를 웹 페이지에 출력하자

( 만약 특정 컴포넌트를 출력하자 라는 말이 기억나지 않으면 https://codingaja.tistory.com/75 전 글 다시 보고 오기 )

 

웹 페이지 내에서 F12 를 눌러 개발자 모드를 열어보자

개발자 모드를 보면 이제 Components(1), Profiler(2) 탭이 보임

이 탭은 리엑트 웹 페이지에서만 보이는 것

 

개발자 모드를 연 상태에서 F5 키를 눌러 페이지를 새로고침 하자

이제 Components 탭에 다음과 같이 페이지를 구성하고 있는 컴포넌트들이 보임

 

이제 이를 통해서 문제가 생겼을 때 상태를 확인할 수 있음


디버깅 얘기가 나온 김에 마지막으로 Chapter02 에서 만들었던 주소록 컴포넌트에서 발생하는 문제를 해결하고 마무리 하자

 

Components 탭은 현재 페이지를 구성하고 있는 컴포넌트들을 확인할 수 있는 탭임

그외에 다른 문제들은 Console 탭(1)에서 확인할 수 있음

 

Console탭을 보면 지금 다음과 같이 빨간색 글씨로 출력된 문장이 있는데 Warning 으로 시작하므로 경고 메세지임

심각한 오류는 아니므로 현재 페이지가 제대로 보이지만 경고 메세지도 뜨지 않게 해주는게 좋음

 

이 경고 메세지는 map을 사용할 때 태그를 반환한다면 그 태그에 key 를 넣어줘야한다는 것임

 

이 경고 메세지를 따라 AddressList 컴포넌트 코드로 가서 다음과 같이 key를 추가하자

 

키를 추가해야하는 이유는 리엑트가 컴포넌트를 빠르게 랜더링하기 위해 필요한 요소임

728x90
LIST

<< 학습 목표 >>

1. JSON 형식 데이터를 설명할 수 있다.

2. JSON 형식 데이터를 만들 수 있다.

3. JSON 형식 데이터를 Jquery의 Ajax를 사용해 서버로 보낼 수 있다.

4. 서버는 클라이언트가 보낸 JSON 형식 데이터를 꺼낼 수 있다.


실무에서는 데이터를 주고 받을 때 JSON 형식 데이터를 많이 활용함

아주 오래 전에는 XML을 많이 활용했음

 

JSON은 JavaScript Object Notation의 약자로 JS가 객체를 표현하는 데이터 형식임


이름 나이 연락처
홍길동 29세 167.1cm 010-1111-1111

위와 같은 정보를 JSON으로 표현하면 다음과 같음

<script>
    let person = {
    	name: "홍길동",
        age: 29,
        height: 167.1,
        tel: "010-1111-1111"
    };
</script>

 

JSON은 { } 안에 name: value, name: value 의 형식으로 데이터를 표현함

value가 배열일 경우에는 [value, value, ...] 로 표현할 수 있음

<script>
    let person = {
    	name: "홍길동",
        age: 29,
        height: 167.1,
        tel: "010-1111-1111",
        schoolList: ["대한초등학교", "민국중학교", "한국고등학교"]
    };
</script>

 

이후에는 계속 같은 형식의 반복임

만약 JSON(객체) 안에 JSON(객체) 를 표현하고 싶다면 똑같은 형식이 반복됨

<script>
    let person = {
    	name: "홍길동",
        age: 29,
        height: 167.1,
        tel: "010-1111-1111",
        school: {
        	name: "대한초등학교",
        	grade: "6학년",
        	classNumber: "1반",
        	studentNumber: "25번"
        }
    };
</script>

 

JSON 배열(객체 배열) 도 표현할 수 있음

<script>
	let personList = [{name: "홍길동", age: 23}, {name: "고영희", age: 21}, {name: "김철수", age: 22}];
</script>

 

JSON을 문자열로 바꿔야하는 경우가 생기는데 그럴 때는 JSON.stringify 메서드를 사용하면 됨

<script>
    let person = {
    	name: "홍길동",
        age: 29,
        height: 167.1,
        tel: "010-1111-1111"
    };
    
    let str = JSON.stringify(person);
</script>

 

또는 문자열을 JSON으로 바꿔야하는 경우가 생기는데 그럴 때는 JSON.parse 메서드를 사용하면 됨

<script>
    let str = '{"name":"홍길동","age":29,"height":167.1,"tel":"010-1111-1111"}';
    let person = JSON.parse(str);
</script>

 

여기까지 JSON을 전부 알아봤음

굉장히 간단하면서 객체를 표현할 수 있기 때문에 실무에서 데이터를 주고 받을 때 주로 사용하는 데이터 형식임


여기서 끝내기 아쉬우니 Jquery의 Ajax를 사용해서 데이터를 보낼 때 JSON 데이터를 서버로 보내보자

 

먼저 서버로 JSON 데이터를 보낼 웹 페이지를 만들자

webapp -> chapter03 -> sendJson.html 을 만들고 아래 코드를 입력하자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>서버로 JSON 데이터 보내기</title>
</head>
<body>
	<button type="button">데이터 보내기</button>
	
	<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
	<script>
		let json = {name: "홍길동", age: 21, height: 178.1};
		
		$.ajax({
			url: "/studyProject/chapter03/receive_json",
			type: "POST",
			contentType: "application/json",
			data: JSON.stringify(json),
			success: function() {
				alert("서버가 제대로 데이터를 받았음");
			},
			error: function() {
				alert("어떤 문제가 생겼음");
			}
		});
	</script>
</body>
</html>

 

클라이언트가 서버로 JSON 데이터를 보낼 때 주의 할 점 두 가지가 있음

1. 보낼 데이터는 JSON.stringify 메서드를 사용해서 JSON 형식의 문자열로 변환해야함

2. 요청 정보의 헤더에 content-type을 "application/json" 으로 해야함

  클라이언트가 아무런 형식이 없는 데이터를 보내는게 아니라 JSON 형식의 데이터를 보내기 때문에 서버에서 클라이언트가 보낸 JSON 데이터를 인식하려면 요청 정보의 헤더에 content-type을 "application/json" 으로 설정해줘야함

 

ajax 로 보낼 때 요청 정보의 헤더에 content-type을 "application/json" 으로하는 방법은 위와 같이 contentType: "application/json" 으로 지정하면 됨

이때! 대소문자 정확하게 입력해야함

[ 위 ] 와 같이 ajax 로 요청을 하게 되면 [ 아래 ] 와 같이 요청 정보가 생성되 서버로 전달됨

 

이제 클라이언트가 보낸 JSON 데이터를 받을 서블릿을 만들자

chapter03 -> ReceiveJson 서블릿을 만들고 아래 코드를 입력하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/receive_json")
public class ReceiveJson extends HttpServlet {
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		
		String name = request.getParameter("name");
		String age = request.getParameter("age");
		String height = request.getParameter("height");
		
		System.out.println("name = " + name);
		System.out.println("age = " + age);
		System.out.println("height = " + height);
	}
}

 

클라이언트가 보낸 JSON 데이터 안에 한글 이름이 있으므로 request.setCharacterEncoding 을 빠트리면 안됨

그 후 request.getParameter 메서드를 사용해서 클라이언트가 보낸 JSON 데이터의 name, age, height 값을 꺼냈음

이제 서버를 시작하고 웹 페이지에서 [ 데이터 보내기 ] 버튼을 클릭해보자

 

그랬더니 콘솔에 보이는 결과는??

 

읭?

 

분명 클라이언트가 보낸 데이터가 꺼내져야하는데 꺼내지 못하고 있음

그 이유는 getParameter 메서드에 있음

getParameter는 form 태그가 보낸 데이터만 인식해서 꺼낼 수 있는 메서드임

정확하게 얘기하면 요청 정보 헤더의 content-type이 application/x-www-form-urlencoded 이어야하고 URL이나 몸통(body)에 데이터 형식이 그에 맞게 name=value&name=value&... 형식으로 담겨있어야지 getParameter 메서드로 꺼낼 수 있음

 

그러나 우리가 보낸 요청 정보를 다시 보면 이와 같음

그래서 우리가 JSON 으로 데이터를 보냈을 때 서블릿이 getParameter 메서드로 꺼낼 수 없는 것

 

그럼 JSON으로 보낸 데이터는 꺼내지 못한다는걸까?

아님 다른 방식으로 꺼내야함

 

이제 서블릿의 doPost 메서드 내 코드를 아래와 같이 바꾸자

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	
	BufferedReader br = request.getReader();
	String line = br.readLine();
	
	System.out.println(line);
}

 

JSON으로 보낸 데이터를 꺼낼 때는 먼저 요청 정보(HttpServletRequest)에 들어있는 BufferedRead 객체를 꺼내야함(1)

그 후 JSON으로 보낸 데이터를 꺼냄(2), 이때 사용하는 readLine 메서드는 클라이언트가 보낸 JSON 형식의 문자열을 반환함

 

우선은 꺼낸 JSON 형식의 문자열을 간단하게 출력해봤음

 

꺼낸 JSON 형식의 문자열을 서버에 맞게 짤라서 사용해야함

앞 뒤에 있는 괄호 { } 를 짜르고(1) , 를 기준으로 분리(2)하면 String 배열에 이름:값 이 들어있게됨

 

이제 doPost에 필요한 나머지 코드를 더 넣어서 클라이언트가 보낸 JSON 데이터를 서버에서 꺼내서 출력해보자

( 코드가 많이 추가 됐으니 더음부터 천천히 살펴보고 정확히 입력하자 )

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	
	String name = null;
	String age = null;
	String height = null;
	
	BufferedReader br = request.getReader();
	String line = br.readLine();
	
	line = line.substring(1, line.length()-1);
	String[] keyValueList = line.split(",");
	
	for(int i=0; i<keyValueList.length; i++) {
		String keyValue = keyValueList[i];
		
		String[] keyValueSet = keyValue.split(",");
		String key = keyValueSet[0].replace("\"", "");
		String value = keyValueSet[1].replace("\"", "");
		
		if(key.equals("name")) {
			name = value;
		} else if(key.equals("age")) {
			age = value;
		} else if(key.equals("height")) {
			height = value;
		}
	}
	
	System.out.println("name = " + name);
	System.out.println("age = " + age);
	System.out.println("height = " + height);
}

 

이제 서버를 재시작하고 다시 웹 페이지에서 [ 데이터 보내기 ] 버튼을 누르면 클라이언트가 보낸 데이터를 서버가 꺼내서 출력하고 있다는걸 알 수 있음

doPost 내 모든 코드를 반드시 이해할 필요는 없음

모든 코드를 이해하는게 당연히 좋겠지만 이해하지 못했다고 하더라도 "클라이언트가 보낸 JSON 데이터를 서버에서 꺼내려면 이렇게 복잡한 방식으로 꺼내야하는구나" 정도로만 이해하도됨

 

좀 더 쉽게 클라이언트가 보낸 JSON 데이터를 꺼내보자

 

클라이언트가 보낸 JSON을 쉽게 꺼내려면 별도의 라이브러리가 필요함

먼저 라이브러리를 다운 받아서 프로젝트에 추가하자

 

구글에 다음과 같이 maven repository 로 검색(1)

그 후 나오는 첫 번째 검색 결과로 이동

만약 검색 결과가 이와 다르다면 직접 이동 ( https://mvnrepository.com/ )

 

그 후 [ java json ] 이라고 검색(1) 하자

그러면 자바에서 사용할 수 있는 JSON 라이브러리들이 나옴

첫 번째 검색 결과로 이동(2)

 

검색 결과 페이지로 들어가면 JSON in Java 라이브러리의 설명과 현재 공개된 버전들이 나와있는데(1) 여기서 적당한 버전을 선택하자

최신 버전을 선택해도 되고 적당히 몇 년 전 버전을 선택해도 됨

 

적당한 버전을 선택해 들어왔으면 거기서 이제 다운로드 받을 페이지로 이동하자(1)

 

다운로드 페이지에서 다음과 같이 jar 로 끝나는 파일 눌러 다운 받자(1)

jar 란 자바에서 사용할 수 있는 압축 파일의 형식

라이브러리 안에는 굉장히 많은 자바 소스 파일이 들어있음

이 굉장히 많은 자바 소스 파일을 압축 없이 공개하면 다운 받는데 굉장히 오래 걸리고 사용하는것도 굉장히 복잡함

그래서 빨리 다운 받고 간편하게 사용하기 위해 jar 형식으로 압축 되어있는 것

 

이제 다운 받은 jar 압축 파일을 이클립스 -> 프로젝트 -> src -> main -> webapp -> WEB-INF -> lib 폴더로 드래그 & 드롭하자

 

이렇게 자바에서 JSON을 사용할 수 있게 라이브러리를 추가했음

자바에서 JSON을 사용하려면 왜 라이브러리를 추가해야할까?

JSON의 약자를 잘 생각해보기!

만약 생각 안나면 다시 이 글의 처음으로 올라가서 보고 오기!

 

이제 본격적으로 서버에서 클라이언트가 보낸 JSON 데이터를 받아서 꺼내보자

코드는 굉장히 간단함

import org.json.JSONObject;

// ...

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		
		BufferedReader br = request.getReader();
		JSONObject jo = new JSONObject(br.readLine());
		
		String name = jo.getString("name");
		int age = jo.getInt("age");
		double height = jo.getDouble("height");
		
		System.out.println("name = " + name);
		System.out.println("age = " + age);
		System.out.println("height = " + height);
}

 

클라이언트가 보낸 JSON 데이터를 꺼내기 위해 우선 요청 정보(HttpServletRequest)의 BufferedReader 객체를 꺼냄(1)

클라이언트가 보낸 JSON 데이터를 꺼낸 후 JSONObject 클래스 생성자의 인스턴스로 넣어줌(2)

 

그러면 JSONObejct 클래스 생성자 안에서 여러 처리를 거쳐 jo 객체 안에 클라이언트가 보낸 JSON 데이터가 들어있게 됨

 

jo 객체가 가지고 있는 값을 꺼낼 때는 꺼낼 값의 형태를 잘 생각해야함

jo 객체가 가지고 있는 값을 문자열로 꺼낼 때는 getString 메서드를 사용함(1)

jo 객체가 가지고 있는 값을 정수로 꺼낼 때는 getInt 메서드를 사용함(2)

jo 객체가 가지고 있는 값을 실수값으로 꺼낼 때는 getDouble 메서드를 사용함(3)

 

여기까지 길고 길었던~!

클라이언트가 보낸 JSON 데이터를 서버가 꺼내는 방법을 배웠음

그러나 여기서 한가지 언급하자면 여러분이 취업 준비는 동안에는 클라이언트가 JSON 데이터를 보낼 일도 없을 것이고 그에 따라 서버에서도 클라이언트가 보낸 JSON 데이터를 꺼내는 일도 없을 것

취업을 하게 되면

1. 앱에서 보내는 데이터를 서버가 받아야하고

2. 웹에서 보내는 데이터를 서버가 받아야하고

3. 기타 여러 기기에서 보내는 데이터를 서버가 받아야하는

경우가 생김

이런 경우에 서버가 JSON 데이터를 받아야하는 경우가 생겨 알아야함

 

취업을 하기 전에는 보통 웹과 통신하는 서버만 만드니 "서버가 JSON 데이터를 받으려면 굉장히 복잡하구나" 정도로만 기억해두면 나중에 취업해서 이런 상황이 생기면 "아! 인터넷에서 찾아봐야겠다" 가 떠오를 것

728x90
LIST

<< 학습 목표 >>

1. Jquery의 Ajax를 사용해 요청을 보낼 수 있다.


앞 글(https://codingaja.tistory.com/28) 에서는 JS의 XMLHttpRequest 객체를 사용해 요청해봤음

이번에는 Jquery의 Ajax 로 요청해보자

JS 보다 Jquery를 사용해 요청하는게 더 간편함

그러나 실무에서 Jquery 를 사용하지 못하는 상황도 있으니 두 방법 다 잘 기억해둬야함


$.ajax({
	url: "요청할 서블릿의 경로",
	type: "요청방식",
	data: 서버로 보낼 데이터,
	dataType: 서버로 보낼 데이터 형식,
	success: function() {
		alert("서버가 처리 결과를 전달(Response) 함");
	},
	error: function(response) {
    	console.log(response);
		alert("400, 500번대 상태 코드를 전달 받음");
	}
});

JS의 XMLHttpRequest에 대해서 사용 방법이 하나로 압축되었음

흑시 XMLHttpRequest는 설정 후 실행시키기 위해서 send 메서드를 호출해야하지만 ajax 는 별도로 호출하는 메서드가 없음

저 한 덩어리의 코드로 요청 정보를 설정한 후 요청까지 보내짐


회원 가입 페이지를 복사한 후 복사한 페이지 내 XMLHttpRequest와 관련된 코드는 지우자

그 후 그 자리(</form> 태그와 </body> 태그 사이)에 아래 코드를 넣자

( 단, Jquery의 Ajax를 사용하는 것이므로 Jquery 를 추가해야함 / HTML, CSS, JS 관련된 기초 내용은 하지 않으므로 Jquery를 모른다면 JS의 처음부터 공부하고 오세요 )

<script>
		let submitBtn = document.querySelector("input[type=submit]");
		submitBtn.addEventListener("click", function() {
			event.preventDefault();
			
			$.ajax({
				url: "/studyProject/chapter03/join",
				type: "POST",
				data: "id=myId&pw=myPw&name=홍길동&gender=male&fav=exercise&fav=game",
				success: function() {
					alert("회원가입 완료!");
				},
				error: function(response) {
					console.log(response);
				}
			});
		});
	</script>

이제 서버를 재시작하고 브라우저를 새로고침한 후에 [ 회원가입 ] 버튼을 눌러보자

페이지 전환 없이 현재 페이지 그대로인 상태에서 [ 회원가입 완료! ] 메세지가 뜸

이와 같이 페이지 전환 없이 요청을 보낼 수 있음

 

ajax는 요청 정보를 설정하면서 데이터도 같이 설정하기 때문에 여기까지가 끝!

728x90
LIST

<< 학습 목표 >>

1. XMLHttpRequest 객체를 사용해 요청을 보낼 수 있다.

2. MIME TYPE을 설명할 수 있다.

3. 동기(Synchronous)와 비동기(Asynchronous)에 대해 설명할 수 있다.


HTML 태그를 사용해서 서버로 요청을 하게 되면 페이지가 전환됨

마치 물건을 사기 위해 직접 매장에 가는 것

 

여기서는 페이지 전환 없이 서버로 요청하는 방법을 알아보자

페이지 전환 없이 서버로 요청하는건 물건을 인터넷으로 주문하는 것과 마찬가지

물건을 인터넷으로 주문하면 택배를 통해서 받는 것처럼

페이지 전환 없이 서버로 요청하기 위해서는 자바스크립트 또는 Jquery 를 사용해야함


우선 페이지가 전환된다는 사실을 다시 한번 확인해보자

https://codingaja.tistory.com/25 이 글에서 만들었던 회원가입 페에지를 사용해서 확인해보자

 

이처럼 적당히 데이터를 넣고 [ 회원가입 버튼 ] 을 눌러보자

잠깐! 여기서 주의 깊게 봐야할 건 페이지 URL

지금은 회원 가입 페이지에 있으니 당연히 회원 가입 페이지의 URL임

 

[ 회원가입 ] 버튼을 누르고 URL 을 확인해보자

 

이렇게 HTML만을 사용해서 서버로 요청을 하면 URL이 바뀜

지금처럼 요청했을 때 URL이 바뀌어도 되는 상황이 있지만 URL이 바뀌면 안되는 상황이 있음

URL이 바뀌어도 되는 상황에서는 HTML 로 요청을 보내고 URL이 바뀌면 안되는 상황이라면 JavaScript 또는 Jquery를 사용해 요청을 보내면 됨


JavaScript(자바스크립트 / 이하 JS 라고 하겠음 ) 를 사용해서 서버로 요청을 보내보자

JS를 사용해 서버로 요청을 보낼 때는 XMLHttpRequest 객체를 사용함

예시 코드를 보자

var request = new XMLHttpRequest();
request.onreadystatechange = function() {
	if(this.readyState == this.DONE && this.status == 200) {
		alert("서버가 처리 결과를 전달(Response) 함");
	}
}

request.open("요청방식", "요청할 서블릿의 경로", true);
request.send();

 

이와 같이 JS의 XMLHttpRequest 객체를 사용해 서버로 요청을 보낼 수 있음

이 방식을 사용하면 페이지 전환 없이 그 페이지 그대로 있지만 요청을 하고 응답을 받을 수 있음

 

요청을 보낼 때 요청 방식은 request.open 메서드의 첫 번째 매개변수로 지정함

// GET 방식으로 요청
request.open("GET", "요청할 서블릿의 경로", true);

// POST 방식으로 요청
request.open("POST", "요청할 서블릿의 경로", true);

request.open 메서드의 세 번째 매개변수는 동기(Synchronous) 또는 비동기(Asynchronous) 방식으로 요청을 보내도록 조절하는 매개변수임

동기, 비동기는 약간의 설명이 필요하니 이 글의 마지막에 설명하겠음

 

 

서버가 응답했을 때 JS가 취할 행동은 function 안에 적어둠

request.onreadystatechange = function() {
	if(this.readyState == this.DONE && this.status == 200) {
		alert("서버가 처리 결과를 전달(Response) 함");
	}
}

 

this.readyState == this.DONE 은 서버가 응답을 했다면 이라는 코드임

this.status 는 서버가 응답한 상태 코드를 뜻함

( 상태 코드에 대해 모르겠다면 https://codingaja.tistory.com/16 이 글을 보고 오자 )

 

if의 조건식을 해석해보면 아래와 같음


회원가입 페이지에 JS 를 붙여서 페이지 전환 없이 그 페이지 그대로 [ 회원가입 ] 요청을 보내자

아래 JS 코드를 </form> 과 </body> 사이에 넣자

<script>
		let submitBtn = document.querySelector("input[type=submit]");
		submitBtn.addEventListener("click", function() {
			event.preventDefault();
			
			let request = new XMLHttpRequest();
			
			request.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					alert("회원가입 완료!");
				} else if(this.readyState == this.DONE && this.status == 400) {
					alert("이미 사용중인 아이디입니다.");
				} else if(this.readyState == this.DONE && this.status == 500) {
					alert("서버에 문제가 생겼습니다.\n잠시후 다시 시도해주세요");
				}
			}
			
			request.open("POST", "/studyProject/chapter03/join", true);
			request.send();
		});
	</script>

 

이제 서버를 재시작하고 브라우저를 새로고침한 후에 [ 회원가입 ] 버튼을 눌러보자

페이지 전환 없이 현재 페이지 그대로인 상태에서 [ 회원가입 완료! ] 메세지가 뜸

이와 같이 페이지 전환 없이 요청을 보낼 수 있음


여기까지 다 배운것같지만 아직 한가지가 빠졌음

서버로 데이터를 담아 요청하기

 

서버로 데이터를 담아 요청할 때는 request.send 메서드의 인자로 데이터를 담으면 됨

그리고~! 내가 담은 데이터가 어떤 형태의 데이터인지 명시를 해줘야함

request.setReqestHeader("content-type", "내가 담은 데이터의 MIME TYPE");

request.send("데이터");

여기서 잠시 MIME TYPE 에 대해서 배우고 넘어가자

MIME TYPE 이란 내가 보내는 데이터의 형태를 뜻함

클라이언트가 서버로 MIME TYPE을 보내면 클라이언트가 서버로 보내는 데이터의 형태를 정의하는 것임

서버가 클라이언트로 MIME TYPE을 보내면 서버가 클라이언트에게 보내는 데이터의 형태를 정의하는 것

 

MIME TYPE은 여러가지가 있음

text/plain text/html
보내는 데이터가 아무 의미 없는 텍스트이다 보내는 데이터가 텍스트인데 HTML 코드로 이뤄진 텍스트이다.
image/jpg image/png
보내는 데이터가 JPG 이미지 파일이다. 보내는 데이터가 PNG 이미지 파일이다.
application/json application/x-www-form-urlencoded
보내는 데이터가 JSON 이다. 보내는 데이터가 form 태그 형식의 데이터다.

 

form 태그는 GET, POST 다 데이터를 이름=값&이름=값&... 의 형태로 데이터를 보냄

XMLHttpRequest 객체를 사용해 form 태그 형식으로 데이터를 보낼 때는 다음과 같이 사용함

( request.open 이후의 코드 두 줄만 복사했음 )

request.setRequestHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
request.send("id=myId&pw=myPw&name=홍길동&gender=male&fav=exercise&fav=game");

여기까지 XMLHttpRequest 객체를 사용해 요청을 보내는 방법과 요청을 보낼 때 데이터를 담아 요청을 보내는 방법에 대해서 배웠음

 

이번에는 마지막으로 동기(Synchronous)와 비동기(Asynchronous) 용어를 배우고 마무리하자

동기란 순차적으로 일을 처리하는것을 뜻함

비동기란 비순차적으로 일을 처리하는것을 뜻함

 

동기의 예를 들어보자

아래와 같은 프로그램을 실행시킨다면 순차적으로 1, 2, 3, 4 가 출력될 것

아래 프로그램이 동기 방식

public class Ex01 {
	public static void main(String[] args) {
		System.out.println(1);
		System.out.println(2);
		System.out.println(3);
		System.out.println(4);
	}
}

 

비동기에 대한건 예를 들기 보다 직접 사용해보는게 나으니 비동기 예는 패쓰~!

 

동기, 비동기에 대해서 알아보기 위해 다음과 같은 서블릿 3개를 chapter03 패키지에 추가하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/first")
public class First extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("First 서블릿 호출됨");
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("First 서블릿 처리 완료");
	}

}
package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/second")
public class Second extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("Second 서블릿 호출됨");
		
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("Second 서블릿 처리 완료");
	}

}
package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/third")
public class Third extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("Third 서블릿 호출됨");
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("Third 서블릿 처리 완료");
	}

}

위 세 서블릿은 요청이 들어왔을 때 5, 2, 1 초를 쉼

 

세 서블릿을 동기, 비동기 방식으로 요청하는 HTML 페이지를 만들자

webapp 안에 chapter03 안에 sync.html 을 만들고 아래 코드를 넣자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>동기/비동기 테스트</title>
</head>
<body>
	<button onclick="sync()">동기 방식으로 요청</button>
	<button onclick="async()">비동기 방식으로 요청</button>
	
	<script>
		function sync() {
			let req1 = new XMLHttpRequest();
			let req2 = new XMLHttpRequest();
			let req3 = new XMLHttpRequest();
			
			req1.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req1 응답 받음");
				}
			}
			req2.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req2 응답 받음");
				}
			}
			req3.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req3 응답 받음");
				}
			}
			
			req1.open("GET", "/studyProject/chapter03/first", false);
			req2.open("GET", "/studyProject/chapter03/second", false);
			req3.open("GET", "/studyProject/chapter03/third", false);
			
			req1.send();
			req2.send();
			req3.send();
		}
		
		function async() {
			let req1 = new XMLHttpRequest();
			let req2 = new XMLHttpRequest();
			let req3 = new XMLHttpRequest();
			
			req1.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req1 응답 받음");
				}
			}
			req2.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req2 응답 받음");
				}
			}
			req3.onreadystatechange = function() {
				if(this.readyState == this.DONE && this.status == 200) {
					console.log("req3 응답 받음");
				}
			}
			
			req1.open("GET", "/studyProject/chapter03/first", true);
			req2.open("GET", "/studyProject/chapter03/second", true);
			req3.open("GET", "/studyProject/chapter03/third", true);
			
			req1.send();
			req2.send();
			req3.send();
		}
	</script>
</body>
</html>

[ 동기 방식으로 요청 ] 버튼을 누르면 JS의 sync 함수가 호출됨

1. sync 함수 안에서는 3개의 요청을 하기 위한 XMLHttpRequst 객체를 3개 생성했음

2. 각 객체가 요청을 하고 응답을 받았을 때 console 창에 "~~ 응답 받음" 을 출력하도록 함

3. 각 객체가 요청할 정보 지정 / 요청 방식(a), URL(b), 동기(c)

4. 요청

특히 마지막 요청을 보면 req1, req2, req3 순으로 요청했음

동기 방식이기 때문에 req1의 요청을 하고 서버가 응답을 해야 그 다음에 있는 req2.send() 코드가 실행됨

마찬가지로 req2의 요청에 대해 서버가 응답을 해야 그 다음에 있는 req3.send() 코드가 실행됨

 

[ 동기 방식으로 요청 ] 버튼을 누르고 브라우저의 개발자 모드 내 [ console ] 패널을 확인하자

 

이번에는 비동기 방식에 대해 알아보자

[ 비동기 방식으로 요청 ] 버튼을 누르면 async 함수가 호출되 동작하는데 동기 방식과 차이점은 3번의 c 밖에 없음

3번의 c가 false이면 동기 방식으로 요청을 하고 3번의 c가 true이면 비동기 방식으로 요청함

비동기 방식은 서버의 응답이 온 순서대로 처리함

비동기 방식의 요청은 req1.send() 로 요청을 보내고 응답이 올때까지 기다리지 않고 바로 다음 코드인 req2.send() 가 동작함 그래서 첫 번째 요청에 이어 두 번째 요청도 곧바로 들어감

마찬가지로 마지막 요청도 곧바로 들어감

첫 번째 서블릿은 5초를 기다리고 두 번째 서블릿은 2초를, 세 번째 서블릿은 1초를 기다리고 응답하므로 응답 속도가 제일 빠른 서블릿은 세 번째 서블릿 그 다음은 두 번째 서블릿, 마지막으로 첫 번째 서블릿임

따라서 [ 비동기 방식으로 요청 ] 버튼을 누르면 "req3 응답 받음", "req2 응답 받음", "req1 응답 받음" 순서대로 출력됨

 

동기, 비동기 또한 좋은 방식, 나쁜 방식이 아닌 상황에 맞는 방식이 있는것

그러나 대부분 비동기 방식으로 요청함

728x90
LIST

<< 학습 목표 >>

1. GET, POST 방식을 상황에 맞게 선택할 수 있다.


https://codingaja.tistory.com/22 이 글을 통해 GET 방식과 POST 방식의 차이에 대해서 알아봤음

여기서는 클라이언트가 어느 상황에서 GET 방식으로 요청해야하는지, 어느 상황에서 POST 방식으로 요청해야하는지 알아보자

 

GET과 POST 를구분해서 사용하는 상황은 아래의 상황이 있음

상황1. 서버로 보내는 데이터가 공개되어도 상관 없다.

상황2. 보내는 데이터가 많다.

상황3. 보내는 데이터에 파일이 포함되있다.

 

이 상황 외에도 GET과 POST 가 갖고 있는 의미를 고려해서 사용해야함

GET, POST 가 갖는 의미를 알고 싶고 더 실력있는 개발자가 되고 싶다면 이 책을 읽어보자

 

HTTP 완벽 가이드 - YES24

웹 세상을 떠받치고 있는 HTTP에 대한 모든 것모든 성공적인 웹 트랜잭션 뒤에는, 웹 클라이언트와 서버가 문서와 정보를 교환하는 언어인 HTTP가 있다. HTTP는, 회사 인트라넷에 접근하거나 절판된

www.yes24.com


<< 상황1. 서버로 보내는 데이터가 공개되어도 상관 없다. >>

GET 방식으로 데이터를 보낼 때는 URL에 보내는 데이터가 노출됨
POST 방식으로 데이터를 보낼 때는 URL에 보내는 데이터가 노출되지 않음

유저(클라이언트)가 서버로 보내는 데이터를 다른 유저들이 봐도 상관 없다면 GET 방식을 사용하면 됨

 

 

아래와 같은 로그인 페이지를 만들었다고 하자

 

사용자는 아이디, 비밀번호를 입력하고 로그인 버튼을 누를 것

그러면 사용자의 아이디, 비밀번호가 서버로 전달됨

 

이때 아이디, 비밀번호, 로그인 버튼을 감싸는 form 태그의 method를 GET 으로 했다면 GET 방식으로 요청이 들어감

GET 방식으로 요청을 할 때 서버로 보낼 데이터는 URL의 마지막에 ? 다음에 붙게됨(1)

 

이와 같이 GET 방식은 서버로 보내는 데이터가 URL에 노출되는데 로그인 같은 경우에 GET 방식을 사용하면 내가 로그인을 할 때 다른 사용자도 내 아이디와 비밀번호를 볼 수 있다는 것

그러면 어떻게 될까? 누군가 내 계정을 해킹할 수 있다는 것

 

로그인의 경우에는 서버로 보내는 데이터가 노출되면 안되는 상황

로그인 페이지를 만들 때는 form 태그의 method 를 POST 방식으로 한다면 보내는 데이터가 URL에 붙지 않고 요청 정보 안에 몸통(body) 로 들어가게 됨

서버로 데이터를 보내지만 다른 사용자는 볼 수 없게 숨켜서 보내기 때문에 해킹에 상대적으로 안전함

 

여기까지 로그인 하는 상황을 예로 들면서 GET 대신 POST 를 사용해야되는 경우를 얘기했음

 

그렇다면 GET을 사용해야되는 상황은 언제일까?

대표적인 예로 검색을 하는 경우가 있음

네이버에서 검색하는 상황을 보자

검색어를 입력하고 [ 검색 버튼 ] 을 누르면 서버로 검색어가 전달됨

 

 

대부분의 사람들은 "내가 뭘 검색하는지 다른 사람에게 보여주기 싫다" 라고 생각하며 검색하진 않음

별다른 생각 없이 검색을 함

내가 지금 검색한걸 다른 사람이 본다면 약간 이상하긴 하겠지만 크게 불편하지는 않을 것

이렇게 검색 같은 경우 서버로 보내는 데이터가 노출되어도 심각한 문제가 생기지 않기 때문에 GET 방식을 사용함


<< 상황2. 보내는 데이터가 많다. >>

https://codingaja.tistory.com/22 글에서 GET의 특징에 대해서 언급했듯 GET 방식으로 데이터를 보낼 때는 보내는 데이터의 크기에 제한이 있음

보내는 데이터가 많다는건 보내는 데이터의 전체 크기가 크다는 것이므로 GET 방식으로 데이터가 보내지지 않을 수 있음

그래서 보내는 데이터가 많다면 POST 방식을 사용해야함

 

예를 들어 회원 가입 같은 경우가 있음

회원 가입의 경우 아이디, 비밀번호, 비밀번호 확인, 이름, 연락처 등등 여러 가지를 입력하고 이 데이터들을 서버로 보내게 됨

상황1과 맞물려서 회원 가입 정보는 다른 사람이 보면 안되고 보내는 데이터가 많으므로 POST 방식이 적합함

또한 회원 정보 수정도 마찬가지

그 외에도 글 쓰기, 글 수정하기 등 다양한 상황에서 POST 방식을 사용함


<< 상황3. 보내는 데이터에 파일이 포함되있다. >>

GET 방식으로는 파일을 서버로 보낼 수 없음

파일을 서버로 보내려면 반드시 POST 방식을 사용해야함

 

파일을 서버로 보내는 상황이 어떤 상황일까?

프로필 이미지를 등록할 때, 내가 등록할 프로필 이미지를 서버로 보내는 것임

게시판에 파일을 첨부할 때, 첨부한 파일을 서버로 보내는 것임

등...

 

앞서 얘기했듯 좋은 방식, 나쁜 방식이라는건 없음

상황에 맞는 방식이 있는것임

728x90
LIST

<< 학습 목표 >>

1. 웹 페이지에서 URL을 사용할 때 최대한 짧게 사용할 수 있다.


지금까지 우리가 만든 웹 페이지에서 서블릿으로 요청을 보내기 위해 http 부터 썼음

주로 form 태그를 썼지만 form 태그 뿐만 아니라 a 태그 등 URL을 입력하는 모든 곳에서 프로토콜(http)부터 시작하는데 꼭 그래야하는건 아님

 

프로토콜부터 포트번호까지는 생략하고 그 다음 것들만 사용해도 됨

앞서 우리가 사용했던 회원 가입 웹 페이지 코드를 다시 보자

01

form 태그의 action 속성에 URL을 썼는데(1) 프로토콜부터가 아닌 포트번호 이후에 있는 /studyProject/chapter03/join(2) 만 써도 됨
( 슬라이드 이미지니 넘겨서 보세요 )

 

포트번호 이후에 있는 경로만 썼을 때는 어떻게될까?

필요한 앞부분이 빠졌으므로 현재 URL에서 필요한 부분을 가져와 채움

 

이렇게 쓰지 않았다 해서 없는게 아니라 쓰지 않으면 없는 부분을 채움

회원가입 페이지 내 form 태그의 action 속성 값을 이와 같이 바꾸고 다시 회원가입을 시도해보자

728x90
LIST

<< 학습 목표 >>

1. 클라이언트가 보낸 데이터를 서버에서 그대로 꺼낼 수 있다.


우리는 지금까지 서버로 데이터를 보낼 때 영문, 숫자만 보내봤음

클라이언트가 한글 데이터를 서버로 보냈고 서버가 한글 데이터를 꺼내려면 한가지 처리가 필요함

 

클라이언트가 한글 데이터를 보내도록 웹 페이지를 만들어보자

webapp 안에 chapter03 안에 join.html 을 만들고 아래 코드를 입력하자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>회원가입 페이지</title>
</head>
<body>
	<form action="http://localhost:8080/studyProject/chapter03/join" method="POST">
		<fieldset>
			아이디: <input type="text" name="id">
		</fieldset>
		
		<fieldset>
			비밀번호: <input type="password" name="pw">
		</fieldset>
		
		<fieldset>
			이름: <input type="text" name="name">
		</fieldset>
		
		<fieldset>
			성별:
			<label><input type="radio" name="gender" value="male">남자</label>
			<label><input type="radio" name="gender" value="female">여자</label>
		</fieldset>
		
		<fieldset>
			취미:
			<label><input type="checkbox" name="fav" value="exercise">운동</label>
			<label><input type="checkbox" name="fav" value="book">책읽기</label>
			<label><input type="checkbox" name="fav" value="game">게임</label>
		</fieldset>
		
		<fieldset>
			<input type="submit" value="회원가입">
		</fieldset>
	</form>
</body>
</html>

이 페이지는 회원 가입 페이지로 아이디, 비밀번호, 성별, 취미 데이터는 영문이지만 이름은 한글 데이터로 보낼 예정

 

우선 회원 가입 요청을 받을 서블릿을 추가하자

chapter03 패키지 내 join 서블릿을 추가하고 아래와 같이 코드 입력

package chapter03;

import java.io.IOException;
import java.util.Arrays;

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

@WebServlet("/chapter03/join")
public class Join extends HttpServlet {
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String id = request.getParameter("id");
		String pw = request.getParameter("pw");
		String name = request.getParameter("name");
		String gender = request.getParameter("gender");
		String[] fav = request.getParameterValues("fav");
		
		System.out.println("클라이언트가 보낸 id => " + id);
		System.out.println("클라이언트가 보낸 pw => " + pw);
		System.out.println("클라이언트가 보낸 name => " + name);
		System.out.println("클라이언트가 보낸 gender => " + gender);
		System.out.println("클라이언트가 보낸 fav => " + Arrays.toString(fav));
	}

}

 

이제 회원 가입 페이지에서 아래와 같은 형식으로 데이터를 입력해 [ 회원 가입 ] 버튼을 눌러보자

다른 데이터들은 클라이언트가 보낸 그대로 꺼내졌지만 이름만 클라이언트가 보낸것과 다르게 꺼내졌음

 

클라이언트가 한글 데이터를 보냈을 때는 서버에서 데이터를 꺼내기 전 반드시 다음과 같은 코드(1)를 써줘야함

 

이는 클라이언트가 보낸 데이터를 UTF-8 방식으로 인코딩하겠다는 것

인코딩에 대해서 알아보고 이해하고 나면 더 머리만 복잡해지므로 클라이언트가 보내는 데이터에 한글이 하나라도 있다면 무조건 request.setCharacterEncoding("UTF-8") 로 하자 라고 생각하면 됨

 

여기까지! 서버가 한글 데이터를 받는 방법 끝!

728x90
LIST

<< 학습 목표 >>

1. 500 에러 페이지가 보이는 원인을 찾을 수 있다.

2. 500 에러 페이지가 보이지 않도록 예외 처리를 할 수 있다.

3. 유효성 검증 코드를 작성 할 수 있다.


"열길 물 속은 알아도 한길 사람 속은 모른다" 라는 속담이 있음

여기서 길이란 옛날에 사용하던 길이의 단위로 열길 물 속은 매우 깊은 물 속을 뜻함

그에 비해 사람의 속은 상대적으로 얕지만 알 수 없다는 말

 

갑자기 이 말을 왜 하느냐

이제 우리는 클라이언트가 보낸 값을 서버가 꺼낼 수 있는데

클라이언트가 항상 값을 보낸다고 장담하면 안됨

 

지금 바로 네이버에 로그인을 해보자

일반적으로는 아이디, 비밀번호를 입력하고 로그인하겠지만

고의적으로든 아니면 어떤 실수로든 아이디 또는 비밀번호를 누락하고 로그인을 하려고 할 때도 있었을 것

 

뷰에서는 클라이언트에게 입력을 요구했지만 사용자는 입력하지 않았을 수 있음

서버에서도 이런 상황에 대한 대비가 필요함

이렇게 클라이언트가 값을 보내지 않았을 때를 위한 대비 하는 코드를 "유효성 검증(검사) / Validation" 이라고 함


다시 한번 지금까지 만들었던 계산기 웹 페이지를 만들자

webapp 폴더 안에 chatper03 폴더 안에 calculator.html 에 아래 코드를 입력하자

! 주의 ! 수를 입력하는 input 태그의 type속성이 text임

( form 태그의 method 속성은 GET, POST 둘 중 아무거나 상관 없음 )

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>계산기</title>
</head>
<body>
	<form action="http://localhost:8080/studyProject/chapter03/calculator" method="POST">
		<input type="text" name="firstNumber" placeholder="첫 번째 수">
		<select name="operator">
			<option>+</option>
			<option>-</option>
			<option>*</option>
			<option>/</option>
		</select>
		<input type="text" name="secondNumber" placeholder="두 번째 수">
		<input type="submit" value="결과 보기">
	</form>
</body>
</html>

 

클라이언트의 요청을 받을 서블릿을 추가하자

대신 계산을 하지는 않고 클라이언트가 보낸 값을 꺼내 변환 후 출력만 하고 있음

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/calculator")
public class Calculator extends HttpServlet {
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int firstNumber = Integer.parseInt(request.getParameter("firstNumber"));
		int secondNumber = Integer.parseInt(request.getParameter("secondNumber"));
		String operator = request.getParameter("operator");
		
		System.out.println("첫 번째 수 => " + firstNumber);
		System.out.println("두 번째 수 => " + secondNumber);
		System.out.println("연산자 => " + operator);
	}

}

 

이제 웹 페이지를 열고 아무 값도 입력하지 않은 채로 [ 결과 보기 ] 를 눌러보자

그럼 이러한 페이지가 보임

 

이 페이지는 서블릿 또는 자바에서 예외가 발생했는데 예외 처리를 하지 않았을 때 보여지는 페이지임

앞으로는 이런 페이지가 보이면 이클립스로 돌아가 [ Console ] 패널을 보자

 

이클립스의 [ Console ] 패널에 예외 메세지가 보임

예외 메세지를 분석해 예외가 발생한 라인 번호와 이유를 찾아보자

 

14번째 줄에서 예외가 발생했고(1) 발생한 이유는 For input String: ""(2) 임

14번째 줄 소스 코드를 보자

예외가 발상한 코드는 14번 째 줄에 Integer.parseInt 메서드 때문에 발생함(1)

 

왜 Integer.parseInt 메서드에서 예외가 발생했는지 좀 더 분석해보면 request.getParameter 메서드로 firstNumber 파라미터의 값을 꺼냈는대 클라이언트가 뷰에서 해당 값을 입력하지 않았음

그래서 firstNumber 파라미터의 값이 비어있어 request.getParameter 메서드가 firstNumber 파라미터의 값을 ""(빈 문자열) 로 반환함(1)

Integer.parseInt 메서드는 숫자처럼 생긴 문자열만 정수로 바꿔줄 수 있음

빈 문자열은 숫자처럼 생긴 문자열이 아니므로 정수로 바꿀 수 없어 예외가 발생하는 것(2)

( 슬라이드 이미지이니 넘기면서 보세요 )

012

 

이와 같이 서버는 "클라이언트가 firstNumber 파라미터의 값을 보낼꺼다" 라는 가정으로 코드를 짰는데 클라이언트가 서버로 firstNumber 파라미터 값을 보내지 않았기 때문에 발생하는 예외임

이럴 때 하는게 뭐다? Validation ( 유효성 검증/검사 )

 

유효성 검증은 특별한게 없음

파라미터의 값을 꺼내서 서버가 원하는 형태의 값을 보냈는지 판단하는게 유효성 검증임

firstNumber 파라미터의 값을 꺼내서 유효성 검증을 하려면 예외가 발생했을 때 firstNumber 파라미터의 값이 어떤 값인지 알아야함

firstNumber 파라미터의 값이 어떤 값인지 알기 위해 이와 같이 다양한 방법을 시도해볼 수 있음

이 외에도 여러분만의 방법도 있을 것

 

서버를 재부팅(Restart) 하고 다시 웹 페이지에서 아무것도 입력하지 않고 [ 결과 보기 ] 를 눌러보자

결과창을 보면 첫 번째 결과는 아무것도 안보임(1) 두 번째 결과는 [] 안에 아무것도 안들어있음(2) 세 번째 결과는 0임

이를 통해서 request.getParameter 메서드로 꺼낸 firstNumber 파라미터의 값이 빈 문자열이라는걸 알 수 있음

 

이제 if문 또는 try ~ catch 문을 사용해서 예외 처리를 하면 됨

먼저 if문으로 예외 처리를 해보자

( doPost 메서드 안에 코드만 붙여 넣었음 )

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String firstNumber_string = request.getParameter("firstNumber");
		String secondNumber_string = request.getParameter("secondNumber");
		if(firstNumber_string.length() == 0) {
			System.out.println("firstNumber 파라미터의 값이 비어있습니다.");
		} else if(secondNumber_string.length() == 0) {
			System.out.println("secondNumber 파라미터의 값이 비어있습니다.");
		} else {
			int firstNumber = Integer.parseInt(request.getParameter("firstNumber"));
			int secondNumber = Integer.parseInt(request.getParameter("secondNumber"));
			String operator = request.getParameter("operator");
			
			System.out.println("첫 번째 수 => " + firstNumber);
			System.out.println("두 번째 수 => " + secondNumber);
			System.out.println("연산자 => " + operator);
		}
	}

 

firstNumber 파라미터 외에도 secondNumber 파라미터의 값도 빈 문자열 일 수 있으므로 두 파라미터의 값 모두 유효성 검증을 했음

두 파라미터의 값이 빈 문자열이 아니라면 else 로 빠져서 사용자가 입력한 값을 꺼내 정수로 변환하고 출력할 것

 

유효성 검증이 정상적으로 동작하는지 확인하자

서버를 재부팅(Restart) 하고

1. 웹 페이지에서 아무것도 입력하지 않고 [ 결과 보기 ] 를 눌러보자

2. 웹 페이지에서 첫 번째 수만 입력하고 [ 결과 보기 ] 를 눌러보자

3. 웹 페이지에서 첫 번째, 두 번째 수 모두 입력하고 [ 결과 보기 ] 를 눌러보자

이제 유효성 검증을 통해 500 에러 페이지가 보이지 않음

 

1, 2 번의 경우 유효성 검증에 걸려 "firstNumber 파라미터의 값이 비어있습니다."와 비슷한 메세지가 출력됨

3 번의 경우 유효성 검증을 통과해 else 로 빠져 사용자가 입력한 값을 출력함

1, 2번의 경우 처럼 유효성 검증을 통과하지 못한 상황을 "유효성 검증에 실패했다" 라고 함

3번의 경우 처럼 유효성 검증을 통과한 상황을 "유효성 검증에 성공했다" 라고 함

 

여기까지 유효성 검증 완료~!

이면 좋겠지만 유효성 검증은 생각만큼 쉽고 간단하지 않음

 

앞서 값을 보내지 않았을 때 500 에러 페이지가 보인 이유는?

서버는 "클라이언트가 firstNumber 파라미터의 값을 보낼꺼다" 라는 가정으로 코드를 짰는데 클라이언트가 서버로 firstNumber 파라미터 값을 보내지 않았기 때문에...

서버에서 또 다른 잘못된 가정을 하고 있음

무엇일까?

더보기

클라이언트가 첫 번째 수(firstNumber)와 두 번째 수(secondNumber)로 정수를 입력할 것이다


웹 페이지를 만들 때 input 태그의 type 속성을 text로 한 이유가 있음

첫 번째 수를 입력하는 input 태그의 type 속성이 text 이므로 사용자는 정수가 아닌 실수값을 입력할 수도 있고 문자열을 입력할 수도 있음

"에이 너무 억지아니야?" 라고 생각할 수 있겠지만 세상에는 생각보다 다른 생각을 가진 사람들이 많음

이렇게 정수가 아닌 값을 입력하고 [ 결과 보기 ] 버튼을 눌러보자

역시나 예외가 발생해 500 에러 페이지가 보임

if문으로 예외 처리하지 않았기 때문에...

 

이를 어떻게 해결할까?

여러분이 먼저 직접 해결해보기

더보기

전달 받은 firstNumber, secondNumber 파라미터 값의 각 자리 값을 chatAt 메서드로 꺼내 숫자가 아니라면 "유효성 검증 실패", 마지막 자리 값까지 모두 숫자였다면 "유효성 검증 성공"

 

이제는 점점 코드가 복잡해지므로 유효성을 검증할 메서드가 필요함

다음과 같이 chapter03 패키지에 어떤 문자열이 숫자인지 판단하는 메서드 추가

isNumeric 은 "숫자인가요?" 라고 번역할 수 있음

이 메서드가 true를 반환하면 어떤 문자열은 정수처럼 생긴 문자열임

이 메서드가 false를 반환하면 어떤 문자열이 정수처럼 생기지 않은 문자열임

 

package chapter03;

public class Validation {
	public boolean isNumeric(String str) {
		boolean isNumeric = false;
		
		if(str.length() != 0) {
			for(int i=0; i<str.length(); i++) {
				char nthNumber = str.charAt(i);
				
				if(nthNumber < '0' || nthNumber > '9') {
					isNumeric = false;
					break;
				}
			}
		}
		
		return isNumeric;
	}
}

 

그리고 서블릿에서는 다음과 같이 Validation 을 사용해 유효성 검증을 하는 코드로 바꾸자

( 서블릿의 doPost 메서드만 옮김 )

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Validation v = new Validation();

		if(!v.isNumeric(request.getParameter("firstNumber"))) {
			System.out.println("firstNumber 파라미터의 값이 올바르지 않습니다.");
		} else if(!v.isNumeric(request.getParameter("secondNumber"))) {
			System.out.println("secondNumber 파라미터의 값이 올바르지 않습니다.");
		} else {
			int firstNumber = Integer.parseInt(request.getParameter("firstNumber"));
			int secondNumber = Integer.parseInt(request.getParameter("secondNumber"));
			String operator = request.getParameter("operator");
			
			System.out.println("첫 번째 수 => " + firstNumber);
			System.out.println("두 번째 수 => " + secondNumber);
			System.out.println("연산자 => " + operator);
		}
	}

 

유효성 검증은 if문을 사용해야할까? 아님 try ~ catch 를 사용해도됨

또한 이외에 유효성 검증이 더 필요할까?

그건 여러분의 몫 ~~

728x90
LIST

<< 학습 목표 >>

1. 클라이언트가 다양한 형태의 값을 보내도록 페이지를 구성할 수 있다.

2. 클라이언트가 보낸 값을 서버에서 꺼낼 수 있다.


클라이언트가 서버로 보낸 값을 꺼낼 때는 요청 정보를 갖고 있는 HttpServletRequest 타입 매개변수의 getParamter 메서드를 사용해서 꺼냄

메서드 형식 설명
String getParameter(String) 인자로 파라미터 이름을 넣으면 파라미터의 값을 문자열로 반환함
String[] getParamterValues(String) 인자로 파라미터 이름을 넣으면 파리머터의 값들을 문자열 배열로 반환함

 

우선 뷰 페이지를 만들자

webapp 안에 chapter03 안에 sendData.html 파일을 만들고 아래 코드를 입력하자

( 참고. form 태그의 method 속성이 없으므로 클라이언트의 요청 방식은 GET 임 )

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>데이터 보내기</title>
</head>
<body>
	<h1>데이터 보내기1</h1>
	<form action="http://localhost:8080/studyProject/chapter03/send_data1">
		<input type="text" name="data1"><br>
		<input type="number" name="data2"><br>
		<input type="submit" value="보내기">
	</form>
	<hr>
	
	<h1>데이터 보내기2</h1>
	<form action="http://localhost:8080/studyProject/chapter03/send_data2">
		<input type="text" name="data1"><br>
		<textarea rows="10" cols="50" name="data2"></textarea><br>
		<input type="submit" value="보내기">
	</form>
	<hr>
	
	<h1>데이터 보내기3</h1>
	<form action="http://localhost:8080/studyProject/chapter03/send_data3">
		<input type="text" name="data1"><br>
		<input type="radio" name="data2" value="radio1">라디오1
		<input type="radio" name="data2" value="radio2">라디오2
		<input type="radio" name="data2" value="radio3">라디오3<br>
		<input type="submit" value="보내기">
	</form>
	<hr>
	
	<h1>데이터 보내기4</h1>
	<form action="http://localhost:8080/studyProject/chapter03/send_data4">
		<input type="text" name="data1"><br>
		<input type="checkbox" name="data2" value="check1">체크1
		<input type="checkbox" name="data2" value="check2">체크2
		<input type="checkbox" name="data2" value="check3">체크3<br>
		<input type="submit" value="보내기">
	</form>
</body>
</html>

 

네 가지 유형의 데이터를 꺼내보자

1. 클라이언트는 문자열과 숫자를 보낸다.

2. 클라이언트는 한 줄의 문자열과 여러 줄의 문자열을 보낸다.

3. 클라이언트는 문자열과 라디오 버튼으로 선택한 값을 보낸다.

4. 클라이언트는 문자열과 체크박스로 선택한 값들을 보낸다.


<< 1. 클라이언트는 문자열과 숫자를 보낸다. >>

[ 데이터 보내기1 ] 의 상황에 맞는 서블릿을 작성하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/send_data1")
public class SendData1 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String data1 = request.getParameter("data1");
		String data2 = request.getParameter("data2");
		
		System.out.println("data1 = " + data1);
		System.out.println("data2 = " + data2);
	}

}

 

아직은 보낼 데이터는 무조건 영문으로만 작성하자

아래와 같이 첫 번째 데이터로 영문, 두 번째 데이터로 숫자를 입력하고 보내기를 누르자

 

그럼 SendData1 서블릿이 동작하고 파라미터를 꺼냄

! 여기서 포인트 ! 클라이언트는 두 번째 데이터를 정수 123 으로 보냈지만 서버에서는 꺼내서 String 타입 변수에 담았음

getParameter 메서드는 위에서 설명했듯이 파라미터를 문자열로 반환하기 때문에 클라이언트가 정수로 보냈어도 서버에서는 문자열로 처리해야함

클라이언트가 보낸 값을 정수로 변환하고 싶다면 Integer.parseInt 메서드를 사용해야함


<< 클라이언트는 한 줄의 문자열과 여러 줄의 문자열을 보낸다. >>

[ 데이터 보내기2 ] 의 상황에 맞는 서블릿을 작성하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/send_data2")
public class SendData2 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String data1 = request.getParameter("data1");
		String data2 = request.getParameter("data2");
		
		System.out.println("data1 = " + data1);
		System.out.println("data2 = " + data2);
	}

}

 

아래와 같이 첫 번째 데이터로 영문, 두 번째 데이터도 영문을 입력하고 보내기를 누르자

 

그럼 SendData2 서블릿이 동작하고 파라미터를 꺼냄

! 여기서 포인트 ! 클라이언트는 두 번째 데이터를 여러 줄의 문자열로 보냈지만 서버에서는 꺼내서 String 타입 변수에 담았음

이렇게 클라이언트가 한 줄의 문자열로 보냈든 여러 줄의 문자열로 보냈든 getParamter 메서드로 꺼내기 때문에 String 타입 변수에 담아서 처리함

 

웹 페이지의 textarea에서 우리가 엔터를 친 부분이 서버로 보낼 때는 \n 으로 보내짐

( 슬라이드 이미지이니 옆으로 넘기면서 보세요 )

012

 

클라이언트가 보낸 여러 줄의 문자열을 한 줄 한 줄씩 사용하고 싶다면 split 메서드로 분리해야함

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/send_data2")
public class SendData2 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String data1 = request.getParameter("data1");
		String data2 = request.getParameter("data2");
		String[] data2s = data2.split("\n");
		
		System.out.println("data1 = " + data1);
		System.out.println("data2 = " + data2);
		for(int i=0; i<data2s.length; i++) {
			System.out.println(data2s[i]);
		}
	}

}

<< 클라이언트는 문자열과 라디오 버튼으로 선택한 값을 보낸다. >>

[ 데이터 보내기3 ] 의 상황에 맞는 서블릿을 작성하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/send_data3")
public class SendData3 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String data1 = request.getParameter("data1");
		String data2 = request.getParameter("data2");
		
		System.out.println("data1 = " + data1);
		System.out.println("data2 = " + data2);
	}

}

 

아래와 같이 첫 번째 데이터로 영문, 두 번째 데이터로 라디오 버튼 중 하나를 클릭하고 보내기를 누르자

 

그럼 SendData3 서블릿이 동작하고 파라미터를 꺼냄

! 여기서 포인트 ! 클라이언트는 두 번째 데이터를 라디오 버튼으로 보냈지만 서버에서는 꺼내서 String 타입 변수에 담았음

사실 클라이언트가 서버로 라디오 버튼을 보내는게 아니라 라디오 버튼의 name과 value로 보내는 것

 

그 다음 4번째 유형을 보기 전에 잠깐 여기서 한번 정리하자

지금까지 우리는 총 세가지 유형의 값을 보냈음

1. 클라이언트는 문자열과 숫자를 보낸다.

2. 클라이언트는 한 줄의 문자열과 여러 줄의 문자열을 보낸다.

3. 클라이언트는 문자열과 라디오 버튼으로 선택한 값을 보낸다.

 

그리고 이에 맞는 서블릿을 만들어 값을 받았음

서블릿들의 코드를 나란히 놓고 비교해보자

이 코드들의 차이점은?

( 클릭하면 큰 이미지로 볼 수 있습니다. )

 

없음

사실 전 이 서블릿을 만들 때 일일히 서블릿을 만들지 않고 SendData1 서블릿을 복붙하고 서블릿의 경로만 바꿨음

그 안에서 클라이언트가 보낸 값을 꺼내는 코드는 바꾸지 않았음

이렇게 클라이언트가 문자열을 보내든, 숫자를 보내든, 라디오 버튼의 선택지를 보내든 상관 없이 모두 파라미터를 보낸것이므로 getParameter 메서드로 꺼냄

매우 간단!


이제 마지막 유형을 보자

<< 클라이언트는 문자열과 체크박스로 선택한 값들을 보낸다. >>

[ 데이터 보내기4 ] 의 상황에 맞는 서블릿을 작성하자

( 이 서블릿은 앞의 세 서블릿과 많이 다르니 꼭 정확히 입력해야함 )

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/send_data4")
public class SendData4 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String data1 = request.getParameter("data1");
		String[] data2 = request.getParameterValues("data2");
		
		System.out.println("data1 = " + data1);
		
		System.out.print("data2 = ");
		for(int i=0; i<data2.length; i++) {
			System.out.print(data2[i] + ", ");
		}
	}

}

 

아래와 같이 첫 번째 데이터로 영문, 두 번째 데이터로 체크박스 들을 클릭하고 보내기를 누르자

 

그럼 SendData4 서블릿이 동작하고 파라미터를 꺼냄

! 여기서 포인트 ! 클라이언트는 두 번째 데이터를 체크박스로 보냈음

서버는 꺼낼 때 getParameter 메서드가 아닌 getParameterValues 메서드를 사용해 꺼냈음

또한 getParameterValues 메서드로 꺼내서 String 타입 배열에 담았음

 

체크박스는 여러 개를 선택해 보낼 수 있음

보낼 때는 여전히 name=value 형식으로 보내므로 같은 이름에 값이 담겨서 보내짐

체크박스로 보내는 파라미터는 getParameterValues 메서드로 꺼내야함

728x90
LIST

<< 학습 목표 >>

1. 클라이언트에서 GET, POST 요청 방식으로 서버에 요청할 수 있다.

2. 서버에서 GET, POST 요청 방식을 받을 수 있다.

3. GET, POST 방식의 특징에 대해서 설명할 수 있다.


서블릿은 클라이언트의 요청을 받는 컨트롤러의 역할을 한다고 했음

클라이언트는 주로 GET, POST, PUT, DELETE 방식 중 한 방식으로 요청을 함

 

서블릿이 GET 방식 요청을 처리할 때는 doGet 메서드를 오버라이딩 하면 됨

chapter03 패키지를 만들고 그 안에 다음과 같이 GET 방식 요청을 처리할 서블릿을 추가하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/get_servlet")
public class GetServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("클라이언트가 GET 방식으로 요청했음");
	}

}

클라이언트가 GET 방식으로 요청하는 방법은 다양한 방법이 있음

1. URL에 서블릿의 경로를 직접 입력

2. HTML의 a 태그

3. form 태그의 method 속성을 GET 으로 지정

4. 자바스크립트의 location.href

5. Jquery의 ajax의 type을 GET 으로 지정

굉장히 다양한 방법이 있지만 여기서는 3번 form 태그의 method 속성을 GET 으로 지정해 서버로 요청을 보내보자

 

webapp 폴더 안에 chapter03 폴더를 만들고 그 안에 getRequest.html 페이지를 만들어 아래 코드를 넣자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>GET 요청 페이지</title>
</head>
<body>
	<form action="http://localhost:8080/studyProject/chapter03/get_servlet" method="GET">
		<input type="number" name="firstNumber" placeholder="첫 번째 수">
		<select name="operator">
			<option>+</option>
			<option>-</option>
			<option>*</option>
			<option>/</option>
		</select>
		<input type="number" name="secondNumber" placeholder="두 번째 수">
		<input type="submit" value="결과 전송">
	</form>
</body>
</html>

이제 요청을 하면 get_servlet의 doGet 메서드가 동작해 이클립스의 [ Console ] 탭에 "클라이언트가 GET 방식으로 요청했음" 이라고 출력됨

 

GET 방식으로 요청할 때 특징을 알아보자

1. 클라이언트가 서버로 보내는 값이 URL의 뒤에 붙음

2. 클라이언트가 서버로 보낼 수 있는 값의 종류가 제한적임

3. 클라이언트가 서버로 보낼 수 있는 값의 크기가 제한적임

 

getRequest.html 페이지에 접근해 두 값을 입력하고 연산자를 선택한 후 [ 결과 보기 ] 를 눌러보자

그 후 브라우저 URL을 보면 다음과 같이 보일 것

 

1. 클라이언트가 서버로 보내는 값이 URL의 뒤에 붙음

[ 결과 보기 ] 를 누르면 

http://localhost:8080/studyProject/chapter03/get_servlet 로 요청이 들어가는데 그때 클라이언트가 서버로 보내는 값이 URL의 뒤에 붙음

형식을 보면 URL의 뒤에 ? 가 붙고 그 뒤에 name=value&name=value&... 의 형식으로 붙음

또한 보내는 값 중 operator를 보면 값(value)이 %2B 로 되어있는데 이렇게 GET 방식으로 서버로 보낼 때 영문, 숫자를 제외한 특수문자, 한글 등은 모두 다른 형태로 변환되 전달됨

형태만 다른거지 값은 같은 것 따라서 서버에서는 operator의 값을 다시 원래의 형태로 변환해 사용함

 

2. 클라이언트가 서버로 보낼 수 있는 값의 종류가 제한적임

GET 방식으로 서버에 보낼 수 있는 값은 숫자, 문자열 등 단순한 형태의 데이터임

나중에 파일을 서버로 보내야하는데 파일은 GET 방식으로 보낼 수 없음

 

3. 클라이언트가 서버로 보낼 수 있는 값의 크기가 제한적임
크기가 얼마나 제한적인지는 딱 짚어서 말할 수 없음

그 이유는 클라이언트 프로그램(웹 브라우저)에 따라서 보낼 수 있는 값의 크기가 다르기 때문에...

따라서 "크기가 제한적이다" 라고만 기억하면 됨


서블릿이 POST 방식 요청을 처리할 때는 doPost 메서드를 오버라이딩 하면 됨

chapter03 패키지 안에 다음과 같이 POST 방식 요청을 처리할 서블릿을 추가하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/post_servlet")
public class PostServlet extends HttpServlet {
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("클라이언트가 POST 방식으로 요청했음");
	}

}

 

 

클라이언트가 POST 방식으로 요청하는 방법은 다양한 방법이 있음

1. form 태그의 method 속성을 POST 로 지정

2. Jquery의 ajax의 type을 POST 로 지정

3. 제 3의 프로그램(Third Party Program)을 사용해 POST 로 요청

굉장히 다양한 방법이 있지만 여기서는 1번 form 태그의 method 속성을 POST 로 지정해 서버로 요청을 보내보자

 

webapp 안에 chapter03 안에 postRequest.html 페이지를 만들어 아래 코드를 넣자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>POST 요청 페이지</title>
</head>
<body>
	<form action="http://localhost:8080/studyProject/chapter03/post_servlet" method="POST">
		<input type="number" name="firstNumber" placeholder="첫 번째 수">
		<select name="operator">
			<option>+</option>
			<option>-</option>
			<option>*</option>
			<option>/</option>
		</select>
		<input type="number" name="secondNumber" placeholder="두 번째 수">
		<input type="submit" value="결과 전송">
	</form>
</body>
</html>


이제 요청을 하면 post_servlet의 doPost 메서드가 동작해 이클립스의 [ Console ] 탭에 "클라이언트가 POST 방식으로 요청했음" 이라고 출력됨

 

POST 방식으로 요청할 때 특징을 알아보자

1. 클라이언트가 서버로 보내는 값이 URL에 보이지 않음

2. 클라이언트가 서버로 보낼 수 있는 값의 종류에 제한이 없음

3. 클라이언트가 서버로 보낼 수 있는 값의 크기에 제한이 없음

 

1. 클라이언트가 서버로 보내는 값이 URL에 보이지 않음

[ 결과 보기 ] 를 누르면 

http://localhost:8080/studyProject/chapter03/post_servlet 로 요청이 들어가는데 그때 클라이언트가 서버로 보내는 값이 보이지 않음

POST 방식으로 데이터를 보낼 때는 아래 요청 정보와 같이 몸통(body) 에 담겨져 보냄

 

2. 클라이언트가 서버로 보낼 수 있는 값의 종류에 제한이 없음

POST 방식으로 보낼 수 있는 데이터는 숫자, 문자열 등 외에도 파일도 보낼 수 있음

나중에 서버로 파일을 보낼 때는 POST 방식으로 보내게 될 것

 

3. 클라이언트가 서버로 보낼 수 있는 값의 크기에 제한이 없음

 

여기까지 GET 방식과 POST 방식을 비교해보면 마치 GET 방식이 나쁜것 같고 POST 방식이 좋은것같지만 요청 방식에 나쁘다 좋다는 없음

상황에 따라서 GET 방식으로 보내야할 경우가 있고 POST 방식으로 보내야 할 경우가 있음


지금까지는 서블릿 하나 당 요청 방식 하나씩 처리하도록 했음

이번에는 서블릿 하나가 GET, POST 요청 방식 모두를 처리하도록 해보자

 

chapter03 패키지 안에 다음과 같이 GET, POST 방식 요청을 처리할 서블릿을 추가하자

package chapter03;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/chapter03/both_servlet")
public class BothServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("BothServlet -> 클라이언트가 GET 방식으로 요청함");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("BothServlet -> 클라이언트가 POST 방식으로 요청함");
	}

}

 

webapp 안에 chapter03 안에 postRequest.html 페이지를 만들어 아래 코드를 넣자

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>GET, POST 요청 페이지</title>
</head>
<body>
	<h1>GET 방식 요청</h1>
	<form action="http://localhost:8080/studyProject/chapter03/both_servlet" method="GET">
		<input type="number" name="firstNumber" placeholder="첫 번째 수">
		<select name="operator">
			<option>+</option>
			<option>-</option>
			<option>*</option>
			<option>/</option>
		</select>
		<input type="number" name="secondNumber" placeholder="두 번째 수">
		<input type="submit" value="결과 전송">
	</form>
	
	<br>
	
	<h1>POST 방식 요청</h1>
	<form action="http://localhost:8080/studyProject/chapter03/both_servlet" method="POST">
		<input type="number" name="firstNumber" placeholder="첫 번째 수">
		<select name="operator">
			<option>+</option>
			<option>-</option>
			<option>*</option>
			<option>/</option>
		</select>
		<input type="number" name="secondNumber" placeholder="두 번째 수">
		<input type="submit" value="결과 전송">
	</form>
</body>
</html>

 

이 페이지의 두 form 을 보면 똑같은 서블릿으로 요청을 하고 있음

대신 첫 번째 form은 GET 방식으로 요청하고 있고 두 번째 form은 POST 방식으로 요청하고 있음

GET 방식 요청의 [ 결과 전송 ] 과 POST 방식 요청의 [ 결과 전송 ] 을 눌러보면 both_servlet이 모두 요청을 처리하는 것을 알 수 있음

이렇게 서블릿이 요청 방식 하나만 처리할 수도 있고 GET, POST 요청 방식 모두를 처리할 수도 있음


클라이언트가 서버로 데이터를 전달할 때 GET과 POST가 보내는 방식은 다르지만 결국에는 서버로 데이터를 전달하는 것

이렇게 클라이언트가 서버로 전달하는 데이터를 파라미터(Parameter) 라고 부름

위 프로그램에서 클라이언트는 서버로 firstNumber, operator, secondNumber 파라미터를 보낸 것


이외에 클라이언트가 PUT, DELETE 방식으로 요청했을 때도 봐야하나 "저는" PUT, DELETE 방식은 여러 사정 상 사용하지 않기로 했음

여러 사정에 대해 알고 싶다면 아래 블로그를 들어가보길

https://goldswan.tistory.com/42

 

[Spring]Spring에서 PUT, DELETE Method 사용하기

서론 진행하고 있던 Spring 사이드 프로젝트에서 RESTful 하고 싶은 HTTP API를 만들기 위해 put, delete HTTP Method를 사용하려 했습니다. 단순히 form 태그 안 method 속성을 "put", "delete"로 바꾸고 요청을 시도

goldswan.tistory.com

728x90
LIST