수업 시간에 xce를 이용하여 미들릿을 만들어 에뮬레이터에 실행을 해보곤 한다. 음.. 그런데 이 미들릿을 컴파일 하는게 조금 복잡 하다. 어떻게 복잡하냐? 자바 버전은 source 는 1.2로 맞추어야 하고, bootclasspath 도 기존 자바의 것과 다른 xce에서 사용하는 classpath 를 사용하고, 또 이 생성된 class 파일 같은 경우 xce 프로그램이 설치 되어 있는 루트 디렉토리에 있어야 에뮬레이터에서 인식이 잘 된다.

에구에구 뭐가 이렇게 셋팅 해줄께 많은지....

갑자기 문뜩 떠오른 아이디어!!! 자바프로그램을 처음 입문하면서 난 컴파일에 대한 두려움을 하나도 못느끼게 해준 놈이 있다. 바로 ant란 놈이다. 이놈은 컴파일을 할때 path나 그런 설정들을 혹은 ftp접속 파일 삭제 jar파일 생성 같은 것을 일괄적으로 만들어 주는 놈이라 할 수 있다. 그래서 내가 자바 프로그램을 하는 회사에서도 자바 컴파일 버전이나 어떤 라이브러리를 임포트 할지에 대한 것을 자세히 몰라도 컴파일이 알아서 되고, ftp로 원하는 서버에 전송 까지 되는 것이였다.

이놈을 그렇게 힘들게 쓰지는 않더라도, 약간만 수정 한다면 쉽게 컴파일시 쉽게 만들수 있을것 같다는 생각이 문뜩 떠오르고 이렇게 한번 실행을 해보았다.

여기서 xce를 이용한 프로그램 방법은 설명 하지 않겠다.

자바 소스
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloWorldKbs extends MIDlet{
 
 private Display display;
 private TextBox t;
 
 /**
  * @param display
  */

 public HelloWorldKbs() {
  display = Display.getDisplay(this);
  t = new TextBox("Title", "HelloWorld", 80, 0);
 }
 protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
  // TODO Auto-generated method stub
 
 }
 protected void pauseApp() {
  // TODO Auto-generated method stub
 
 }
 protected void startApp() throws MIDletStateChangeException {
  // TODO Auto-generated method stub
  display.setCurrent(t);
 }
}


위의 소스는 이클립스 xce프로젝트를 생성하여 만든 HelloWorld 프로그램 이다. 핸드폰 화면에 텍스트 박스를 넣어서 HelloWorld라는 단어를 출력 하였다.

그리고 아래는 ant를 실행하는 build.xml 파일이다.
<?xml version="1.0"?>
 
<project name="HelloWorld" basedir="." >
 
<property name="src.dir" value="${basedir}/src" />
<property name="classes.dir" value="C:/Program Files/xce/WIPI-JAVA 2.0.2" />
<property name="org.classes.dir" value="${basedir}/classes"/>
<property name="jar.dir" value="c:/Program Files/xce/WIPI-JAVA 2.0.2" />
<property name="bootclasspath.dir" value="C:/Program Files/xce/WIPI-JAVA 2.0.2/classes"/>
 
<target name="compile" >
   <javac srcdir="${src.dir}" destdir="${classes.dir}" source="1.2" bootclasspath="${bootclasspath.dir}/classes.jar"/>
   <javac srcdir="${src.dir}" destdir="${org.classes.dir}" source="1.2" bootclasspath="${bootclasspath.dir}/classes.jar"/>
</target>
<target name="jar" depends="compile">
   <jar jarfile="${jar.dir}/HelloWorld.jar" basedir="${org.classes.dir}" includes="**/*.class" />
</target>
<target name="build" depends="compile">
 <antcall target="compile"/>
 <antcall target="jar"/>
</target>
</project>



User inserted image





위의 파일을 프로젝트의 기본에 build.xml로 만들어 주고, window view의 ant창을 연다음 build.xml파일을 ant창에 드롭 한다.그럼 ant창에서 리스트들이 나오게 되는데, compile 혹은 jar를 선택 그것의 오른쪽 클릭을 하게 되면 Run as -> Ant Build를 하게 되면 일일이 컴파일 하지 않아도 컴파일 되게 되고 jar도 생성 되게 된다.







