이전글

 

HTTP 요청 방식에 따른 GET과 POST 방식 차이
웹 환경에서는 브라우저에서 서버로 요청 파라미터를 전송할 때 크게 GET방식과 POST 방식 두 가지로 데이터를 전송하게 됩니다.
GET방식의 경우에는 HTTP 메시지 BODY가 없기때문에 URL 뒤에 ? 를 붙이고 그 뒤에 요청파라미터를 전송하며, POST 방식의 경우 HTTP 메시지 BODY 에 요청 데이터를 넣어 전송합니다.
URL에는 길이 제한이 있기때문에 GET방식의 경우 데이터 전송시 데이터 길이에 제한이 있으며,(브라우저나 웹서버에 따라 제한이 없는 경우도 있음) 브라우저 URL 창에 요청 데이터가 노출되는 등의 단점이 있습니다.
따라서 중요한 데이터들은 POST방식으로 전송하며 간단한 요청의 경우에 GET방식 요청을 사용합니다.

다음의 경우 formTest.jsp에서 입력한 데이터를 paramTest.jsp 로 전송하는 예제입니다.
소스는 중요하지 않습니다. 여기서는 전송되는 HTTP 메시지를 보고 GET방식과 POST 방식에서 데이터가 어느 영역에 추가되어 전송되는지의 차이만 확인하면 됩니다.


GET 방식 요청
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: ko-KR
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive
Cookie: JSESSIONID=10FAC7F063351C4847113E226B25F093

POST 방식 요청
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: ko-KR
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Content-Length: 102
Host: localhost:8080
Connection: Keep-Alive
Pragma: no-cache
Cookie: JSESSIONID=10FAC7F063351C4847113E226B25F093

 

userName=%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC&age=19&hobby=%EC%9A%B4%EB%8F%99&hobby=%EB%8F%85%EC%84%9C



HTTP 인코딩
GET방식과 POST 방식에서 요청 데이터 전송 방법의 차이를 아셨을 것입니다.
그런데 자세히 보면 입력한 이름과 취미 데이터가 이상한 데이터로 인코딩 되어 전송되는 것을 발견할 수 있는데, 이는 RFC 2396 이라는 규칙에 따라 인코딩 되었기 때문입니다. RFC 2396 규칙은 간단히 설명하자면 알파벳과 숫자는 그대로 사용하며, 공백(스페이스) 는 + 로 표혆고 특수문자 및 알파멧 외의 문자들은 %HC 형태로 %를 붙여 표현한다는 규칙입니다.

위의 예제에서는 전송 데이터에 한글이 포함되었기 때문에 UTF-8 캐릭터셋을 기준으로 RFC 2396 규칙에 맞게 인코딩 된 것입니다.
웹서버에서는 이 데이터를 사용하기 위해서는 인코딩 된 규칙에 따라서 다시 디코딩하여 원본 데이터를 구하여 사용합니다.


따라서 웹서버에서는 클라이언트(브라우저) 에서 인코딩에 사용한 캐릭터셋(여기서는 UTF-8) 을 이용하여 디코딩해야 하며, 클라이언트에서 사용한 인코딩 규칙과 서버에서 사용한 디코딩 규칙이 다른 경우에는 데이터가 깨지는 일이 발생할 수도 있습니다.



브라우저에서 데이터 전송시 인코딩 규칙
위에서는 브라우저가 한글 데이터를 서버로 전송할 때 UTF-8 캐릭터셋을 사용했습니다.
그렇다면 브라우저는 어떤 규칙에 의하여 인코딩 캐릭터셋을 선택하는 것일까요?
브라우저의 전송 데이터 인코딩 규칙은 GET방식 전송과 POST 방식 전송에 따라 달라집니다.

POST 방식으로 전송하는 경우
먼저 POST 방식으로 데이터를 전송하는 경우입니다.
POST 방식으로 데이터를 전송하는 경우 현재 페이지가 어떤 인코딩을 사용하는지에 따라 결정됩니다.

