Form Study #1

kenu
2002-02-24 12:34오전

값을 넘겨주는 방식 중 많이 사용하는 3가지 방식을 논의하겠습니다. GET, POST 방식과 파일을 전송할 수 있는 multipart/form-data 에 관한 것입니다. 소스를 일단 보시죠.
formstudy.jsp
<html>
<head>
  <title>okjsp form study</title>
</head>
<body>
<%-- 입력 값을 처리하는 부분 --%>
<pre>
contentType: <%=request.getContentType()%>
contentLength: <%=request.getContentLength()%>
method: <%=request.getMethod()%>
get name: <%=request.getParameter("gname")%>
post name: <%=request.getParameter("pname")%>
mp name: <%=request.getParameter("mpname")%>
filename: <%=request.getParameter("filename")%>
</pre>
<%-- 값을 입력받는 부분 --%>
form1:
  <form method="get">
    name (get) <input type="text" name="gname">
    <br>
    <input type="submit" value="get">
  </form>
form2:
  <form method="post">
    name (post) <input type="text" name="pname">
    <br>
    <input type="submit" value="post">
  </form>
form3:
  <form method="post" enctype="multipart/form-data">
    name (multipart) <input type="text" name="mpname">
    <br>
    file <input type="file" name="filename">
    <br>
    <input type="submit" value="multipart">
  </form>
</body>
</html>

		


form 태그에 action 속성이 없다면 자기 자신을 다시 한 번 호출합니다. 즉 action="formstudy.jsp" 와 같은 결과입니다. 브라우저의 주소줄에 입력해서 서버에 요청할 경우 기본 method 는 GET 입니다.

GET 방식의 경우 넘겨주는 값은 주소줄에 추가됩니다. 첫번째 입력창에 okjsp 라는 값을 입력한 후에 전송 버튼을 누르면 다음 화면은 다음과 같이 나오게 됩니다. 특징적인 것은 GET을 통한 값의 전달은 주소줄을 타고 전달이 됩니다. 따라서 서버마다 다르지만 대략 230바이트 이상의 값은 전달할 수 없게 됩니다. 때문에 비밀번호 같은 중요한 값들은 노출되기 쉽고, 항목이 많은 form 양식은 GET방식으로 처리하지 않을 수 밖에 없습니다.

POST 방식은 값의 전달경로는 header 부분입니다. getContentLength() 메소드를 통해서 전달되는 값의 Byte 크기를 알 수 있습니다. 이 때 parameter 이름과 값이 = 을 사이에 두고, 항목과 항목은 & 로 구분된 문자열로 Header 를 통해서 전달이 됩니다. ^^ 주소줄에 GET 방식의 자국을 남긴채 POST 폼을 사용하면 주소줄의 파라메터도 전달이 됩니다. 두번째 입력창에 okjsppost 를 입력하고 전송하면 아래 그림과 같이 나옵니다.

contentLength 가 15가 나왔습니다. 저 길이의 의미는 "pname=okjsppost"를 생각해보면 쉽게 이해가 갈 것입니다. getParameter("pname") 했을 경우 okjsppost 가 나오는 것은 다 아시겠죠. 그리고 contentType 이 application/x-www-form-urlencoded 인 것도 기억해두시기 바랍니다.