위의 ant의 기본 path 는  xce를 설치 했을때의 path이다. 센스가 있으신 분은 알아서 변경 하실수 있을 것이다. 이렇게 ant를 사용하면 매번 일일이 컴파일 옵션을 기억하고 있다가 컴파일 하지 않아도 쉽게 빌드 할수 있다. ant의 다른 설정들은 알아서 찾아 보길 바란다.

User inserted image

비교 3번째네요. 제가 저번 프로젝트때 가장 기초적인 것임에도 불고 하고 제일 혼란해 했던.... 저혼자서 끙끙 앓다가 결국 물어봐서 해결본 것이에요. 그래서 물어보기 전까지 혼자서 생쑈를 했죠. ^^ 일단 코드를 보자구요.

C#코드
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;>
class HttpClientGet
{
    static void Main(string[] args)
    {
        HttpWebRequest wReq =
            (HttpWebRequest)WebRequest.Create(@"http://hahakbs.dothost.co.kr/reqTest.php?input=123256");
        wReq.UserAgent = ".NET Framwork Example Client";
        HttpWebResponse wResp = (HttpWebResponse)wReq.GetResponse();
        Stream respStream = wResp.GetResponseStream();
        StreamReader reader = new StreamReader(respStream, Encoding.Default);
        while (reader.Peek() >= 0)
        {
            String str = reader.ReadLine();
            Console.WriteLine(str);
            if (str.Equals("Y"))
                Console.WriteLine("Get Y");
            else
                Console.WriteLine("Get else");
        }
    }
}



 

결과
N
Get else



 

자바코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HttpRequest {
 public static void main(String[] args)
  throws MalformedURLException, IOException {
  HttpURLConnection connection =
   (HttpURLConnection) new URL("http://hahakbs.dothost.co.kr/reqTest.php?input=123456").openConnection();
 
  BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  String line;
  while ((line = in.readLine()) != null){
   System.out.println(line);
   
   if(line.equals("Y")) {
    System.out.println("Get Y");
   } else {
    System.out.println("Get else");
   }
  }
 }
}


 

결과
Y
Get Y



위의 예제는 간단하다. 미리 만들어 놓은 사이트에 input에 값을 Request한다. 그리고 그 것에 대한 값을 Stream 형태롤 받아서 그 값을 출력한다. input의 값은 123456 일 경우는 Y라는 문자열을 그 외의 경우에는 N이라는 문자열을 보낸다.

뭐 두개의 프로그램상 별다른 차이점은 그다지 없다. C#에서는 HttpWebRequset 객체를 생성하고 그 객체에서 리스폰스를 받아 스트림 버퍼로 읽고 그 읽은 값을 뿌려주고 비교해주고, 자바에서는 HttpURLConnection 객체를 URL객체의 커넥션으로 생성해 그 값을 버퍼 리더로 읽어서 뿌려준다.

자바쪽은 따로 Request나 Response 객체를 둔것이 아니라, Connection 객체를 두어 사용함으로서 조금더 간편하다고 할수 있을것이다. 그리고 어차피 읽어오는 응답텍스트 들은 각각의 스트림객체를 통해 읽어오는것은 비슷하다 할수 있겠다.

위처럼 간단한 것을 하기 위해 한참을 몰랐다가 알았을 때는 정말 한심했다. ^^ 물론 C#이 아니라 자바쪽을.... 왠지 자바쪽은 쉽게 접해지지 않는것 같다. 역시 MS쪽에 길들어 져서.

그런데 제일 혼란 스러웠던 것은 저것이 그냥 콘솔이 아니라, 웹 상에서 했기 때문이기도 하다. 요구점은 이것이였다. 웹 서비스에서 유저가 접속을 해서 내 페이지에서 숫자를 입력 하면, 그 결가 데이터가 자체 웹서버의 DB나 파일에 있는게 아니라 다른 웹에 입력값을 전송하고, 그 전송값에 대한 결과 값을 받아서 처리하는.. 그래서 감을 잡기가 힘들었던거 같다.

제 블로그에 자주 들러 주시는 분들이 계실지 모르겠네요. ^^ 어째던 죄송 스럽네요. 저 자신을 포함해서. 건강도 조금 안좋았고, 회사 일도 좀 치였고.. 그래서 블로그를 방치 상태로 ㅡ.ㅡ; 2월달은 쓴글이 한개도 없네요. 앞으로도 이런 저런 일이 있을수 있겠지만 다시 열심히 글 올려 볼랍니다.