데이터를 입력하는 화면은 formTest.jsp 입니다.
최초 서버에 http://localhost:8080/myApp/formTest.jsp를 요청했을 때 서버는 HTTP 응답 메시지 헤더의 Content-Type 속성을 통해 UTF-8로 인코딩된 페이지 라는 것을 명시해 주었습니다.

다음은 폼 입력 페이지인 formTest.jsp 페이지를 서버에 요청했을 당시 서버가 응답한 HTTP 응답 메시지입니다.
브라우저는 응답한 HTTP 메시지의 본문 HTML을 바탕으로 화면을 그리며, 이후 폼에 입력한 데이터를 전송할 때에는 응답 메시지의 Conent-Type 헤더 값을 바탕으로 데이터를 인코딩 하여 전송 합니다.
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Length: 563
Date: Sun, 11 Feb 2018 06:28:27 GMT

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>정보 입력 </title>
</head>
<body>
        
        <form action="paramTest.jsp" method="GET">
               이름 : <input type="text" name="userName"><br>
               나이 : <input type="text" name="age"><br><br>
               취미 선택 <br>
               <input type="checkbox" name="hobby" value="운동">운동
               <input type="checkbox" name="hobby" value="독서">독서
               <input type="checkbox" name="hobby" value="요리">요리 <br><br>
               <input type="submit" value="프로필전송">              
               
        </form>
        
</body>
</html>


위와 같이 페이지를 인코딩 하기 위해서 JSP의 경우 page디렉티브의 contentType 속성을 통해 설정해 줄 수 있습니다.
1
<%@ page language="java" contentType="text/html; charset=UTF-8"%> 
cs

Servlet의 경우 response 객체를 이용할 수 있습니다.
1
response.setContentType("text/html; charset=UTF-8");
cs
 

위와 같이 응답하는 데이터에 대해 특별히 인코딩 방식을 명시해주지 않은 경우 톰캣은 기본적으로 ISO-8859-1 인코딩을 사용하는데, 이 캐릭터셋은 한글을 표현할 수 없습니다. 따라서 한글을 출력하는 경우 한글이 깨지게 되며, 브라우저는 POST 방식으로 당 페이지에서 한글을 입력하여 서버로 전송하는 경우에도 ISO-8859-1 캐릭터셋을 사용하기 때문에 데이터가 깨지게 됩니다.



GET방식으로 전송하는 경우
사실 HTTP 표준에는 GET방식으로 데이터를 서버에 전송하는 경우에 어떤 규칙에 의해 인코딩 해야 하는지에 대한 사항이 정의되어 있지 않습니다.
따라서 브라우저마다 데이터를 GET방식로 전송할때 사용하는 캐릭터셋이 다를 수 있으며, 웹서버측에서도 GET방식 요청에 대한 처리가 제각각입니다.

그렇다고 해도 브라우저에서 GET방식으로 데이터를 전송할때에는 크게 세 가지 분류에 따른 규칙이 있습니다.

전송 방법
인코딩 방법
웹 브라우저 주소표시줄에서 직접 URL을 입력하여 전송하는 경우
웹 브라우저별로 인코딩 방법이 다름
폼에 데이터 입력 후 전송하는 경우(GET 방식) 현재 페이지를 서버로부터 응답받을 때 HTTP 메시지 헤더의 Content-Type 값에 명시된 캐릭터셋 사용
<a> 태그의 href 속성의 URL에 입력된 요청 파라미터를 전송하는 경우
현재 페이지를 서버로부터 응답받을 때 HTTP 메시지 헤더의 Content-Type 값에 명시된 캐릭터셋 사용
<a> 태그 사용하여 전송하는 경우와 입력 폼을 통해 데이터 전송하는 경우에는 입력폼을 이용해 POST 방식으로 전송하는 경우와 같습니다.(위 내용 참고)
그러나 웹 브라우저의 주소표시줄에서 직접 URL을 입력하여 전송하는 경우에는 브라우저 별로 인코딩에 사용하는 캐릭터셋이 다릅니다.

