아주 심플하지만, 정말 해보고 싶었던 기능이었다..

중요한 웹 서버가 장애가 났을 때, 모니터링을 SMS로 받지만 모든 사람이 다 받기에는 고역이다.
그래서, 관리자도 알게 하고 주위로부터 일종의 경고를 알림으로서, 지금 우리는 장애를 처리하고 있다는 것을 알려주고 싶었다.


(자세한 내용은 아래 레퍼런스 참조)

http://knight76.tistory.com/entry/아두이노-프로세싱-연동-어플에서-버튼을-누르면-불-깜빡거리게-하기

http://knight76.tistory.com/entry/프로세싱-언어가-자바-언어로-변환

http://knight76.tistory.com/entry/프로세싱processing-이클립스연동

http://knight76.tistory.com/entry/me2day-의-특정-글에-리플을-달면-램프-깜박이게-하기-아두이노-이클립스-연동




이클립스 자바 소스

localhost로 떠있는 웹서버가 죽으면, 바로 깜박거리게 한다.

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import processing.core.PApplet;
import processing.serial.Serial;

public class PingTest extends PApplet {
 static int replyNumber = 0;
 Serial port;

 /**
  * 초기화
  */
 public void setup() {
  System.out.println("setup - start");
  System.out.println("Available serial ports:" + Serial.list().length);
  for (String comport : Serial.list()) {
   System.out.println(comport);
  }

  if (Serial.list().length == 0) {
   System.out.println("## NO DETECT ##:");
   System.out.println("end programe");
   System.exit(0);
  }

  // list[1]에 com3로 arduino가 붙어 있다.
  port = new Serial(this, Serial.list()[1], 9600);
  ScheduleJob job = new ScheduleJob();
  Timer jobScheduler = new Timer();
  jobScheduler.schedule(job, 0, 3000);
  System.out.println("setup - end");
 }

 // draw 메소드를 override 해줘야 JApplet을 이용해서 serial 을 사용하는 코드에서 문제가 나지 않는다.
 public void draw() {
 }

 static public void main(String args[]) {
  PApplet.main(new String[] { "--bgcolor=#F0F0F0", "PingTest" });
 }

 /**
  * Timer Task를 상속함
  *
  */
 class ScheduleJob extends TimerTask {
  @Override
  public void run() {
   if (!isok()) {
    blink();
   }
  }
 }

 public boolean isok() {
  String url = "http://localhost/";
  HttpURLConnection.setFollowRedirects(false);
  HttpURLConnection con;
  try {
   con = (HttpURLConnection) new URL(url).openConnection();
   con.setRequestMethod("GET");
   con.setConnectTimeout(5000);
   con.connect();
  } catch (MalformedURLException e) {
   e.printStackTrace();
   return false;
  } catch (IOException e) {
   e.printStackTrace();
   return false;
  }
  return true;
 }
 
 
 /**
  * 깜빡, 깜빡~
  */
 public void blink() {
  for (int i = 0; i < 3; i++) {
   // turn on led
   port.write(255);
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   port.write(0);
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }

 }
}




접속이 안되면,  Exception이 생기고, LED가 깜박거리게 된다.

java.net.ConnectException: Connection refused: connect
 at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
 at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:75)
 at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:337)
 at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:198)
 at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
 at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
 at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
 at java.net.Socket.connect(Socket.java:579)


여기서 좀 더 응용을 하면, http response가 200, 304가 아닌 것에 대한 모든 것에 대해서 에러로 처리할 수도 있을 것이다.



Posted by '김용환'
,

 

이클립스-아두이노를 연동하여 특정 글에 리플이 추가되거나 삭제될 때마다 램프를 깜박이게 하려는 데모를 작성했다. 하다 보니. me2day api 연동 글이 되어 버렸다.

 

1. api 사용자키를 확인

미투 웹의 설정화면에 접속하여 api 사용자 키를 확인한다.

http://me2day.net/knight111111/setting

 

 

2. 애플리케이션 키 발급 및 사용

m2api 를 사용하기 위해서 애플리케이션 키를 발급해야 한다.

http://me2day.net/api/front/appkey

 

http://me2day.net/me2/app/edit_appkey 에 접속하고, 애플리케이션 키 (appkey) 값을 확인한다.

미투 개발서버에서 메일로 웹에서 보았던 애플리케이션 키(appkey) 값을 전달해준다.

