필요한  오픈 컴포넌트

ajaxfileupload.js

http://www.phpletter.com/Our-Projects/AjaxFileUpload/

 

 

  스크립트 부분

 function ajaxFileUpload(index)
{
 var filePath = document.fileUploadForm.elements["file_img_"+index].value;
 if ( !(filePath.match(/\.(gif|jpg|jpeg|png)$/i)) ){ 
  modal.alert("이미지 파일을 선택해주세요.");
  return true;
 }
 
 $.ajaxFileUpload
 (
  {
   url:'주소',
   secureuri:false,
   fileElementId:'file_img_'+index,
   dataType: 'json',    
   success: function (data, status)
   {
       //처리프레서스

      //data  json 객체 이미 처리되어 넘어옴
     },
   error: function (data, status, e)
   {
    alert(e);
   }
  }
 )
 return false;
}

 

# 작동 방식

페이지에 파일 input 박스를 찾는다 [이름지정]

그후 아이프레임 만든후 넘어온 데이터를 success에다가 데이터를 넣어준다.

 

ps : iframe가 안돼는 부라우저에서는 실행 불가능할것으로 예상된다.

 

 

참고 자료

http://whitememo.tistory.com/167

http://malsup.com/jquery/form/progress3.html

 

 


인터넷 익스플로러에서 작업을 하는 중에,
AJAX로 만들어진 요청이 계속해서 같은 값만을 불러 오는 경우가 발생..

익스플로러에서 같은 파라미터 값을 갖는 URL 요청을,
캐쉬되어 미리 저장하고 있던 페이지로만 반복해서 리턴해서 발생한 문제였다.

이러한 문제의 해결법은, 아래와 같은 방법이 있을 수 있겠다.

response.setDateHeader("Expires", -1);
response.setHeader("Pragma", "no-cahce");
response.setHeader("Cache-Control", "no-store"); //HTTP 1.0
response.setHeader("Cache-Control", "no-cache"); //HTTP 1.1

또는,

ajax 요청에 사용되는 URL 끝에 유니크한 파라미터 값을 붙여서 날리는 방법이 있다.

ex) Math.round(Math.random()* (new Date().getTime())); :)

참고 :
http://savour.tistory.com/tag/cache-control
스크립트단

escape(encodeURIComponent('한글 파라메타값'))

java단

URLDecoder.decode("받은 데이터","UTF-8")
 


난이도 : 초급

Brett McLaughlin, Author and Editor, O'Reilly Media Inc.

2007 년 5 월 02 일

평이한 텍스트와 XML은 비동기식 애플리케이션에서 정보를 송수신 할 때 사용할 수 있는 데이터 포맷입니다. Ajax 마스터하기 시리즈에서는 또 다른 유용한 데이터 포맷인 JavaScript Object Notation (JSON)에 대해 알아보고, 이것이 애플리케이션에서 데이터와 객체들을 어떻게 이동시키는지를 설명합니다.

여러분이 본 시리즈를 오랫동안 읽어왔다면, 데이터 포맷에 대한 지식도 많이 쌓였을 것이다. 이전 기술자료에서는 평이한 텍스트와 간단한 name/value 쌍이 많은 비동기식 애플리케이션에서 어떤 역할을 하는지를 살펴보았다. 여러분은 다음과 같은 데이터를 조합할 수 있다.

firstName=Brett&lastName=McLaughlin&email=brett@newInstance.com

더 이상 무엇을 할 필요가 없다. 사실, 웹 고수들은 이것이 GET 요청을 통해 보내지는 정보용 포맷이라는 것을 알고 있다.

그리고 나서, 본 시리즈에서는 XML에 대해서 다루었다. 확실한 것은 XML은 부정적인 측면과 긍정적인 측면 모두에서 정당한 평가의 몫을 받았고, 이러한 것이 Ajax 애플리케이션에서도 나타나는 것은 그리 놀랄 일이 아니다. 본 시리즈의 지난 기술자료들에서 XML이 대안 데이터 포맷들을 어떻게 제공하는지를 파악하기 바란다.

<request>
  <firstName>Brett</firstName>
  <lastName>McLaughlin</lastName>
  <email>brett@newInstance.com</email>
</request>

이것은 여러분이 위해서 보았던 것과 같은 데이터이지만, XML 포맷으로 저장되어 있다. 그 외에 특징적인 것은 없다. 평이한 텍스트와 name/value 쌍 대신에 XML을 사용할 수 있는 또 하나의 데이터 포맷일 뿐이다.

이 글에서는 또 다른 데이터 포맷인 JavaScript Object Notation(JSON)에 대해 살펴보겠다. JSON은 여러분이 이미 보았던 것과 비슷한 부분이 있고, 어떤 부분은 생소하다. 이것은 여러분에게 또 다른 선택권을 줄 것이며, 그 선택은 그렇게 나쁘지 않다.

선택할 수 있는 권한

JSON 포맷에 대해 상세히 설명하기 전에, 특히, 평이한 텍스트에서 XML과 name/value 쌍으로 작업하는 방법을 이미 알고 있다면, 다양한 데이터 포맷을 다룬 기술자료들을 먼저 읽어보기 바란다.(다음 글에서도 JSON에 대해 다룰 것이다.) 이유는 간단하다. 여러분에게 선택권이 많이 주어지고 문제에 대한 옵션들이 많아질수록, 단 하나의 솔루션 보다는 문제에 대한 최상의 솔루션을 찾을 수 있는 더 좋은 기회들이 생기기 때문이다.

