package 선언된 java 컴파일하기 kenu 2001-10-30 10:03오후 |
package 는 꾸러미라는 뜻이죠. 소포라는 뜻도 있구요. java 에서 package 라 함은 연관있는 class 들을 모아놓은 꾸러미라는 뜻을 갖고 있습니다. jdk 를 깔면 bin 디렉토리에 javac 이라는 java 컴파일러가 있습니다. 이것을 이용해서 .java 라는 확장자를 가진 파일을 컴파일할 수 있습니다. jvm 상에서 돌아가는 .class 파일(bytecode 라고 합니다. jvm 이 알아듣는 명령어의 집합체라고 생각하시면 됩니다.)을 만들어 내는 것이죠. |
제가 사용하는 method 를 모아놓은 Kr.java 와 Fn.java 파일을 컴파일해보도록 하겠습니다. 이 두 개의 파일은 ok 라는 패키지에 속하게 만들었습니다. ROOT/WEB-INF/classes/ok/ 에 Kr.java 파일을 놓아둡니다. Kr.javapackage ok; public class Kr{ public static String a2k(String str) { String rtn = null; try { rtn = (str==null)?"":new String(str.getBytes("8859_1"),"euc-kr"); } catch (java.io.UnsupportedEncodingException e) {} return rtn; } public static String k2a(String str) { String rtn = null; try { rtn = (str==null)?"":new String(str.getBytes("euc-kr"),"8859_1"); } catch (java.io.UnsupportedEncodingException e) {} return rtn; } public static String nchk(String str) { return (str==null)?"":str; } } |
3개의 메소드를 짧게 설명하자면 a2k() 는 "8859_1" 문자세트를 "euc-kr" 로 전환하는 것입니다. 파라메터로 받은 한글의 경우 jasper.jar(jsp를 servlet으로 변환시 사용) 가 8859_1 의 문자세트로 처리를 하기 때문에 한글문자가 깨집니다. 이것을 한글코드로 전환해주는 것이죠. k2a() 는 반대의 경우입니다. 파일을 다운받게 할 경우 한글로 보내면 깨지기 때문에 "8859_1" 문자세트로 변환하고 보내주는 경우입니다. nchk() 는 문자열이 null 일 경우 "" 를 반환해서 substring() 이나 indexOf() 메소드 등을 사용시 NullPointerException 이 일어나는 것을 방지하는 기능입니다. 이것을 컴파일 해 보도록 하죠. |
여러분들이 좋아하시는 화면캡쳐였습니다. ^^; 그래서 여기를 찾으시는 줄로 알고 있거든요. text 로만 잔뜩 보는 것보다 그림도 있고, 소리도 나고, 우잉? 소리라... 딱! 아얏! ^^; 계속 진도 나가겠습니다. MS-DOS 시절부터 명령어에 익숙하신 분들은 * (wild card 문자)에 익숙할 겁니다. 위와 같은 방법으로 디렉토리를 변경해 들어갑니다. 여기서 잠깐 윈도우 Tip 하나 소개하고 들어가겠습니다. 저렇게 열심히 들어가려면 시간이 엄청걸립니다. 또 Program Files 같이 중간에 띄어지고 긴 문장까지 들어가려면 에러도 픽픽나고 그럽니다. 그럼 지금부터 제가 마술을 보여드리겠습니다. 윈도우 탐색기를 옆에 열어놓습니다. 자아~ c:\Program Files\Apache Group\Apache\conf\ 디렉토리를 쉽게 들어가는 법을 소개합니다. 천기누설입니다. 저 목숨걸고 알려드리는 것입니다. 연변에서도 이거 아는 사람 몇 안됩니다. 탐색기 여셨습니까? c:\Program Files\Apache Group\Apache\conf\ 를 클릭해서 여는 것은 쉽습니다. 그리고 cmd 창(도스 프롬프트창이라고도 하죠.)에 cd 하고 스페이스 한번을 꾹 눌러줍니다. 그리고 conf 디렉토리를 마우스로 잡아서 cmd 창으로 끌면... ^^ ㅋㅋ |
Enter만 치면 됩니다... 다시 거기로 돌아가겠습니다. 마찬가지로 cd 치고 탐색기에서 열어서 ok 디렉토리를 끌어다 놓아도 됩니다. |
javac -d ../ -classpath ../ Kr.java 라고 한 이유를 설명하겠습니다. 만일 그냥 javac Kr.java 라고 하면 어떻게 될까요? Kr.class 가 생깁니다. ^^; 컴파일 될 것입니다. 그럼 또 하나 퀴즈? javac -d . Kr.java 라고 하면요? 그러면 ok/ 디렉토리 안에 ok/ 디렉토리 하나가 더 생기고 그 안에 Kr.java 가 생깁니다. 만일 package ok.jsp; 라고 선언했다면 현재 디렉토리 아래에 ok/ 디렉토리가 생기고 그 아래에 jsp/ 디렉토리가 생기고 class 파일은 그 안에 생성됩니다. 그렇다면 javac -d ../ Kr.java 하면 짐작할 수 있으실까요? 만일 package ok.jsp; 라고 되어있으면 javac -d ../../ Kr.java 가 될 것입니다. |
package 가 선언되지 않은 class 파일이 ROOT/WEB-INF/classes/ 에 있다고 칩시다. 대표적인 예가 DBConnectionManager.java 같은 경우죠. 만일 Kr.java 에 import DBConnectionManager; 라고 선언되어 있다면 필요한 것이 -classpath ../ 옵션입니다. 이런 경우 javac -d ../ -classpath ../ Kr.java 해주면 상위디렉토리에 있는 class 를 import 해오면서 컴파일이 이뤄집니다. javac -d ../ -classpath ../;%classpath% Kr.java 는 그럼 무슨 뜻일까요? (linux 경우 javac -d ../ -classpath ../:$CLASSPATH Kr.java 입니다.) 환경변수에 잡힌 classpath 를 가져 온다는 뜻입니다. 이 환경변수에 있는 값은 set 명령을 치면 확인할 수 있습니다. |
이해가 가셨을 겁니다. Fn.java 파일입니다. 좀 길죠. 그런데 이 파일은 컴파일하면 에러가 날것입니다. javac -d ../ -classpath ../ Fn.java Fn.javapackage ok; import javax.servlet.http.*; public class Fn { public static String rplc(String str, String n1, String n2) { int itmp = 0; if (str==null) return ""; String tmp = str; StringBuffer sb = new StringBuffer(); sb.append(""); while (tmp.indexOf(n1)>-1) { itmp = tmp.indexOf(n1); sb.append(tmp.substring(0,itmp)); sb.append(n2); tmp = tmp.substring(itmp+n1.length()); } sb.append(tmp); return sb.toString(); } public static String crop(String str, int i) { if (str==null) return ""; String tmp = str; if(tmp.length()>i) tmp=tmp.substring(0,i)+"..."; return tmp; } public static String wwwlink(String str) { if (str==null) return ""; String tmp = str; int itmp = 0; int wend = 0; StringBuffer sb = new StringBuffer(); sb.append(""); while(tmp.indexOf("http://")>-1) { itmp = tmp.indexOf("http://"); wend = tmp.indexOf(" ",itmp); if (wend>tmp.indexOf("\r",itmp)) wend = tmp.indexOf("\r",itmp); if (wend>tmp.indexOf("<",itmp)) wend = tmp.indexOf("<",itmp); else if (wend==-1) wend = tmp.length(); sb.append(tmp.substring(0,itmp)); if(itmp>3 && tmp.substring(itmp-3,itmp).indexOf("=")>-1) { wend = tmp.indexOf("</a>",itmp)+3; if (wend==2) wend = tmp.indexOf(">",itmp); sb.append(tmp.substring(itmp,wend)); } else { sb.append("<a href=\""+ tmp.substring(itmp,wend)+"\" target=\"_blank\" class=\"ok-2\">"); sb.append(tmp.substring(itmp,wend)); sb.append("</a>"); } tmp=tmp.substring(wend); } sb.append(tmp); tmp = sb.toString(); sb.setLength(0); while(tmp.indexOf("www.")>-1) { itmp = tmp.indexOf("www."); wend = tmp.indexOf(" ",itmp); if (wend>tmp.indexOf("\r",itmp)) wend = tmp.indexOf("\r",itmp); if (wend>tmp.indexOf("<",itmp)) wend = tmp.indexOf("<",itmp); if (wend==-1) wend = tmp.length(); sb.append(tmp.substring(0,itmp)); if(itmp>10 && tmp.substring(itmp-10,itmp).indexOf("=")>-1) { wend = tmp.indexOf("</a>",itmp)+3; if (wend==2) wend = tmp.indexOf(">",itmp); sb.append(tmp.substring(itmp,wend)); } else { sb.append("<a href=\"http://"+ tmp.substring(itmp,wend)+"\" target=\"_top\" class=\"ok-2\">"); sb.append(tmp.substring(itmp,wend)); sb.append("</a>"); } tmp=tmp.substring(wend); } sb.append(tmp); return sb.toString(); } public static void setCookie(HttpServletResponse response, String name, String value, int iMinute) { value = java.net.URLEncoder.encode(value); Cookie cookie = new Cookie(name, value); cookie.setMaxAge(60 * iMinute); response.addCookie(cookie); } public static void setCookie(HttpServletResponse response, String name, String value) { value = java.net.URLEncoder.encode(value); Cookie cookie = new Cookie(name, value); cookie.setMaxAge(60*60*24*15); response.addCookie(cookie); } public static String getCookie(HttpServletRequest request, String cookieName) throws Exception { Cookie [] cookies = request.getCookies(); if (cookies==null) return ""; String value = ""; for(int i=0;i<cookies.length;i++) { if(cookieName.equals(cookies[i].getName())) { value = java.net.URLDecoder.decode(cookies[i].getValue()); break; } } return value; } } |
Fn.java:3번째 줄에 있는 package javax.servlet.http 가 없다는 얘기죠. import javax.servlet.http.*; 문장에서 발생한 문제인데, servlet 에 관련된 API(Tomcat:servelt.jar 혹은 Resin:jsdk22.jar,jsdk23.jar) 를 찾지 못해서 그렇습니다. classpath 에 없다는 뜻인데요. javac 으로 컴파일을 할 때 jvm 을 띄웁니다. 이 jvm 이 가동할 때 자동으로 *.jar 파일들을 인식하는 곳이 있습니다. 이곳에만 있으면 모든 *.jar 파일이 classpath 에 내부적으로 들어가서 인식이 됩니다. 어디냐면 jdk1.3/jre/lib/ext/ 디렉토리 입니다. jre 는 java runtime environment 라고 합니다.(zip 은 안됩니다. oracle 의 classes12.zip 은 압축풀거나 -classpath c:/jdbc/classes12.zip 옵션에 경로를 바로 넣어주세요.) 여기에 Tomcat 의 lib 디렉토리나 common 디렉토리 아래있는 servlet.jar 파일(resin 은 lib 아래 jdsk22.jar) 파일을 jdk1.3/jre/lib/ext/ 디렉토리에 복사해줍니다. 그리고 다시 javac -d ../ -classpath ../ Fn.java 해보세요. |
이제 compile 하는 요령이 생겼을 겁니다. 좋은 하루 되시고요. 답변도 중요한데요. 이렇게 문서를 만드는 것이 힘들긴 하지만 더 귀한 것 같이 생각됩니다. 열심히 공부하세요. 한 가지 지금 생각나는 말씀은요. "잘 하는 것"과 "열심히 하는 것"은 다른 것이라고 합니다. 사회 생활일수록 더 그렇습니다. 그렇다고 포기하지 마세요. "열심히" + "시간/경력" = "잘" 이니까요. ^^; kenu 생각입니다. |
관련 사이트 |
xml-typed document http://okjsp.pe.kr/ |