오늘 이런 얘기를 들었는데, 회사 선배왈 '일하면서 어느 순간 실력이 늘으는 것 같이 느껴져도 느는게 절대 아니라내요 공부 안하면...' 뭐 결론은 공부 하라는 얘긴데요. 뭐 한달 남짓 일하면서 저도 많은걸 배웠지만, 저도 생각한게 절대 실력이 많이 늘었다고는 생각 안했습니다.

회사에서는 자체 프레임워크를 씁니다. 거의 다 지정되서 파라메터를 넘겨줄때도 지정 클래스에서 받고, 아무튼 되게 편하게 관리 할수 있게 해놓았습니다. 코딩하는건 그 프레임워크에 맞춰서 쓸수 있는 xml파일을 설정하고, 나머지는 조건간들것만 처리하고, 분명 관리하고 만들어내는 것은 쉽고 빨리 할 수 있지만, 내 마음대로 할 수 없으니 제약 조건이 크다는것을 느꼈고, 그 틀에 맞지 않으면 엄청 고생해야 한다는 것.

이번 프로젝트 하면서도 그것을 느꼈답니다. 그 프레임에 안맞으면 되게 힘들게 돌려야 된다는것!! 그렇다고 아직 초급개발자인 제가 그 프레임워크를 맘대로 고칠수도 없는 노릇이고, 과연 그게 제 실력이 될까 의문이 들기도 했답니다. 만약 다른 회사를 가게되면 프레임워크가 다르게 될테고 그렇게 되면 기존에 배웠던 것들이 무용지물이 될지도 모르지요.(그정도 까진 아니겠지만)

저는 앞으로 프레임워크를 만드는 사람이 되고 싶지, 그것을 써서 활용만 하는 사람만 되지는 않고 싶습니다.    흐흐흐


ps : 휴~~ 오늘은 구박을 너무 많이 들었어요 ㅜ.ㅜ 정말로 힘들고 뭐가 뭔지도 잘 모르겠었고.. 어제는 다 만들어 놓은것을 구조가 이렇게 나와서는 안된다고, 기획이 잘못됬다고 고치고. 누가 프로그램 구조가 잘못된 구조인지 알았나요? 그냥 만들래니 만든것 뿐인데. 신입인 제가 잘못된 구조라는 것을 어떻게 알겠어요

이놈의 귀차니즘 때문에 @.@ 글을.. 쓰고 싶은데 쏘스가 주어지고 해야될일이 생기니 에휴 ~~ 이놈의 핑계~ 어째던 이번에 알아볼 것은 db에 접속 하는것을 알아 보겠다. 그것도 동일한 sql문에 param 값을 설정 하여서 한개의 sql문으로 처리 하는 방법을 해보는 것이다.


자바 소스
import java.sql.*;
public class CallableTest {
 public static void main(String[] args) throws SQLException{
  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/mysql", "root", "apmsetup");
 
  PreparedStatement stmt;
 
  String sqlStr = "select * from db where id=?";
 
  stmt = conn.prepareStatement(sqlStr);
 
  stmt.setInt(1, 10);
 
  ResultSet rs = stmt.executeQuery();
 
  while(rs.next())
  {
   System.out.println(rs.getString(1));
  }
 
  stmt.close();
  conn.close();
 }
}



 

그리고 C# 소스
using System;
using System.Data;
using System.Data.SqlClient;

class SqlParamTest
{
    static void Main(string[] args)
    {
        string connStr = "Provider=MySQLProv;Data Source=mysql;" +
                         "Location=localhost;User Id=root;Password=apmsetup";
        string query = "select * from db where id=@ID";
        SqlConnection conn = new SqlConnection(connStr);
        conn.Open();
        SqlCommand comm = new SqlCommand(query, conn);
        comm.Parameters.Add("@ID", SqlDbType.Int);
        comm.Parameters["@ID"].Value = "10";
        SqlDataReader sr = comm.ExecuteReader();
        while (sr.Read())
        {
            Console.WriteLine(sr.GetInt32(0)));
        }
        sr.Close();
        conn.Close();
    }
}



위의 코드는 솔직히 실행해보지는 못했다. 일단 실행을 할려면 MySql 설치해야 하고, 공급자도 설치해야 하고.. 아마도 자바와 닷넷용 모두 설치해야 할것이다. 그렇다고 MSSql을 설치하기도 그렇고. 그러니 이해해 주시기를 바랍니다 ^^