name/value 쌍과 XML

본 시리즈에서는 name/value 쌍이 적합한 상황과 XML을 사용하기에 적합한 상황에 대해 이미 다루었다. 거듭 말하지만, 여러분은 우선 name/value 쌍을 사용하는 것을 늘 생각해야 한다. 이것은 대부분의 비동기식 애플리케이션에서 생기는 문제들에 대한 가장 간단한 솔루션이고, JavaScript에 대한 기본적인 지식만 있어도 간단히 해결된다.

여러분은 XML로 전향하는데 제약이 없다면 대안 데이터 포맷을 사용하는 것에 관해 걱정할 필요가 없다. 확실히, XML 포맷의 입력을 요하는 서버 측 프로그램으로 데이터를 보낸다면, 데이터 포맷으로 XML을 사용해야 한다. 대부분의 경우, XML은 애플리케이션에 여러 정보 조각들을 보내야 하는 서버용으로 적합하다. 다시 말해서, XML은 Ajax 애플리케이션으로부터의 요청 보다는, Ajax 애플리케이션으로의 응답으로 더 일반적으로 사용된다.

JSON 추가하기

name/value 쌍 또는 XML을 사용할 때, JavaScript를 사용하여 애플리케이션에서 데이터를 가져다가, 이것을 데이터 포맷에 채워 넣는다. 이 경우, JavaScript는 데이터 조작 언어로서의 역할을 하고, 웹 폼에서 데이터를 이동시키고 조작하며, 이것을 서버 측 프로그램에 쉽게 보내질 수 있는 포맷에 넣는다.

하지만, 단순한 포맷 언어 이상으로 JavaScript를 사용해야 할 때가 있다. 이러한 경우에, JavaScript 언어의 객체를 사용하여 데이터를 표현하고, 웹 폼에서 데이터를 가져다가 요청을 한다. 이러한 상황에서, JavaScript에 있는 객체에서 데이터를 추출하고 그 데이터를 name/value 쌍 또는 XML로 채우는 것이 일이다. 이때에 JSON이 빛을 발한다. JavaScript 객체를 (동기식 또는 비동기식) 요청의 일부로 보내질 수 있는 데이터로 쉽게 변환할 수 있다.

기본적으로 JSON은 문제해결의 특효약은 아니다. 하지만, 매우 특수한 상황에 있어서 훌륭한 옵션이 된다. 그러한 상황에 절대로 놓이지 않을 것이라고 가정하지 말고, 이 글과 다음 글을 읽으면서 JSON을 배워가기 바란다. 그러한 유형의 문제에 직면할 때를 대비한다고 생각하면 좋을 것이다.




위로


JSON 기초

JSON으로는 JavaScript 객체로 표현된 데이터를 한 함수에서 다른 함수로, 또는 비동기식 애플리케이션의 경우, 웹 클라이언트에서 서버 측 프로그램으로 쉽게 전달할 수 있는 스트링으로 변형할 수 있다. 문자열이 약간 이상해 보이지만 JavaScript에 의해 쉽게 인터프리팅 되고, JSON은 name/value 쌍 보다 복잡한 구조도 표현한다. 예를 들어, 단순한 키와 값 리스트 대신, 배열과 복합 객체들을 나타낼 수 있다.

JSON 예제

JSON에서는 name/value 쌍이 다음과 같이 표현된다.

{ "firstName": "Brett" } 

이는 매우 기본적인 것이고, 텍스트의 name/value 쌍 보다는 더 많은 공간을 차지한다.

firstName=Brett

하지만, JSON은 여러 name/value 쌍들을 하나로 연결할 때 진가를 발휘한다. 우선, 다음과 같이, 여러 name/value 쌍으로 데이터 레코드를 생성할 수 있다.