form tag 에 enctype="multipart/form-data" 일 경우 전송에 대해서 살펴봅시다. 가장 많이 질문되는 것이 왜 파일은 업로드 되는데 request.getParameter() 로 변수값을 가져오지 못하는가 입니다. (이것 질문하는 사람 100명도 더 봤습니다. 이 문제 때문에 이 강좌를 쓴 것이기도 하죠. 일종의 FAQ 라고 할 수 있죠.) 일단 multi 라는 값만 넣어서 보내면 293~300 사이의 값이 나옵니다. 왜 이리 가변적인지는 아직 저도 더 찾아봐야할 것 같구요(저도 이거 분석은 처음입니다. ^^) "mpname=multi" 외에도 뭔가 다른 것이 280바이트 이상의 정보를 같이 보낸다는 것을 감을 잡으셔야 합니다. 쉽지는 않을 것 같죠? 그렇습니다. 쉽지 않습니다. 이 값을 분석해서 뽑아내야(parsing) 하는데 직접하게 된다면 골 아플 것입니다. 다행스럽게도 무료로 공개된 MultipartRequest 라던가 문제가 좀 있지만 기능이 좋은 jspsmartupload 와 개발자가 책을 구입해야 사용권한을 얻을 수 있는 jason hunter 의 O'reilly MultipartRequest 등이 있습니다. 국내 개발자들이 공개하는 자바의꿈 님의 NewTakeUpload 등도 있구요. 중복파일처리 메소드도 있다고 합니다. 이것들의 소스를 구해서 분석해보시는 것도 나쁘지 않겠죠.

multipart 에 대해서는 다음에 더 집중분석해보도록 하고, 여기서는 request.getParameter() 그 이상의 뭔가가 있다는 것을 아는 것으로 만족하도록 하죠. 그럼 이 값을 받을 수 있는 방법을 간단히 소개하고 마치도록 하겠습니다. jason hunter 의 MultipartRequest 에서 업로드 객체(multi)를 생성하면서 업로드를 합니다. 이 MultipartRequest 클래스에는 request 에서 사용했던 메소드들을 그대로 사용할 수 있도록 지원합니다. 따라서 request 대신 객체명(multi) 을 사용해서 원하는 파라메터값을 뽑아낼 수 있습니다. 아래 소스를 보시죠. 제가 사용하는 소스 중의 일부입니다. filename 은 다른 방식으로 뽑아내는 것도 유심히 살펴보세요.
board_write2.jsp 파일 중
...
  MultipartRequest multi =
        new MultipartRequest(request, savePath, sizeLimit);

  Enumeration files = multi.getFileNames();

  while(files.hasMoreElements()) {
    fname = (String)files.nextElement();
    f = multi.getFile(fname);
    maskname[cnt] = ""+System.currentTimeMillis()+cnt;
    filename[cnt] = multi.getFilesystemName(fname);
    filesize[cnt] = 0;
    if (f != null) {
  		filesize[cnt] = f.length();
  		up1 = new File(savePath+"/"+filename[cnt]);
   		up2 = new File(savePath+"/"+maskname[cnt]);
   		if (up1.exists()) {
         boolean rslt = up1.renameTo(up2);
   		}
   	} // end if f != null
    cnt++;
  }
...

  String name    = Kr.nchk(multi.getParameter("mpname")    );
...


      


이번 강좌는 여기서 마치겠습니다. 저도 API 를 더 보면서 공부를 좀 더 한 다음에 multipart 에 대해서 더 깊은 내용의 강좌를 준비해보고 싶습니다.(^^; 언제 강좌가 써질지는 저도... 헤헤). Jason Hunter 의 자바 서블릿 프로그래밍 개정판(한빛미디어, 이창신 번역) 책에 자세한 내용이 있으니 참고하시기 바랍니다.

관련 사이트
http://www.servlets.com/cos/
Jason Hunter 의 MultipartRequest 를 구할 수 있는 곳
http://iasandcb.hihome.com/cosi/
MultipartRequest의 국제화버전을 구할 수 있는 곳
http://aboutjsp.com/lec/multipart.htm
MultipartRequest사용법 aboutjsp의 이선재님 강의
http://cafe.daum.net/DOJ
Dream Of Java 님의 NewTakeUpload 를 구할 수 있는 곳
http://okjsp.pe.kr/heogn/lecture/lec05/fileup01.htm
FileUpload 컴포넌트 소스와 예제
http://www.kimho.pe.kr/jsp/jsp_upload.html
Jason Pell 의 MultipartRequest 에 대한 김호님의 강좌
xml-typed document
http://okjsp.pe.kr