미투 Open API(http://dev.naver.com/openapi/apis/me2day/me2api_intro#metwo2)에 따르면, 헤더에 ‘me2_application_key’을 이용하거나, GET/POST 파라미터에 'akey'를 넣으면 된다고 하며 모든 m2api 호출시 반드시 넣어야 한다.

 

나는 웹 파라미터를 이용한 방식을 사용해 본다. 웹으로 동작되는지 확인한다.

http://me2day.net/api/get_posts/$계정명$.xml?akey=발급받은애플리케이션키
(발급 받은 애플리케이션 키(appkey)가 없어도 볼 수는 있다.)

http://me2day.net/api/get_posts/knight111111.xml?akey=7f4e6364d7f4dd8bf7072c11f20b3be0

 

3. 인증

글쓰기, 친구신청, 쪽지 쓰기 등 사용자 본인만 할 수 있는 것을 하려면, 인증을 해야 한다.

미투 API 인증 절차(http://dev.naver.com/openapi/apis/me2day/me2api_intro#metwo3)가 있다. 나는 이미 있는 라이브러리를 쓰기로 했다.

미투 API 참고자료(http://dev.naver.com/openapi/apis/me2day/me2api_intro#metwo4)에 보면 외부 개발자가 다양한 언어별로 클라이언트 라이브러리 개발한 것이 있다. 자바의 경우는 예전에 많든 소스와 구글 프로젝트 코드(http://code.google.com/p/me2day-api/) 가 있는데, 나는 간단히 테스트만 할 것이라 me2api-java14-src.tar.gz 만 다운받았다.

 

코드는 아래와 같이 사용하면 포스트가 된다.  (실제 인증에 대해서 궁금한 사람은 Me2API 클래스의 request()메소드를 참조한다.)

        Me2API me2api = new Me2API();
        me2api.setUsername("knight111111");
        me2api.setApplicationKey("7f4e6364d7f4dd8bf7072c11f20b3be0");
        me2api.setUserKey("67000463");
        me2api.post("test");

 

4. 댓글자 확인

http://me2day.net/api/get_posts/knight111111.xml  URL을 통해서 body 글을 확인하고 포스트의 id가 “pyhja7h-665uq”인지 확인한다.

http://me2day.net/api/get_comments/xml?post_id=pyhja7h-665uq URL은 댓글 정보를 알 수 있다.  이 정보를 파싱하는 방법이 있지만, 이미 있는 api가 있으므로 그것을 활용한다.

 

me2api-java14 클라이언트 라이브러리를 이용해서 reply-test 댓글을 단다.

Me2API me2api = new Me2API();
me2api.setUsername("knight111111");
me2api.setApplicationKey("7f4e6364d7f4dd8bf7072c11f20b3be0");
me2api.setUserKey("67000463");
me2api.createComment("pyhja7h-665uq", "reply-test");

 

4. 아두이노 연동

특정 글이 리플이 달릴 때마다 아두이노에서 램프를 깜박이게 하는 것이다. 이 데모를 따라하기 위해서는 “http://knight76.tistory.com/entry/프로세싱processing-이클립스연동” , “http://knight76.tistory.com/entry/아두이노-프로세싱-연동-어플에서-버튼을-누르면-불-깜빡거리게-하기” 정보를 참조하면 좋다.

 

이클립스 프로젝트의 Referered Libraries 정보이다.

이클립스의 자바 코드

import java.io.IOException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.ParserConfigurationException;

import net.me2day.java.Comment;
import net.me2day.java.Me2API;
import processing.core.PApplet;
import processing.serial.Serial;

public class Me2dayReplyTest extends PApplet {
    static int replyNumber = 0;
    Serial port;

    /**
     * 초기화
     */
    public void setup() {
        System.out.println("setup - start");
        System.out.println("Available serial ports:" + Serial.list().length);
        for (String comport : Serial.list()) {
            System.out.println(comport);   
        }
       
        if (Serial.list().length == 0) {
            System.out.println("## NO DETECT ##:");
            System.out.println("end programe");
            System.exit(0);
        }
       
        // comment 개수
        replyNumber = getCommentNumber();
       
        // list[1]에 com3로 arduino가 붙어 있다.
        port = new Serial(this, Serial.list()[1], 9600);
        ScheduleJob job = new ScheduleJob();
        Timer jobScheduler = new Timer();
        jobScheduler.schedule(job, 0, 3000);
        System.out.println("setup - end");
    }
   
    // draw 메소드를 override 해줘야 JApplet을 이용해서 serial 을 사용하는 코드에서 문제가 나지 않는다.
    public void draw() {
    }

    static public void main(String args[]) {
        PApplet.main(new String[] { "--bgcolor=#F0F0F0", "Me2dayReplyTest" });
    }

    /**
     * Timer Task를 상속함
     *
     */
    class ScheduleJob extends TimerTask {
        @Override
        public void run() {
            int commentNumber = getCommentNumber() ;
            if (commentNumber != replyNumber) {
                blink();
                replyNumber = commentNumber;
            }
        }
    }

    /**
     * 특정 글에 대한 Comment 개수 구하기
     * @return
     */
    public int getCommentNumber() {
        Me2API me2api = null;
        try {
            me2api = new Me2API();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        me2api.setApplicationKey("7f4e6364d7f4dd8bf7072c11f20b3be0");
        me2api.setUserKey("67000463");
        List<Comment> list = null;
        try {
            list = me2api.getComments("pyhja7h-665uq");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("list number : " + list.size());
        return list.size();
    }
   
    /**
     * 깜빡, 깜빡~
     */
    public void blink() {
        for (int i = 0; i < 3 ; i++) {
            // turn on led
            port.write(255);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            port.write(0);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

아두이노 소스는 기존과 동일하게 Serial로 전달된 정보를 받고 LED에 값을 변경한다.

 

 

const int ledPin = 8;      // the pin that the LED is attached to

void setup()

{

  // initialize the serial communication:

  Serial.begin(9600);

  // initialize the ledPin as an output:

  pinMode(ledPin, OUTPUT);

}

void loop() {

  byte brightness;

  // check if data has been sent from the computer:

  if (Serial.available()) {

    // read the most recent byte (which will be from 0 to 255):

    brightness = Serial.read();

    // set the brightness of the LED:

    analogWrite(ledPin, brightness);

  }

}

 

특정 글에 comment를 넣어주는 클라이언트 코드는 아래와 같이 하거나.. 직접 글에 댓글을 달아주면 된다.

public class Me2Test2 {
    public static void main(String[] args) throws Exception {
        Me2API me2api = new Me2API();
        me2api.setUsername("knight111111");
        me2api.setApplicationKey("7f4e6364d7f4dd8bf7072c11f20b3be0");
        me2api.setUserKey("67000463");
        me2api.createComment("pyhja7h-665uq", "reply-test");
    }
}

 

테스트하니 정상적으로 잘 동작한다.

 

 

 

참고) java.lang.RuntimeException: Error inside Serial.write() 발생시에 대한 대처 방법

아래와 같은 에러가 난다면, draw() 메소드를 반드시 override 해야 한다. draw() 메소드를  override 하면 아래 에러는 더 이상 발생하지 않는다.


java.lang.NullPointerException
    at processing.serial.Serial.write(Unknown Source)
    at Me2dayReplyTest.blink(Me2dayReplyTest.java:98)
    at Me2dayReplyTest$ScheduleJob.run(Me2dayReplyTest.java:63)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)
Exception in thread "Timer-0" java.lang.RuntimeException: Error inside Serial.write()
    at processing.serial.Serial.errorMessage(Unknown Source)
    at processing.serial.Serial.write(Unknown Source)
    at Me2dayReplyTest.blink(Me2dayReplyTest.java:98)
    at Me2dayReplyTest$ScheduleJob.run(Me2dayReplyTest.java:63)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)


 //   public void draw() {
//    }
->

    public void draw() {
    }

Posted by '김용환'
,

 

좋은 글을 발췌 해 본다.

 

자발적으로 올바르게 사색하는 사람은 올바른 길을 발견하는 나침반을 준비하고 있다.

 

단지 남에게 배워서 얻은 진리는 우리게 부착되어 있을 뿐, 그것은 마치 의수, 의족, 의치 아니면 초로 만든 코, 다른 살을 이용하여 정형 수술한 코 같은 것이지만, 스스로 사색하여 얻은 진리는 산 수족과 같은 것으로 그것만이 정말로 우리 자신의 것이다.

 

너무 많이 읽는 것은 좋지 않다. 왜냐 하면 정신이 대용품에 길이 들어 생각하는 것 자체를 잊어버리게 하기 때문이다. 즉, 다른 사람이 이미 닦아 준 길을 잊어버려, 그 발자취를 더듬을 뿐 자기의 방법으로 생각하는 것으로부터 멀어져 간다면 아무 일도 안 되기 때문이다.

Posted by '김용환'
,

log4jdbc

java libs 2011. 12. 16. 10:40

jdbc driver 의 PreparedStatement에 대한 코드를 잘 분석해줄 수 있는 툴이다.

select * from athlete where code=?  이라는 쿼리에 동적으로 데이터 A 를 넣는 경우에 로그로

select * from athlete where code=A 라고 출력한다.

참고 자료

http://stackoverflow.com/questions/6315057/log4jdbc-preparedstatement-tostring

http://code.google.com/p/log4jdbc/

http://www.mimul.com/pebble/default/2008/10/24/1224847200000.html

http://www.cubrid.com/zbxe/modules/board/skins/xe_board_cubrid_tutorial/tutorial.php?srl=47278&htm=log4jdbc.htm

http://dev.anyframejava.org/anyframe/doc/core/3.1.0/corefw/guide/query-sqllogging.html

Posted by '김용환'
,

Window Live Writer 2011을 써보니 확실히 좋았다. 어떤 장점이 있는지 작성해 본다.

1. Style을 제대로 활용할 수 있다.

 

2. 블로그의 프로세스에 맞게 사용 가능하다.

블로그 글은 ‘글 작성’단계와 ‘퍼블리싱’ 단계로 나누어질 수 있다.

‘글 작성’ 단계에서는 로컬에 저장이 가능하게 할 수 있다.

 

‘퍼블리싱’ 단계에서는 블로그에 임시 저장 또는 블로그에 등록할 수 있다.

 

3. 표 그리기가 편하다.

블로그의 글을 쓰기 위해 Word에 먼저 작성하는 경우가 있다. 이 때, Word로 만든 초안을 복사해서 블로그에 붙일 때, 블로그의 Editor 특성에 따라 표가 꼬이는 일이 벌어진다. 특히 XE의 Smart Editor가 대표적인 예이다.

Window Live Writer 2011 제품은 완벽하지는 않지만, 쓸만하게 작성이 쉽다.

  테스트1 테스트2 테스트3
A 솔루션      
B 솔루션      

 

4. 미리보기 & 소스 기능이 있어서 편하다.

어떻게 나올지 모르는 부분을 미리 방지할 수 있다는 점이 훌륭하다.

 

5. 이미지 사용이 편하다.

이미지 때문에 고생했던 것이 확실히 사라진다. 파일 파일 업로드 할 필요 없이 편집기에 캡쳐한 이미지를 복사만 하면 된다. (하지만 생각 만큼 예쁘게 나오지 않는다. size를 줄여 용량을 줄이지만, 이 정도면 참을 만하다. )

효과를 쉽게 넣을 수 있다.


6. 동영상 삽입이 수월하다.

동영상 삽입시 유튜브나 로컬 파일, 인터넷에 올라가 있는 부분들을 잘 찾아내어 쉽게 연동 가능하게 한다.

 

실제로 넣었을 때, 편하게 사용할 수 있다.

 

7. 맞춤법 검사를 할 수 있다.

블로그에 글을 쓸 때마다 오타나 문법 체크를 자동으로 해주지 못해서 미리 Word 에 쓰는 경우가 많았는데, 맞춤법 검사를 글쓰면서 할 수 있다는 점이 큰 장점이다.

8. UI가 MS Word 나 MS Office Outlook 의 메일 쓰기 화면과 비슷해서 큰 무리가 없다.

9. 태그, 사진 앨범, 지도,이모티콘 등 편리하게 지원되는 개체는 글을 에디터에 제한을 받지 않아도 된다.

10. 다양한 플러그인을 설치하며 마음껏 응용이 가능하다.


이 정도 정리한 Window live Writer 2011 의 장점이다. 나에게 있어서 최고의 발견품이다. MS 땡큐!


(추가됨)
파일 업로드,  블로그(티스토리) 에 연동되는 글상자 기능이 없어 2% 아쉽다.

http://demun.thoth.kr/?document_srl=252065

Posted by '김용환'
,

1. 다운로드

http://explore.live.com/windows-live-writer 에서 다운로드를 선택한다.

(설치 시, 모든 툴을 설치할 필요 없이 필요 없는 툴들은 선택해서 정리한다.)



2. Tistory 에서 Blog API 지원 여부 확인 및 설정

Tistory의 관리자 메뉴에서 [글설정]->[BlogAPI] 화면에서 API 사용 여부에서 API 사용 여부인지 확인한다.



3. 시작 메뉴

모든 프로그램->Window Live->Window Live Writer 실행



4. Tistory 사용자의 경우는 기타 서비스를 선택한다.



5. 블로그 계정을 추가한다.



6. 닉넥임을 설정한다.



7. MS Word 또는 Outlook의 메일 쓰기 화면과 비슷한 화면이 나타난다.



8. 내용을 작성하고 난 후 미리보기를 눌러본다.

Window Live Writer 2011 의 하단에 보면 '미리 보기’를 사용한다.

8. 내용을 작성하고 올려본다.

 



9. Tistory 계정에 접근해서 확인한다.

잘 된다. ^^

 

결론 : 앞으로 Window Live Writer 2011으로 잘 써야지….

Posted by '김용환'
,

MicroSoft에 근무하는 Scott Hanselman 이라는 분이 개발자에게 유용한 툴을 공유했다.

http://www.hanselman.com/blog/ScottHanselmans2011UltimateDeveloperAndPowerUsersToolListForWindows.aspx

완전 괜찮은 툴들을 소개시켜 주었다.내가 아는 것도 있고, 새로운 것도 있는데. 나는 소개된 툴 중 좋을 만한 것을 적어본다. 잘 써봐야겠다.
 
 * window live writer 2011은 MSword에 플러그인으로 wordpress에 연동하여 쉽게 글을 쓸 수 있도록 연동한 것이 있다. 그동안 블로그를 쓰면서 이 부분에 고민이 많았는데. 쉽게 연동할 것 같다. 

* Bins 이거 iPHONE 의 그룹처럼 해주는 윈도우 툴이다. 완전 귀엽다. 

* SQL Designer 은 웹으로 table schema 로 만들 수 있다. 귀찮은 거 설치 안해도 된다.

* Terminals 라고 해서 데스크탑 매니저(mstsc)이 하나의 터미널 창만 지원하는 것에 반해 multi로 지원되는 녀석이 있다. 오홋! 굿~
Posted by '김용환'
,

Cassandra mmap 이슈로 소스를 살펴보고 있는데, 빌드 체계가  Ant-ivy에서 Ant-maven으로 바뀌었다. 이에 대한 이유를 살펴보도록 한다. 내가 속한 조직에서는 Ant + Ivy를 사용하고 있는데, 이에 대한 보완 또는 빌드 속도 향상에 도움이 되지 않을까 해서 공부해본다.

Ant-Ivy 구조에서 Ant-Maven으로 바뀐 부분에 대한 내용은 Cassadra에서 올라온 이슈(https://issues.apache.org/jira/browse/CASSANDRA-2017)를 살펴본다.

첫번째, cassandra가 플랫폼 형태로 쓰기 때문에 maven central repository로 올려야 사람들이 편하게 쓸 수 있어야 한다. ivy는 pom 파일을 생성하지 못하기 때문에 maven-ant-tasks 가 필요하다.
두번째, gpg 시그내처 (보안) 를 생성하기 위해서 ivy task를 또 다시 실행시켜야 하는 것이 있는데, maven-ant-task는 한번에 gpg 시그내처를 생성할 수 있다.
세번째, dependency 정보를 한곳에서 할 필요가 있다. (아마도 maven central에 올리면서 중복 정보가 생기는 부분에서 얘기가 된 것 같다. 오해를 위해서 ivy.xml 파일 하나에서 충분히 관리될 수 있다. ivy는 maven에 비해 보기는 편하다.)

이외에 빌드할때, dependency 체크가 ivy보다 빨라서 빌드 속도 개선이 되었다고 한다.

그래서 0.7.6부터 배포되었다.  (http://pkgsrc.se/databases/apache-cassandra)

아직 회사에서 사용하는 것이 특별히 이슈는 없지만, ant-maven으로 고민할 필요가 있다는 생각이 들었다..



'Web service' 카테고리의 다른 글

hash dos 공격 with Tomcat  (1) 2012.01.17
2012년 초 Webwork / struts2 보안 이슈  (0) 2012.01.16
Webwork(Strust2), OGNL, Sitemesh  (0) 2011.12.13
이클립스 - PHP-Java 개발환경 구축  (0) 2011.12.07
gcDaemonProtection false 설정  (0) 2011.11.17
Posted by '김용환'
,

이예 - 일본 통상기

리더쉽 2011. 12. 14. 13:30



나의 멘토는 나에게 '포지션보다 사명에 헌신하라'고 하신다. 내가 어떤 사람이 되기 보다는 어떻게 살아야 하는지를 알려주신다. 어떻게 사는지가 중요하다..

오늘 클리앙( & 오유) 을 보는데, '이예'라는 굉장히 좋은 분이 계셔서, 잘 정리하고자 메모한다. 사람을 섬기는 그 분의 모습을 보면서 많은 감동이 있었다.

출처는 "오늘의 유머"싸이트. (http://todayhumor.co.kr/board/view.php?kind=todaybest&table=humorbest&no=416986)



 






 





출처 : 위키 http://ko.wikipedia.org/wiki/%EC%9D%B4%EC%98%88_(1373%EB%85%84)

생애1397년 1월 31일 3천명의 왜구들이 울주포[2]에 침입하여 군수 이은(李殷) 등을 사로잡아 돌아갔다.[3] 다른 관리들이 모두 도망가 숨은데 비해 이예는 자진해 군수를 따라가 끝까지 보필해 해적들을 감복시켰다. 후일 조선에서 파견한 통신사의 중재로 1397년 2월 이예는 군수와 함께 무사히 조선으로 돌아왔다.

조정에서는 이예의 충성을 가상히 여겨 아전의 역(役)을 면제하고 벼슬을 주었다. 이 사건을 계기로 이예는 중인 계층의 아전 신분에서 벗어나 사대부 양반으로서의 전문 외교관의 길을 걷게 된다. 8세 때 해적에게 잡혀간 어머니를 찾기 위해 조정에 청해 1400년 회례사(回禮使) 윤명(尹銘)의 수행원으로 대마도에 갔으나 찾지 못했다.[출처 필요]

처음으로 사절의 책임을 맡은 것은 1401년(태종1년)으로, 보빙사로 일기도에 파견되었다. 1406년 일본 회례관(日本回禮官)으로 파견되어, 납치되었던 남녀 70여 명을 데리고 돌아왔다.[4] 1416년 1월 27일 유구국[5]으로 가서, 왜에 의해 포로가 되었다가 유구국으로 팔려간 백성을 데려오기 위해 유구국으로 파견되었다.[6] 그는 유구국에서 44인을 데리고, 같은 해 7월 23일 귀국하였다. [7]

1418년 4월 24일 태종 18년 대마도 수호 종정무가 사망하자, 조의 사절로 대마도에 파견되어 쌀, 콩, 종이를 부의하여 그의 충성을 후사하였다. 종정무는 치세 기산 도적을 금제하여, 변경을 침범하지 못하게 했다는 이유로 특별히 이예를 파견한 것이다. [8]

“ 모르는 사람은 보낼 수 없어서, 이에 그대를 명하여 보내는 것이니, 귀찮다 생각하지 말라. ”
—《세종실록》, 세종8년에 통신사로 일본으로 떠나는 이예에게 임금이 갓과 신을 하사하며 당부하는 말
 

1443년 세종 25년 왜적이 변방에 도적질하여 사람과 물건을 약탈해 갔으므로 나라에서 사람을 보내서 찾아오려 하니, 이예가 자청하여 대마도 체찰사(對馬島體察使)로 파견되었다. 이것이 마지막 사행(使行)이었다.

28세 나던 1400년에서 71세 나던 1443년까지 44년간 40여회 일본[9]에 임금의 사절로 파견되었다. 그 중 조선왕조실록에 기록되어 사행(使行)의 내용이 구체적으로 알려진 것만 해도 13회에 달한다[10].

조선왕조실록에는 44년간의 사행에서 이예가 쇄환해온 조선인 포로의 수가 667명이라고 기록되어 있다.

[편집] 업적일본인의 조선 입국 허가와 관련한 문인제도와 양국의 교역조건을 규정한 계해약조를 정약하는 등 많은 업적을 남겼다.

세종의 명으로 대장경을 일본에 전달하고 조선에 자전(自轉) 물레방아를 도입하였으며 일본식 상가제도의 시행을 건의하는 등 양국 문화 및 경제의 교류에도 크게 기여하였다.

또한 사탕수수의 재배와 보급, 또한 민간에 의한 광물채취자유화와 이에 대한 과세, 화통 및 완구의 재료를 동철에서 무쇠로 변경, 외국 조선기술의 도입 등을 건의한 바 있다.





멋진 분이다!!
 

Posted by '김용환'
,




(이미지 출처 : http://www.identropy.com/blog/. 사진만 링크걸음)


2010년 하반기, 나는 회사에서 FOSS 거버넌스 정책에 대한 초안을 잡았다. 조직이동을 하면서 아이디어와 개념만 잡는 일만 하고, 거버넌스에 대한 실무는 내가 직접 하지 않았다는 점이 가장 흠이지만. 큰 틀에서는 내가 생각한 큰 틀은 지금도 이어지고 있다. 사실 내가 하고 싶어서 한 것은 아니고, 시간이 약간 널널한 관계로 정리했었던 것 같다.

(내 생각에는 내가 뛰어나서기 보다는 시간이 많아서 된 것 같다. 절대로 내가 특출난 능력이 있어서 한 것은 아니다. 사실 난 많이 부족한 사람이다. )

회사 특성상, 오픈 소스를 많이 활용하고 있다. 웹 서비스 및 솔루션 특성상 많은 오픈 소스 라이브러리를 알고 언제든기 개발할 준비가 되어있어야 한다. 그러나 워낙 많은 오픈 소스들이 범람하고 있고, 잘못하다가는 장애로 이어질 수 있는 수많은 장애가 있기 때문에 반드시 이 부분이 있어야 했다.

단순히 오픈 소스 소프트웨어 는 아무거나 쓰세요 하기에는 중요한 결정을 하는 조직에 있었고, 많은 개발자들이 새로 나온 오픈 소스 소프트웨어 또는 버그가 충만한(?) 오픈 소스 소프트웨어의 특이 버전을 쓰면서 이슈가 될 수 있었다. 오픈 소스 소프트웨어를 쓰면서 문제나 장애가 생기면 누구의 책임인가? 하는 고민들이 생기던 시점이었다. 그리고 회사에 많은 서비스조직이 있다보니 계속 반복된 장애는 계속 다른 부서에서도 나타났다. 마치 메아리처럼 이 산, 저 산 부딪히듯이 계속 발생되는 경우가 있었다.

또한 거버넌스 (Governance)라는 단어는 사람마다 달리 생각할 수 있는 모호한 단어였다. 거버넌스란 무엇인가? 거버넌스의 한계는 어디까지인가? 정부가 통제하듯이 하는 것인가? 가이던스(Guidance) 라는 단어와 많이 비슷한 느낌이면서 먼가 Push하는 느낌 때문에 초안 잡는 부분에 힘이 들었다. 너무 관여하면 자율성에 문제가 일어나고, 너무 멀리 있으면 장애나 서비스개발에 어려운 점들이 많았다.

인터넷을 통해서 다양한 정보를 얻으려 했지만, 결코 정보를 취합하지는 못했다. 거버넌스 하는 회사가 한국 뿐 아니라 외국에도 없는 독특한 사례였다. 단순히 Test 의 개념이나 Regressive Test 개념정도로 거버넌스를 바라보는 자료도 있었다. 좋은 선례가 없어서 결국 우리 회사안에서의 FOSS 거버넌스를 직접 하기로 했다.

나는 여러가지 인문서와 성경을 참조했다.
- 헤겔의 역사철학 강의
- 예링의 권리를 위한 투쟁
- 키케로의 의무론
- 루소의 사회계약론
- 홉스의 리바이던
- 애덤스미스의 국부론
- 토마스 모어의 유토피아
- 로크의 정부론
- 아리스토텔레스의 정치학
- 하이데거의 존재와 시간

우선 거버넌스를 하기전에 많은 것을 알아햐 했다. 사람에 대해서 알아야 했었다. 조직이란, 사람이란 무엇인가? 그리고, 어떻게 해야 유익할 것인가? 선한 게 행동할 것인가? 개발자는 어떤 사람인가? 관리자는 어떤 사람인가? 이 조직의 롤은 무엇이고, 다른 조직의 롤은 무엇인가? 바람직한 거버넌스는 무엇인가? 협업은 어떻게 할 것인가?하는 많은 고민을 하고 또 고민했다. 사람을 이해하고 조직을 이해하는 과정 속에서 다른 사람들은 어떻게 문제를 해결하려고 했을까 하는 수많은 생각들을 접하면서 깊이 고민했다.
(이런 시간들을 통해서 나는 겸손함을 더욱 더 배웠던 시간이었다. 나보다 똑똑하고 훌륭한 사람들이 많았고, 그 분들을 통해서 사회를 볼 수 있었다. 그러나.. 내 안에 아직도 많은 식견이 부족해서 많이 다듬어야 할 것 같다. )

내가 과연 모든 사람이 만족할만한 완전한 거버넌스를 만들어낼 수 있을까? 라는 고민속에 초안을 작성하기 시작했다. 잘못된 방향과 설득으로 인해서 어중간하게 하다가 종료하는 것은 없도록 해야할 것 같았다. 감사하게도 조직장과 좋은 피드백을 통해서 좋은 초안이 만들어지기 시작했다.

오픈 소스 거버넌스의 사용 조건, 오픈 소스 거버넌스 결과에 대한 게시판, 오픈 소스 거버넌스 조직은 모든 오픈소스를 다 할 수 없기 때문에 오픈 소스를 사용하려고 하는 서비스 부서와의 협업 모델을 생각하며 그렸다. 다양한 시나리오를 따라 흘러가는 플로우 차트를 그리며 오픈 소스 거버넌스에 대한 내용을 작성해서 어른 조직장들의 회의를 통과했다.

내가 가장 바탕을 둔 것은 오픈 소스 라이브러리에 대한 '검증'과 서비스 부서와 거버넌스 조직간의 '신뢰'였다. 첫번째 오픈 소스 소프트웨어에 대한 '검증'은 철저히 하려고 했다. 비슷한 종류의 라이브러리를 비교하고 사용성 팩터들을 모두 나열하고 객관적인 검토와 테스트를 통해서 검증할 수 있게 했다. 그리고 승인받은 오픈 소스 라이브러는 버전 통제를 통해서 잘 쓸 수 있는 것과 못쓰는 것, 문제 있는 것을 구분하려고 했다.

두번째, 상호 조직간의 신뢰였다. 거버넌스 자체가 굉장히 딱딱해질 수 밖에 없고, 특히 칼로 자르듯 하는 부분 때문에 감정이 상하거나 신뢰 관계가 손상되지 않게 하려고 했다. 서로가 돕고 지식을 쌓고 신뢰를 증강시키는 부분을 많이 염두하려고 했다. 신뢰 관계가 손상되면 소문이 나게 되고 불신이 전체 조직으로 흘러갈 수 있는 부분을 줄이려 했다. 이 불신에 대한 방법론이 여러가지로 나타나게 하지 않는 것이 최선이라고 생각했다. 


(이미지 출처 : http://opiniontribunal.wordpress.com, 사진만 링크걸음)

초안을 작성하고 나고 공유하면서. 여러 담당자들로부터 들은 얘기는 다들 할 수 없다는 분위기였다. 그리고 코딩과 상관없는 일들을 하는 것에 대해서 많은 부담을 가지고 있었다. '코딩'의 즐거움이 없어서 부담스러웠을지 모르겠다. 하지만, 조직장의 업무 지시로 다들 잘해갔다. 그리고, 관계에 대한 신뢰 부분을 얘기할 때, 여러 개발자들의 설득이 가장 어려웠다. 관계의 중요성을 잘 얘기하려고 했지만, 이 부분은 잘 이해하는 사람은 많지 않았다. 개발자들에게는 관계의 중요성을 얘기하는 것은 가장 어렵다. (협업 잘하는 것과 관계를 잘 이끄는 것은 비슷하지만, 완전 다른 내용이다. 관계를 잘 이끄는 것은 상대에 대한 신뢰와 섬김과 양보가 필요하다. 때로는 적절한 관계를 두고 하는 것도 포함한다. 나중에 일과 관계에 대해서 써봐야겠다는 생각이 든다.)

모든 오픈 소스 라이브러리를 검증할 수 없기 때문에 중요한 것만 검증을 시도했다. 모든 라이브러리를 검증할 필요가 없었다. 중요한 것만, 장애로 검증한 것만 해도 사실은 충분했다.

시스템적으로 다양하게 변화했다. 위키보다는 Cafe 형태로 제공하는 방법으로 말씀드렸고, 그 부분은 잘 진행할 수 있었다. 또한 좀 더 진화해서 서버에 있는 라이브러리를 검증하여 서비스 개발자에게 이메일로 알려주도록 하는 시스템을 추가하였다. 이렇게 하여 안정성을 확보한 솔루션이 만들어졌다.

실제로 업무가 돌아가는 것을 보면서 기분이 좋았고, 사실 초안을 작성한 나도 확신이 없었다. 오픈 소스 라이브러리에 대한 믿음을 가지고 힘을 가지고 능력을 가진 조직장때문에 일이 잘 진행되었다. 다만, 아쉬운 점은 상호간의 협력 대신 점차 그 의미는 시들어지고, 껍데기인 프로세스만 남는다는 사실이 아쉬웠다. 아마도 많은 사람들이 나와 같은 고민을 했을까? 흐훗..


마치며...

오픈 소스 거버넌스에 대해서 간단하게 적은 글이다. 프로세스를 만들기전 어떤 고민을 했는지를 적었다. 거버넌스에 대한 고민에 대해서 누군가가 이런 일을 할 때 좋은 소스가 되지 않을까 해서 작성해본다.
좋은 오픈 소스 거버넌스는 방법론적 접근보다는 검증과 신뢰 관계가 중요하다는 관점에서 시작했고, 좋은 결과를 가질 수 있었던 것 같다.

Posted by '김용환'
,