{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" }

신택스의 관점에서 보면 name/value 쌍 보다 나은 점이 없어 보이지만, 이 경우, JSON은 훨씬 더 사용하기 쉬우며, 가독성도 놀랍다. 예를 들어, 위 세 개의 값들은 같은 레코드의 일부이다. 중괄호는 그 값이 같은 커넥션을 갖고 있다는 것을 표시하고 있다.

값들의 배열

값을 나타내야 할 때, JSON은 보다 읽기 쉽고, 덜 장황하다. 예를 들어, 인명부가 있다고 해보자. XML에서는, 수 많은 오프닝/클로징 태그에 둘러싸이게 되고, 전형적인 name/value 쌍을 사용한다면, 독점적인 데이터 포맷을 사용해야 하거나, person1-firstName처럼 키 네임을 수정해야 한다.

JSON에서는 다음과 같이 괄호를 사용하여 레코드를 그룹핑 할 수 있다.

{ "people": [
  { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },
  { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },
  { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }
]}

이해하기도 어렵지 않다. 이 경우, people이라는 하나의 변수가 있고, 값은 세 개의 아이템을 포함하고 있는 배열이며, 각각의 레코드에는 이름, 성, 이메일 주소가 있다. 위 예제는 레코드들을 모두 투입하는 방법과, 아이템을 괄호가 있는 싱글 값으로 그룹핑 하는 방법을 설명하고 있다. 물론, 같은 신택스를 사용할 수 있지만, 여러 값들(각각 여러 레코드들을 갖고 있음)을 갖고 있다.

{ "programmers": [
  { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },
  { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },
  { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }
 ],
"authors": [
  { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },
  { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },
  { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }
 ],
"musicians": [
  { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },
  { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
 ]
}

여기에서 주목해야 할 점은 각각이 다수의 값을 내포하고 있는 많은 값들을 표현할 수 있는 당신의 능력이다. 또 하나 주목해야 할 점은 레코드의 name/value 쌍들은 다른 메인 항목(programmers, authors, musicians)에 따라 변한다는 것이다. JSON은 완전히 동적이고, JSON 구조 안에서 데이터를 표현하는 방식을 바꿀 수 있다.

또 한 가지 알아두어야 할 것은 JSON 포맷 데이터로 작업할 때 제약 조건이 없다는 점이다. 따라서, 어떤 것을 표현하는 방식을 바꿀 수 있고, 심지어는 같은 데이터 구조 내에서 같은 것을 다른 방식으로 나타낼 수도 있다.




위로


JavaScript에서 JSON 사용하기

JSON 포맷을 다룬 후라면, JavaScript에서 이것을 사용하는 것은 간단하다. JSON은 네이티브 JavaScript 포맷이고, JavaScript 내에서 JSON 데이터와 작업하기 위해 특별한 API나 툴킷이 필요 없다.

JSON 데이터를 변수에 할당하기

예를 들어, 새로운 JavaScript 변수를 만들고, JSON 포맷 데이터 스트링을 여기에 직접 할당한다고 해보자.

var people =
  { "programmers": [
    { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },
    { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },
    { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }
   ],
  "authors": [
    { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },
    { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },
    { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }
   ],
  "musicians": [
    { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },
    { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
   ]
  }

복잡하지 않다. people에는 이제 JSON 포맷 데이터가 포함되어 있다. 하지만, 많은 것을 수행하지 않는다. 데이터는 여전히 유용한 포맷으로 되어있지 않다.

데이터에 액세스 하기

위의 매우 긴 스트링은 단순한 배열일 뿐이고, JavaScript 변수에 그 배열이 있다면 쉽게 액세스 할 수 있다. 사실, 그 배열을 마침표로 구분할 수 있다. 따라서, programmers 리스트의 첫 번째 엔트리의 성(last name)에 액세스 하려면, JavaScript에서 다음과 같은 코드를 사용해야 한다.

people.programmers[0].lastName;

인덱싱은 '0' 부터 시작한다. 따라서, 이것은 people 변수에 있는 데이터로 시작한다. 그리고 나서, programmers라고 하는 아이템으로 이동하고, 첫 번째 레코드([0])에 액세스 한다. 마지막으로, lastName 키의 값에 액세스 한다. 결과는 "McLaughlin"이라는 스트링 값이다.

다음은 같은 변수를 사용하는 예제들이다.

people.authors[1].genre			// Value is "fantasy"

people.musicians[3].lastName		// Undefined. This refers to the fourth entry,
 and there isn't one

people.programmers.[2].firstName	// Value is "Elliotte"

이 신택스로도, 다양한 JSON 포맷 데이터로 작업할 수 있고, 추가 JavaScript 툴킷이나 API가 필요 없다.

JSON 데이터 수정하기

위에 나타난 점과 괄호 표기법을 사용하여 데이터에 액세스 하듯, 같은 방식으로 데이터를 쉽게 수정할 수 있다.

people.musicians[1].lastName = "Rachmaninov";

문자열에서 JavaScript 객체로 변환했다면 변수에 있는 데이터를 수정하면 된다.

문자열로 변환하기

물론, 모든 데이터 수정은 텍스트 포맷으로 쉽게 변환할 수 없다면 가치가 없다. 이것 역시 JavaScript에서는 간단하다.

String newJSONtext = people.toJSONString();

이것이 다이다. 원하는 곳 어디에서나 사용할 수 있는 텍스트 문자열이 생겼으니, 이것을 Ajax 애플리케이션에서 요청 스트링으로 사용할 수 있다.

훨씬 더 중요한 것은, 어떤 JavaScript 객체라도 JSON 텍스트로 변환할 수 있다. 원래 JSON 포맷 스트링으로 할당된 변수로만 작업할 필요가 없다. myObject라는 객체를 변형하려면, 같은 종류의 명령어를 실행하면 된다.

String myObjectInJSON = myObject.toJSONString();

이것이 JSON과 다른 데이터 포맷과의 가장 큰 차이이자, 이 시리즈를 통해 탐구할 주제이다. JSON에서는, 단순한 함수를 호출하면, 포맷팅 되어 사용하기에 알맞은 데이터를 얻을 수 있다. 다른 데이터 포맷의 경우, 미가공 데이터와 포맷 데이터간 변환은 여러분의 몫이다. Document Object Model 같이 데이터 구조를 텍스트로 변환하는 함수를 제공하는 API를 사용할 때도, 네이티브 JavaScript 객체와 신택스 보다는, API를 배우고 그 API의 객체를 알아야 한다.

여러분이 많은 JavaScript 객체들과 작업할 때, JSON은 데이터를 서버 측 프로그램으로 요청을 보내기에 알맞은 포맷으로 쉽게 변환할 수 있다.




위로


결론

본 시리즈에서는 데이터 포맷에 대한 내용을 많은 부분을 할애했다. 여러분의 비동기식 애플리케이션이 거의 비동기식이기 때문이다. 모든 종류의 데이터를 송수신 할 수 있는 다양한 툴과 기술이 있다면, 각 데이터 유형에 가장 잘 맞는 방식으로 수행하면 되고, Ajax 전문가의 반열에도 오를 것이다. 여기에 JSON을 추가하면, JavaScript에서 보다 복잡한 데이터 구조도 능숙히 다룰 준비가 된다.

다음 기술자료에서는 단순히 데이터를 보내는 것 이상으로, 서버 측 프로그램이 JSON 포맷 데이터를 수신하여 처리하는 부분을 설명할 것이다. 또한, 서버 측 프로그램이 스크립트와 서버 측 컴포넌트에 JSON 포맷으로 된 데이터를 보내는 방법도 설명할 것이다. XML, 평이한 텍스트, JSON 요청과 응답을 혼합하는 부분에 대해서도 설명할 것이다. 목표는 어떤 환경에서도 유연하게 이러한 툴들을 능숙히 조작할 수 있도록 하는 것이다.

기사의 원문보기



//읽어보지못했다 처음만보고 주말에 자세히 봐야겠다.
//퍼온곳 http://kwon37xi.egloos.com/2558053 
Ajax 기본 예제와 JSP 엔진에서 한글 인코딩 충돌 문제 처리
Ajax가 필요한 일이 발생해서, 급조해서 Ajax를 공부했다.
공부한 책은 Ajax 입문이며, 처음 약 5~60 페이지만 읽었다. 급조한 내용이니 너무 신뢰하지 말 것. 아.. 그리고 이 책, 중대한 오탈자가 은근히 있다. 혹시 이 책으로 공부하고자 한다면 오탈자를 확인한 뒤에 공부해서 불필요한 시간 낭비를 줄이는 것이 좋겠다.

아무튼, 책의 내용중 Ajax의 기본적인 사용에 관한 문제를 정리하고, 또 JSP/Servlet 엔진에서 Ajax사용시에 발생하는 한글 인코딩(encoding)문제의 처리방법도 정리해 둔다.


Ajax의 개념에 관한 설명은 인터넷 상에 차고 넘치므로 생략.

* A Simpler Ajax Path가 Ajax 입문에 좋은 글.

Ajax의 개발 순서

1. XMLHttpRequest 객체 생성
2. HTTP 요청을 발생시킴(open(), send())
3. 서버측에서 XMLHttpRequest를 통해 보낸 요청을 받아서 파라미터를 분석하고, 작업을 한 뒤에 결과를 XML이나 문자열로 리턴한다.
4. XMLHttpRequest로 서버가 리턴한 데이터를 받아서 처리(onreadystatechange, responseText, responseXML)

XMLHttpRequest에 의한 송수신 상세 예

JavaScript에서 XMLHttpRequest Object 생성하기

// XMLHttpRequest 오브젝트 생성 함수
// @sample oj = createHttpRequest();
// @return XMLHttpRequest 오브젝트
function createHttpRequest()
{
    if (window.ActiveXObject) {
        try {
            // IE6
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                // IE4, IE5
                return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                return null;
            }
        }
    } else if (window.XMLHttpRequest) {
        // Mozilla, FireFox, Opera, Safari, Konqueror3
        return new XMLHttpRequest();
    } else {
        return null;
    }
}


HTTP 요청 발생

 1. open() 메소드 실행 (POST/GET, 요청URL, 동기/비동기지정)
var request = createHttpRequest();
request.open("GET", "/test.xml");
 
// param 1 : GET/POST
// param 2 : URL
// param 3 : 생략가능. 동기/비동기 여부. 기본 비동기.

 2. send() 메소드(데이터 송신)
 request.send(""); // 데이터 없이 전송할때 혹은
 request.send(null); // Konqueror에서는 오류 발생함. Konqueror를 제외하고 데이터 없이 전송할 때 사용가능

위 a,b가 기본적인 모양새이지만, 실제로 GET과 POST 방식에 따라 차이가 많이난다.

  * GET 방식 : GET 방식은 URL에 파라미터를 직접 붙여 보내지만, 한글 등의 문제로 인코딩이 필요하고, RequestHeader 설정도 필요하다. 일반적으로 다음과 같은 모양이 된다.
var paramName = encodeURIComponent("파라미터명"); // 파라미터이름을 UTF-8로 인코딩
var paramValue = encodedURIComponent("파라미터값"); // 파라미터 값을 UTF-8로 인코딩

// 파라미터 구분에 사용되는 ?와 &는 인코딩 되면 안된다. 그래서 따로 붙인다.
var fullParameter = '?' + paramName + '=' + paramValue; // URL에 사용할 파라미터 구성

request.open("GET", "/test.cgi" + data);

// setRequestHeader()는 open()보다 이후에 나와야만 한다.
// 아래는 파라미터 값을 UTF-8로 인코딩해서 보내겠다는 의미.
// GET방식에서는 필요 없고, POST방식에서는 필수이다.
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

request.send(null);


  * POST 방식 : send() 메소드에 인수를 데이터로 넘긴다.
request.open("POST", "/test.cgi");
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
// POST 방식에서도 파라미터를 인코딩하여 send()메소드의 인자로 넘겨주면 된다.
request.send("name=test&data=123");

A Simpler Ajax Path에 보면 HTML폼에 입력된 값을 자동으로 파라미터 문자열로 변경해주는 메소드 예가 있다.

착신과 데이터 처리

 * onreadystatechange 이벤트(송수신 상태 변할때 기동) - IE 이외 부라우저에서는 콜백 스타일의 onload 이벤트 사용가능
 * readyState 프라퍼티 (송수신 상태를 나타내는 값. "4"가 송신 완료) - onload의 경우에는 불필요
onreadystatechange는 요청 처리 상태를 나타내는 readyState 프라퍼티의 값이 바뀔 때 발생한다.
 * 착신을 처리할 함수 지정은 request.open() 함수를 호출하기 전에 선언해야 정상 작동했다. 항상 요청을 보내기 전에 요청을 처리할 함수 지정을 해둔다.
request.onreadystatechange = callbackFunction; // callbackFunction() 함수가 호출된다.

function callbackFunction() {
    // readyState == 4는 착신 완료를 의미한다.
    if (request.readyState == 4) {
        // 착신시의 처리
    }
}

다른 방법으로, callback 함수를 인라인으로 정의하고, HTTP 상태 코드가 200일때만 작업하도록 할 수도 있다. 두가지를 한꺼번에 보면,
request.onreadystatechange = funcation() {
    if (request.readyState == 4 &&
            request.status == 200) {
        // 착신시의 처리
    }
}

onreadystatechange 대신 onload를 사용할 수 있다. Opera 8은 버그때문에 onload만 사용한다. (IE를 제외한 다른 브라우저에서 다 된다)
request.onload = function() {
    // 착신시의 처리
}

onload와 onreadystatechange를 동시에 이용하기 위해서 다음과 같이한다.
if (window.opera) {
    request.onload = function() { callback(request); }
} else {
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            callback(request);
        }
    }
}