어째던 DB 접속에 둘다 문제가 없다면 두개의 소스가 비슷한 동작을 할것이다. 일단 둘다 각각의 Connection 객체를 통해 일단 DB에 접속 했다. 그런데 여기서 약간의 차이점은 자바에서는 DBManager 를 사용하여 객체를 생성하고, C#에서는 객체 스스로 생성되었다. 그래서 그런지는 모르겠지만 C#으로는 Connection 객체를 open을 해주는데 자바에서는 해주지 않는다.

그리고 다음은 비슷한 동작을 하는 command == statement 이두 객체가 비슷한 동작을 한다. 커넥션 객체에서 각 쿼리를 실행 하기 위한 Sql명령을 가지고 있는 객체이다. 여기서 바뀌게 되는 파라 미터 값을 command 에서는 @param 으로 구분했고 statement 에서는 ?로 구분했다. 그리고 자바에서는 preparedstatement라는 객체를 따로 만들어야 했으나, C#에서는 command라는 객체의 다른 종류는 없었다.

그리고 데이터를 읽는 것은 각각의 Reader로 읽어 값을 읽었고, 마지막으로 각 파라미터에 값을 넣을때 Java에서는 셋팅을 할때 메서드를 호출에서 ? 순서에 따라 각각의 값을 지정하였고, C#에서는 각 파라미터의 @param를 가지고 셋팅후 값을 대입 2번의 수행을 하였다.

뭐 두개다 큰 차이는 없겠지만 자바에서는 param 들이 ?로 표시되어 각각을 지정하는데 유연함이 조금 떨어질수 있겠지만, C#에서는 2번 셋팅을 해주어야 해서 불편하다는 점이 내가 내린 결론!!



에구에구 오랜만에 쓰는데 왜이리 피곤한지.. 그리고 자바에서는 또 특이하게 callablestatement라는 놈이 있다. 이놈은 preparedstatement라는 놈과는 비슷하지만 다른부분이 있다. 좀더 알아보고 기회가 된다면 다름 글에 이야기 해보겠다.

2007/01/27 01:34

감격!!

드디어 찾았다~~ 휴~~ 명국아 찾았다~~ 으~~ 이 감격스러움 ㅜ.ㅜ

군대가기 전에 즉 03년도 5월 전에도 나는 프로그램 공부를 하고 있었다. 뭐 잘할줄 아는 것은 별로 없었지만.. 그 때 내 취미가 이런 저런 프로그램 받아 보고 실행해 보고 모아 놓고, 그런것들 이였는데 그 중에서 데브피아에서 어떤 분이 올려주신 프로그램이다. ksmpy@msn.com 이 분이 만드신 프로그램인데.. 이게 이게 아주 재밌는 프로그램이라서 군대 다녀온 후에도 기억이 났다.

어떤 프로그램이였나면 리눅스를 한번이라도 사용한 분이라면 쉽게 알수 있을것이다. 리눅스의 X윈도우를 한번이라도 써봤다면 보통 작업표시줄에 레드헷계열이라면 4개의 창이 있는걸 알수 있다. 그래서 1개의 구역에서 프로그램을 실행해 놓고, 다른쪽을 선택해서 다른 창을 열면 작업표시줄에 하나도 없이 또 새로운 프로그램을 실행 시켜 놓을수 있다.

MS윈도우는 아쉽게도 이런기능이 없다. 그런데 이러한 기능을 비슷하게 해놓은 프로그램을 군대가기 전에 데브피아에서 인가 받았던 사실을.... 그런데 그 때는 필요가 없었다. 학생이 무슨 필요가 있겠나 그런 영역을 구분해 봤자 리소스만 많이 잡아 먹고.. 여태까지도 필요가 없었다....

그런데 회사를 취직 하면서 솔직히 많이 생각이 났다. 아무래도 눈치도 보이고 ^^ 그리고 이 프로그램을 가지고 있었던 이유가 이때를 위해서 으흐흐흐(만들어 볼 생각은 안하고.. 정신머리가 썩을..)