인터넷 익스플로러(IE)에서는 MS949 라는 캐릭터셋을 사용하는데 이는 EUC-KR을 확장한 마이크로소프트에서 만든 캐릭터셋입니다.
크롬의 경우 최신버전은 기본적으로 UTF-8을 사용합니다.
이밖에도 주소표시줄을 이용하는 경우에는 브라우저의 종류나 버전에 따라 인코딩 규칙이 달라집니다.



톰캣에서 브라우저가 보낸 데이터 디코딩 처리
지금까지의 내용을 정리하자면 브라우저에서 요청 데이터를 서버에 보낼 때 규칙에 따라 데이터를 인코딩하며, 서버에서는 해당 데이터를 인코딩 된 규칙에 따라 다시 디코딩하여 사용해야 한다는 것 입니다.

여기서는 브라우저가 인코딩하여 보낸 데이터를 디코딩하는 방법을 알아보도록 하겠습니다.
브라우저와 마찬가지로 클라이언트로부터 받은 데이터를 디코딩하는 규칙 또한 POST방식과 GET방식에 따라 다릅니다.

POST 방식으로 요청한 데이터 디코딩
POST방식의 요청 데이터를 디코딩하기 위해서는 request 객체의 인코딩 설정을 변경해주면 됩니다.
주의할 점은 request의 getParameter() 메서드를 통해 데이터를 얻어오기 이전에 설정해 주어야 한다는 사실입니다.
1
2
3
4
5
     //POST 방식일때 요청 파라미터 디코딩에 사용될 캐릭터 셋 설정 
     request.setCharacterEncoding("utf-8"); 
     //꼭 setCharacterEncoding() 설정 이후에 값을 얻어와야 캐릭터셋이 적용된다. 
     request.getParameter("userName"); 
     request.getParameter("age");  
cs
 

request 객체는 JSP와 Servlet 모두 HttpServletRequest 클래스 이므로 자세한 사항은 다음의 글을 참고합니다.


GET 방식으로 요청한 데이터 디코딩
서블릿 스펙에 따르면 setCharacterEncoding() 메서드의 경우 HTTP 프로토콜의 데이터 영역에 대한 데이터의 인코딩 설정에만 사용되기 때문에 GET방식의 URL을 통해 넘어온 요청 파라미터는 처리하지 못합니다. 톰캣8의 경우 기본적으로 GET방식을 통해 넘어온 데이터를 UTF-8로 처리 하도록 구현되어 있지만 이전 버전의 경우에는 기본값으로 ISO-8859-1 캐릭터셋을 사용합니다.

따라서 톰캣8 이전의 버전에서 GET방식의 요청 파라미터를 한글 처리하는 경우 톰캣의 server.xml 설정파일을 수정하여 직접 변경해 주어야 합니다.


톰캣 설정 변경을 위한 server.xml 수정
server.xml 파일은 [톰캣설치폴더]\conf 디렉터리 하위에 위치합니다. (예: c:\tomcat7\conf\server.xml)
이클립스 IDE의 경우 Project Explorer 뷰나 Package Explorer 뷰의 Servers\가상서버명-config\server.xml 을 참고합니다.



server.xml 파일을 열고 다음과 같이 port가 8080인 Connector 태그를 찾아 userBodyEncodingForURI 설정을 true로 변경해줍니다.
이렇게 변경하면 POST 방식에서 사용하는 setCharacterEncoding() 설정을 GET방식 인코딩 처리에도 사용하게 됩니다.
    <Connector connectionTimeout="20000"
                    port="8080"
                    protocol="HTTP/1.1"
                    redirectPort="8443"
                    useBodyEncodingForURI="true"/>


혹은 GET방식만의 인코딩 설정을 따로 명시해주고 싶은 경우 다음과 같이 URIEncoding 값에 인코딩 캐릭터셋을 설정합니다.
    <Connector connectionTimeout="20000"
                    port="8080"
                    protocol="HTTP/1.1"
                    redirectPort="8443"
                    URIEncoding="utf-8"/>
블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

댓글을 달아 주세요! 질문 환영합니다!