function callback(request) {
    // 실제 착신시의 처리를 구현하는 부분
}

 * responseText 또는 responseXML (데이터를 텍스트 혹은 DOMDocument로 수신)
   * responseText : 텍스트로 받기
   * responseXml : XML로 받기
   * 여러줄의 CSV 텍스트를 받았을 때의 일반적 처리
var res = request.responseText;
var rows = res.split(" "); // 여러 줄을 한 줄씩 배열로 만든다.
var cols = rows[0].split(","); // 첫번째 줄을 쉼표 단위로 분리하여 배열로 만든다.

   * JSON 처리
eval("res = " + request.responseText)
//... 기타 처리

   * XML 처리
<?xml version="1.0"?>
<lists>
  <name>Toshiro Takahashi</name>
  <msg>hello</msg>
</lists>

var res = request.responseXML;
var msgs = res.getElementsByTagName("msg"); // DOM 객체 사용

alert(msg[0].firstChild.nodeValue);


서버측 스크립트

XMLHttpRequest.send() 에 의해 요청을 받아 처리하게 되는 서버측 스크립트(JSP, Servlet, ASP, PHP 등)은 요청 파라미터를 분석하여 작업을 처리한 뒤에 결과를 Text나 XML로 리턴하면 된다.
 * 리턴시 문자 인코딩은 기본적으로 UTF-8로 한다.
 * 텍스트로 리턴할 경우, Opera 8, Konqueror 3, Safari 등은 UTF-8을 인식하지 못한다. 서버는 응답 문자열을 UTF-8기준으로 URI 인코딩을 해서(Java의 경우 java.net.URLEncoder.encode() 메소드 사용) 리턴하고, 받는 측(웹 브라우져)는 다음과 같이 해석하면 정상적인 문자열을 받게 된다.(실제로는 작동하지 않으므로 URLEncoder를 사용하지말고 받는 자바 스크립트 측에서도 아래와 같이 받지 말고 그냥 request.responseText를 받을 것)