그래서 예전부터 그 프로그램을 찾아 봤지만, 내가 군대 있을 동안 동생이 컴퓨터도 망가 트리고.. 이런 저런 일이 있으면서 데이터를 백업해 놓긴 했는데 도저히 못찾았던 프로그램을 장장 3시간동안 온 CD를 다 뒤져서 찾았다. 으흐흐흐~~ 찾고 나서 펄쩍 뛰었다.

User inserted image




다음 프로그램을 실행 시키면 다음과 같이 트레이 창에 트레이가 하나 생긴다.

User inserted image



마우스를 가져다 대고 오른쪽 버튼을 눌르면 다음과 같은 팝업 메뉴가 뜬다.

User inserted image
User inserted image













대충 눈치 채신 분을 알겠지만 바탕 설정이 한 작업 환경이다. 이작업 환경을 옮기면 작업표시줄에 있던것이 안보이고 감추어 지게 된다. ^^ 그런데 아쉽게도 단축키로 옮겨지지가 않는다. 그대신 트레이 아이콘쪽에 아이콘을 가져다 대고 더블클릭을 하면 0 에서 1번 으로 1에서 2로 이렇게 옮겨 지게 된다.




프로그램은 위에 있고, 아참 위의 프로그램은 제가 만든것이 아니고 ksmpy@msn.com 아이디를 쓰시는 분께서 만드셨으니, 저작권이나 어떠한 권리도 저에게 없고 불쾌하시거나 저작권 문제가 있으실 경우에는 요청 하시면 바로 삭제하겠습니다. 어째던 감사합니다. ^^ 복받으실 거에요~~ 03년도에 만든 프로그램이니 더 업그레이드 된 버전은 없나요?

C# 2007/01/24 21:24

private 생성자..

나는 private로 만드는 생성자는 잘 쓰지 않는다. 글세 나만 잘 안쓰지 다른 사람들은 잘쓸지도 모르겠다. ^^ 백마디 말보다 소스 한번 보자~~

class PrivateConstruct
{
    private static PrivateConstruct privateConstruct = null;
    private int sumX;
    private int sumY;
    private PrivateConstruct()
    {
        Console.WriteLine("Private Construct~~");
    }
    public static PrivateConstruct getInstance()
    {
        if (PrivateConstruct.privateConstruct == null)
            PrivateConstruct.privateConstruct = new PrivateConstruct();
        return PrivateConstruct.privateConstruct;
    }
    public int Sum()
    {
        return (this.sumX + this.sumY);
    }
    public int i
    {
        get
        {
            return this.sumX;
        }
        set
        {
            this.sumX = value;
        }
    }
    public int j
    {
        get
        {
            return this.sumY;
        }
        set
        {
            this.sumY = value;
        }
    }
    static void Main(string[] args)
    {
        PrivateConstruct pc1 = PrivateConstruct.getInstance();
        PrivateConstruct pc2 = PrivateConstruct.getInstance();
        pc1.i = 1;
        pc1.j = 2;
        Console.WriteLine("pc1 의 sum() 메서드 " + pc1.Sum());
        Console.WriteLine("pc2 의 sum() 메서드 " + pc2.Sum());
    }
}



 

결과
Private Construct~~
pc1 의 sum() 메서드 3
pc2 의 sum() 메서드 3



위에서 PrivateConstruct 는 싱글톤 형태의 서비스를 한다. 싱글톤 서비스란 나는 웹서비스 쪽에서 처음 접했는데, 어떤 서비스를 요청할때 마다 매번 새로운 서비스를 만드는 것이 아니라, 딱 한번만 그 인스턴스를 만드는 것이다. 그래서 만든것을 가져다 사용 하는것이다. 그럼으로 이점은 숫자 카운팅이나 잊어버리지 않을 성격의 것들을 기억 할수 있다. 웹서비스가 멈출때까지...

그것을 구현하기 위해서 private 형으로 생성자를 선언했다. PrivateConstruct는 단 한개의 인스턴스만 있으면 된다. 뭐 위에 프로그램은 간단해서 문제가 없을지 모르겠지만, 만약 큰 통합 프레임워크 같은 경우에는 PrivateConstruct를 쓰게 된다면 어디선가 그냥 생성할수 있을것이다. 이것을 방지 하기위해서 private 생성자로 생성자을 만들어 놓으면 그냥 가져다 쓸경우 생성을 할수 없게 된다. 이런 경우 private 생성자를 사용하는것이 유용하게 쓰인다. ^^


div>