eyesofkhepri

03-3. x-www-form-urlencoded 본문

NetProgram

03-3. x-www-form-urlencoded

eyesofkhepri 2015. 9. 30. 13:51

x-www-form-urlencoded

웹 설계 당시에 웹을 설계 하는 사람들은 각 운영체제의 차이점을 처리해야 하는 과제에 직면 했다. 왜냐하면 이 문제는 URL을 사용함에 있어서 문제를 발생시키고 있었기 때문이다. 예를 들자면 몇몇 운영체제는 파일 이름에 공백이 허용되지만 어떤건 되지 않았고, 어떤 운영체제는 파일이름에 # 기호가 허용되지만 URL에서 #은 부위 지정자 역할을 하고 있었으며 웹이 처음에 만들어 졌을때는 유니코드가 널리 사용되지 않았기에 한글, 한자, 중국어 등등의 문자를 처리할 수 없었기 때문이였다. 

이러한 문제를 해결하고자 URL에서 사용될 문자들은 다음과 같이 정해진 일부 아스키 문자 집합으로 표현되어야 했다.


- 대문자 A-Z

- 소문자 a-z

- 숫자 0~9

- 문장부호 문자 - _ . ! ~ * ' ,


만약 / & ? @ # ; $ + = %같은 특수 한 목적의 문자나 한글, 한자, 중국어 같은 문자를 처리하고 하는 경우는 어떻게 해야할 것인가? 현재는 각각을 모두 인코딩해서 사용하고 있다.


이런식으로 인코딩된 형식을 x-www-form-urlencoded 형식이라 한다.


인코딩은 간단하게 이루어진다. 위에 명시한 4개의 문자 집합을 제외한 나머지 문자들은 모두 Byte로 변환되고 변환된 바이트들은 %기호와 두개의 16진수로 표기된다. 스페이스 경우는 자주 사용되기 때문에 %20으로 고정이 되어있다. 또한 +기호도 %2B로 인코딩 된다. / # = & ? 문자는 URL요소를 구분하는 용도의외에 쿼리문자열로 사용되는 경우는 동일하게 인코딩된다.


Java에서는 이런 인코딩을 해주는 URLEncoder와 디코딩을 해주는 URLDecoder를 지원해준다.

1. URLEncoder

URLEncoder를 통해서 인코딩을 할 수 있다.


public static void main(String[] args) {
	/**
	 * String encode(String s, String enc) : 비아스키 문자를 enc로 인코딩 하며 '/','&','=',':'등의 문자를 퍼센트인코딩 하며 띄어쓰기는 '+'로 인코딩한 결과를 리턴한다.
	 */
	try {
		System.out.println(URLEncoder.encode("Encode String*Test%One+Two/Three\"Four:Five~Six(Teen)Seven.Eight=Nine&Ten킹", "UTF-8"));
	} catch (UnsupportedEncodingException e) {
		System.err.println(e);
	}
}


하지만 encode()메소드는 URL의 각 구성 요소를 구분하지 않고 모두 인코딩 해버린다. 결국 한 URL을 통으로 인코딩하면 안되며 각 구성요소를 찾아서 그 각 요소를 인코딩 해줘야 한다. 보통 GET 메소드를 통해서 서버 측 프로그램과 통신을 위한 쿼리 문자열을 만드는데 URLEncoder를 많이 사용하므로 잘 알아 두어야 한다.


public class GenQueryString {
	private final String ENCODE = "UTF-8";
	private StringBuilder query = new StringBuilder();
	
	
	public GenQueryString() {}
	
	public synchronized void add(String name, String value) {
		query.append('&');
		encode(name, value);
	}
	
	private synchronized void encode(String name, String value) {
		try {
			query.append(URLEncoder.encode(name, ENCODE));
			query.append('=');
			query.append(URLEncoder.encode(value, ENCODE));
			
		} catch (UnsupportedEncodingException e) {
			System.err.println(e);
		}
	}
	
	public synchronized String getQuery() {
		return query.toString();
	}
	
	@Override
	public String toString() {
		return getQuery();
	}
	
	public static void main(String[] args) {
		//https://www.youtube.com/watch?v=UhC7M8KF7AE&list=RDpIw7RAfYgI8&index=2&line=I/O 변환
		GenQueryString qs = new GenQueryString();
		qs.add("v", "UhC7M8KF7AE");
		qs.add("list", "RDpIw7RAfYgI8");
		qs.add("index", "2");
		qs.add("line", "I/O");
		String url = "https://www.youtube.com/watch?" + qs;
		System.out.println(url);
	}
}

2. URLDecoder

URLDecoder는 x-www-form-url-encoded 형식으로 인코딩된 문자열을 디코딩하는 decode()메소드를 제공해준다. decode()는 인코딩 되지 않은 문자들은 디코드 해주지 않기때문에 URLEncode.encode()와는 다르게 모든 통 URL을 한번에 전달해서 처리 할 수 있다.


public static void main(String[] args) {
	/**
	 * String decode(String s, String enc) : encode된 string을 decode해서 결과를 리턴한다. +는 스페이스로, %16진수는 원래 값으로 디코드 한다.
	 */
	try {
		String encodeUrl = "https://www.youtube.com/watch?&v=UhC7M8KF7AE&list=RDpIw7RAfYgI8&index=2&line=I%2FO";
		String decodeUrl = URLDecoder.decode(encodeUrl, "UTF-8");
		System.out.println("decodeUrl is " + decodeUrl);
	} catch (UnsupportedEncodingException e) {
		System.err.println(e);
	}
}


Comments