// Mozilla FireFox와 IE에서는 Encode/Decode할 경우
//공백이 +로 바뀌는 현상이 발생했다. 그래서 안쓴다.
// JavaScript측에서 decodeURIComponent를 안하면 서버측에서도 URLEncoding을 하면 안된다.
var res = decodeURIComponent(request.responseText);


JSP/Servlet 에서 Ajax와 한글 인코딩 문제

Ajax는 기본적으로 UTF-8 만으로 통신을 한다고 보면된다. 그 이외의 Encoding을 지원하는 인코딩 함수가 없기 때문에 EUC-KR로 데이터를 전송하려는 꿈은 접어야만 한다.
헌데, 아직 우리나라는 EUC-KR 인코딩으로 된 웹 어플리케이션이 압도적으로 많은 상황이다(어서 빨리 UTF-8로 옮겨가길 바라마지 않는다).
거기다가 보통 JSP/Servlet 웹 어플리케이션은 Servlet 스펙 2.3이후부터 문자 인코딩 서블릿 필터를 사용해 모든 요청에 대해 일관된 문자 인코딩을 사용하는 것이 보편적인 방법으로 자리잡았다.

서블릿 필터는 일관성있게 모든 요청을 EUC-KR로 받아들이게 했는데, 몇몇 Ajax관련 요청만 UTF-8로 받아들여야만 하는 것이다.
필터를 적용할 URL-Pattern을 따로 줘보려 했으나, 너무 복잡해졌다.
그래서 HTTP 요청의 헤더를 이용해서 해결 했다.

아.. 한가지 더. 현재 한글 문제는 "XMLHttpRequest 요청 -> JSP/Servlet" 이 상황에서만 발생하는 것이다.
"JSP/Servlet -> XMLHttpRequest"의 상황(서버에서 클라이언트로 값을 리턴)에서는 이 문제가 발생하지 않는다.
서버가 리턴하는 문자열은 간단하게 다음처럼 하면 WAS가 자동으로 UTF-8로 값을 변경해서 전달하기 때문이다.
<%@ page contentType="text/plain; charset=utf-8" pageEncoding="EUC-KR"%>

contentType에서 text/plain은 텍스트나 JSON으로 값을 리턴할 때이다. XML로 리턴할 때는 text/xml.

아래는 Ajax 요청을 처리하기 위해서 만들어본 간단한 Encoding Filter 이다.
package ajax.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 어플리케이션 전체에 적용되는 필터이다.
 *
 * <ul>
 * <li>encoding 파라미터 : encoding 파라미터를 설정하면 request 객체에
 * setCharacterEncoding(encoding)을 실행한다.</li>
 * <li>ajaxFlag 파라미터 : Ajax요청임을 나타내는 HTTP 파라미터 이름이다. ajaxFilter로 지정한 HTTP 파라미터의
 * 값이 true 로 설정되면 인코딩을 무조건 UTF-8로 설정한다.</li>
 * </ul>
 *
 * @author 손권남(kwon37xi@yahoo.co.kr)
 *
 */
public class EncodingFilter implements Filter {

    private Log log = LogFactory.getLog(this.getClass());

    /** HTTP 요청 문자 인코딩 */
    private String encoding = null;

    /** Ajax 요청임을 나타내는 플래그 파라미터 이름 */
    private String ajaxFlag = null;

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        if (ajaxFlag != null
                && "true".equals(((HttpServletRequest) request)
                        .getHeader(ajaxFlag))) {
            // Ajax 처리 요청일 경우 무조건 UTF-8 지정.
            request.setCharacterEncoding("UTF-8");
            if (log.isDebugEnabled()) {
                log.debug("요청 헤더에 " + ajaxFlag + "가 "
                        + ((HttpServletRequest) request).getHeader(ajaxFlag)
                        + "로 설정되어 있어 문자 인코딩에  UTF-8을 사용합니다.");
            }
        } else if (encoding != null) {
            // Ajax 플래그가 true가 아니면, 기본적인 인코딩을 적용한다.
            request.setCharacterEncoding(encoding);
            if (log.isDebugEnabled()) {
                log.debug("문자 인코딩에 " + encoding + "을 사용합니다.");
            }
        }

        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {
        encoding = config.getInitParameter("encoding");

        ajaxFlag = config.getInitParameter("ajaxFlag");

        if (log.isDebugEnabled()) {
            log.info("encoding : " + encoding + ", ajaxFlag : " + ajaxFlag);
        }
    }

    public void destroy() {
    }
}

이 필터를 적용하고서, web.xml에 다음 내용을 추가하면 필터가 작동한다.
<filter>
    <description>이중 인코딩 필터</description>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>ajax.filter.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>euc-kr</param-value>
    </init-param>
    <init-param>
        <param-name>ajaxFlag</param-name>
        <param-value>Ajax</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

여기 내용을 보면, 기본적인 인코딩은 EUC-KR이고, 요청 헤더에 "Ajax" 헤더의 값이 "true"일 경우에는 강제로 UTF-8을 지정하라고 한 것이다. "ajaxFlag"의 값을 변경하면 헤더의 키을 "Ajax"가 아닌 다른 값으로도 지정할 수 있다. 하지만 아무튼 해당 헤더의 값을 "true"로 지정하면 Ajax로 인식하게 되는 것이다.

이를 위해서는 XMLHttpRequest에도 한가지 처리를 더 보태야 한다.
    request.open("GET", "AjaxProcessor.jsp" + fullParameter);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('Ajax', 'true');

당연히 헤더에 값 Ajax요청임을 명시하는 값을 설정하는 것이다.

그리고 다음 문제가 또 있는데, Tomcat 버전별로 문자 인코딩 설정이 달라질 수 있다는 것이다.
위 내용은 Tomcat 4.x에서는 정상 작동하지만, Tomcat 5.x 에서는 제대로 작동하지 않는다.
Tomcat 5.x에서는 server.xml 에 GET 방식의 요청에 대한 인코딩을 지정하기 때문이다.
여기서 URIEncoding="euc-kr" 을 사용하지 않고, useBodyEncodingForURI="true"을 사용하면 Tomcat 4.x 처럼 request.setCharacterEncoding()의 값을 따라가게 할 수 있다.
Tomcat과 한글에 대해서는 Tomcat/JSP와 한글문서를 참조한다.

또하나 Ajax임을 나타내는 플래그를 HTTP 요청 헤더에 설정하도록 했는데, 그러지 않고 요청 파라미터(request.getParameter()로 값을 얻어올 수 있는 것)으로 설정하면 안된다.
request.getParameter()가 실행되어 Ajax 플래그의 값을 감지하는 그 순간, 그 이후 호출되는 request.setCharacterEncoding()는 완전히 무시되어 버리기 때문이다.

예제

급조한 예제이다.
* AjaxCaller.jsp - Ajax 호출부(클라이언트) : 수식을 만들어서 서버측에 계산을 요청한다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
<script type="text/javascript">
// XMLHttpRequest 오브젝트 생성 함수
// @sample oj = createHttpRequest();
// @return XMLHttpRequest 오브젝트
function createHttpRequest()
{
    if (window.ActiveXObject) {
        try {
            // IE6
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                // IE4, IE5
                return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                return null;
            }
        }
    } else if (window.XMLHttpRequest) {
        // Mozilla, FireFox, Opera, Safari, Konqueror3
        return new XMLHttpRequest();
    } else {
        return null;
    }
}

// 계산을 수행한다.
function calc() {
    var request = createHttpRequest();
    var nameParam = encodeURIComponent("name");
    var nameValue = encodeURIComponent(document.getElementById("name").value);
   
    var oper1Param = encodeURIComponent("oper1");
    var oper1Value = encodeURIComponent(document.getElementById("oper1").value);
   
    var oper2Param = encodeURIComponent("oper2");
    var oper2Value = encodeURIComponent(document.getElementById("oper2").value);
   
    var operatorParam = encodeURIComponent("operator");
    var operatorValue = encodeURIComponent(document.getElementById("operator").value);
   
    var fullParameter =
        "?" + nameParam + "=" + nameValue
        + "&" + oper1Param + "=" + oper1Value
        + "&" + oper2Param + "=" + oper2Value
        + "&" + operatorParam + "=" + operatorValue;
   
    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            alert("Response : " + request.responseText);
            eval("var result = " + request.responseText);
            alert(result.name + "님 계산결과는 " + result.value + "입니다.");
        }
    }
   
    request.open("GET", "AjaxProcessor.jsp" + fullParameter);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('Ajax', 'true');
    request.send("");

} // end of calc()
</script>
</head>
<body>
이름 : <input type="text" id="name" /> <br />
<input type="text" id="oper1" />
<select id="operator">
    <option value="+">+</option>
    <option value="-">-</option>
    <option value="*">*</option>
    <option value="/">/</option>
</select>
<input type="text" id="oper2" />
<input type="button" value="계산하기" onclick="calc()" />
</body>
</html>

* AjaxProcessor.jsp - Ajax 처리부(서버) : 수식을 계산한 결과를 JSON 형태로 리턴한다
<%@ page contentType="text; charset=utf-8" pageEncoding="EUC-KR"%>
<%
System.out.println("AjaxProcessor.jsp 시작");

String result = null;

String name = request.getParameter("name");
String oper1 = request.getParameter("oper1");
String oper2 = request.getParameter("oper2");
String operator = request.getParameter("operator");

double oper1Value = Double.parseDouble(oper1);
double oper2Value = Double.parseDouble(oper2);

double calcResult = 0;

if ("+".equals(operator)) {
    calcResult = oper1Value + oper2Value;
} else if ("-".equals(operator)) {
    calcResult = oper1Value - oper2Value;
} else if ("*".equals(operator)) {
    calcResult = oper1Value * oper2Value;
} else {
    calcResult = oper1Value / oper2Value;
}

result = "{  " +
    ""name" : "" + name + "", " +
    ""value" : "" + calcResult + "" " +
    "} ";
System.out.println("Result : " + result);

%><%= result%><%
System.out.println("AjaxProcessor.jsp 끝");
%>

이름 입력 부분에 한글을 입력하여 문제없이 처리되는지 확인해보기 바란다.

JSON

Ajax(JavaScript)는 데이터를 리턴 받는 방법으로 XML/Text/JSON을 지원한다. JSON은 텍스트 형태로 객체를 정의하는 방식이다. 이것은 XML과 1:1 매칭을 할 수도 있다. XML보다 훨씬 만들기 쉽고 사용법도 자바 객체를 사용하는 것과 유사하다. 그래서 이걸 사용해서 프로그램을 작성했다.
{
  "test1": "hello",
  "test2": "hello2"
}

위와 같은 메시지를 서버에서 응답으로 내보냈다고 할 때
// JSON 형태의 텍스트를 JavaScript 객체화 한다.
eval("res = " + request.responseText);

// 객체를 사용한다.
alert(res.test2); // 이 명령은 "hello2"를 출력한다.

배열은 다음과 같이 생성한다.
[
  ["test1", "test2"],
  ["test3", "test4"]
]

아래와 같이 사용한다.
eval("res = " + request.responseText);

// test4를 출력한다.
alert(res[1][1])

 * JSON 홈페이지 : http://www.json.org/
 * Java 객체를 이용해서 JSON 객체를 위한 텍스트 생성하기 : http://www.json.org/java/simple.txt 매우 단순한 방법으로 핵심 기능만 가지고 있다. 이것을 사용하길 권장한다. 라이브러리 다운로드는 http://www.JSON.org/java/json_simple.zip 에서 한다.
 * XML과 JSON간의 변환
 
[팁] XMLHttpRequest를 사용할 때 한글 파라미터의 인코딩 처리 방법
XMLHttpRequest에서 한글 파라미터를 전송할 때 인코딩을 처리하는 방법에 대해서 살펴본다.
프로바이더: 최범균
섹션 목록
  • XMLHttpRequest 사용시 한글 파라미터 전송 방법
XMLHttpRequest 사용시 한글 파라미터 전송 방법

자바캔에 실린 'XMLHttpRequest를 이용한 웹 채팅 구현'이란 글에서 한글 문제를 iframe을 사용하여 해결했는데, 그 방식 말고 자바캔의 댓글 추가에서 사용한 한글 처리 방식에 대해서 설명해보도록 하겠다.

XMLHttpRequest의 한글 파라미터 문제 해결 방법에 대해서 살펴보기 전에, 웹브라우저가 파라미터 값을 전송할 때 어떻게 인코딩하는 지 살펴보도록 하자. 대부분의 한글 사이트는 다음과 같이 캐릭터셋이 "euc-kr"인 HTML 문서를 사용할 것이다.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=euc-kr" />
        <title>test</title>
    </head>
    <body>
    <form name="test" action="form.jsp">
    <input type="text" name="name" /><input type="submit"/>
    </form>
    </body>
    </html>

위 문서는 name 파라미터를 form.jsp로 전송하는 FORM을 갖고 있는데, name 필드에 '한글'을 입력한 뒤 submit 버튼을 누르면 다음과 같이 파라미터 값이 변환되어 전송된다.

    euc-kr 캐릭터셋에 맞춰 '한글' 을 인코딩한 값
    
    http://..../form.jsp?name=%C7%D1%B1%DB

위에서 '%C7%D1%B1%DB'는 '한글'을 euc-kr 캐릭터셋에 맞춰서 인코딩한 결과이다. IE나 파이어폭스 등의 웹 브라우저는 문서의 캐릭터셋에 맞춰서 파라미터를 인코딩하여 전송하기 때문에, 만약 문서의 캐릭터셋이 utf-8 이면 '한글' 파라미터를 다음과 같이 인코딩하여 전송하게 된다.

    
    utf-8 캐릭터셋에 맞춰 '한글' 을 인코딩한 값
    
    http://..../form.jsp?name=%ED%95%9C%EA%B8%80

문서 캐릭터셋이 euc-kr인 경우와 utf-8인 경우 전송되는 파라미터의 인코딩된 값도 다른 것을 확인할 수 있다.

이제, 다시 본론으로 돌아와서 XMLHttpRequest가 전송하는 파라미터에 대해서 살펴보자. XMLHttpRequest도 파라미터를 웹서버에 전송하기 때문에 파라미터 값을 알맞게 인코딩 해 주어야 한다. 그런데, 아쉽게도 XMLHttpRequest 자체적으로 인코딩 처리를 지원해주지는 않는다. 따라서, 자바스크립트가 지원해주는 인코딩 처리 함수를 사용해야 한다. 자바 스크립트가 제공하는 인코딩 처리 함수는 escape()와 encodeURIComponent()의 두가지가 있다. 이 두가지는 동작 방식이 다른데, 다음표는 두 함수의 실행 결과를 보여주고 있다.

인코딩 처리 인코딩된 값 설명
두 함수의 실행 결과는 문서 캐릭터셋이 euc-kr 이거나 utf-8 인 경우 모두 동일하다.
escape('한글') %uD55C%uAE00 유니코드 값을 표현
encodeURIComponent('한글') %ED%95%9C%EA%B8%80 utf-8로 인코딩. encodeURI() 함수도 동일한 결과 출력

두 함수의 실행 결과를 보면 encodeURIComponent() 함수가 utf-8로 인코딩한 결과를 보여줌을 알 수 있다. 따라서, XMLHttpRequest로 한글 파라미터를 전송할 때에는 다음과 같은 방법을 사용하면 된다.

  • 웹브라우저에서: 자바스크립트 encodeURIComponent() 함수를 사용하여 파라미터 값을 utf-8로 인코딩하여 전송한다.
  • 서버에서: 파라미터 값을 utf-8로 디코딩하여 읽어온다.

웹브라우저의 코드를 작성하면 다음과 같을 것이다. (POST 방식으로 전송할 때에도 같은 방법으로 파라미터를 인코딩하면 된다.

)
    <script type="text/javascript">
    function sendData() {
        var xmlHttp = null;
        if( window.XMLHttpRequest ){
            xmlHttp = new XMLHttpRequest();
        }
        else{
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        
        if( xmlHttp ){
            var nameValue = document.memberForm.name.value;
            var idValue = document.memberForm.id.value;
            var param = "name="+encodeURIComponent(nameValue)+"&id="+encodeURIComponent(idValue);
            xmlHttp.open('GET', 'http://www.some.com/receive.jsp?'+param, true);
            
            xmlHttp.onReadyStateChange = function(){
                if( xmlHttp.readyState == 4 ){
                    alert(xmlHttp.responseText);
                }
            }
            xmlHttp.send(null);
        }
    }
    </script>

서버에서는 파라미터를 utf-8로 읽어오기만 하면 된다. 예를 들어, JSP를 사용한다면 다음과 같이 파라미터의 인코딩을 utf-8로 지정하면 된다.

    <%
        request.setCharacterEncoding("utf-8");
        ...
        String name = request.getParameter("name");
    %>

PHP나 ASP.net과 같은 다른 서버 프로그래밍 언어에서도 JSP와 같은 방식으로 파라미터 값을 utf-8로 디코딩하여 읽어오면 파라미터를 알맞게 처리할 수 있다.

프로바이더 최범균 ( madvirus@madvirus.net ) :
틀 프레임워크, 틀 자바스크립트 등을 개발하였으며, JSP 2.0 프로그래밍, JSP 실전 Know-how, Jakarta Project 등의 책을 집필하였다. 자바캔의 운영자이며, 현재 CVNet e-biz 팀에서 근무하고 있다.
Ian SelbyPrototypeScriptaculous를 이용한 에이젝스 활동 알리미(Ajax Activity Indicators)에 대한 문제점을 지적하고 자신이 개발한 사용법을 공개하였다. XMLHttpRequest들의 완료시점이 어정쩡한 프로토타입의 onComplete 옵션에 질려버린 개발자라면 Ian이 말하는 방식을 꼭 한번 살펴보자. 그의 데모 페이지에서 테스트해본 결과 XMLHttpRequest 요청이 일어나는 시점과 끝나는 시점을 정확히 잡아내며 여러번 클릭하여 다중으로 요청하는 경우에도 문제가 발생하지 않는다.

Ajax.Responders.register({
onCreate: function() {
if($('indicator') && Ajax.activeRequestCount > 0)
Effect.Appear('indicator',{duration: 0.25, queue: 'end'});
},
onComplete: function() {
if($('indicator') && Ajax.activeRequestCount == 0)
Effect.Fade('indicator',{duration: 0.25, queue: 'end'});
}
});
출처 : http://firejune.com/905