1. 함수의 프로토타입을 꼼꼼히 분석하라 : 함수의 프로토타입에는 그 함수가 뭘하는 것인지에 대한 정보의 90%가 들어 있다.
  2. const 형식이 어떤 것인지 모두 이해하고 있어라 : 함수 인자, 변수 선언, 멤버 함수 맨 뒤.
  3. static 형식이 어떤 것인지 모두 이해하고 있어라 : 변수 선언, 함수 선언, 멤버 함수
  4. 오브젝트 파일안에 뭐가 들어 있는지 알고 있어야한다. : nm, objdump, readelf, dumpbin.exe, depends.exe 등의 유틸리티가 도움이 된다.
  5. 소스를 코딩하고나면 오브젝트 코드가 어떻게 생기는지 알고 있어야한다.
  6. 스택에 쌓이는 순서를 상상하라
  7. 커널레벨과 사용자레벨의 차이와 그 전환은 어떻게 일어나는지 알고 있어야한다.
  8. 디버깅 툴(브레이크 포인트, 변수 내용 보기, 시스템 콜 트레이싱)의 작동원리를 알고 있어라.
  9. 환경변수가 어떻게 저장되는지 알고 있어라.
  10. fork에서 유지되는 것과 유지되지 않는 것에 대해 알고 있어라.
  11. callback 함수의 개념에 대해 알고 있어라
  12. -fPIC로 주어지는 relocatable object의 원리에 대해 알고 있어라
  13. 호출 스택에 대한 구조를 알고 있어라
  1. Delight 2005.06.21 12:32 신고

    좋은글 많이 보고 가요

  2. doodoo 2006.04.12 02:47 신고

    9번 글은 제가 항상 궁금하던 것인데...어디서 좀 찿을길이 없을까요? 무슨 글자를 넣어서 검색을 해보라는 둥...그런거...

    • 주인 2006.04.12 03:34 신고

      hex dump를 만들어서 argv 가 가리키는 곳부터 1kB 정도를 출력해보세요.

      어디서 찾긴 힘들것 같습니다.

    • 최호진 2006.04.12 11:08 신고

      bss code stack env
      위 단어를 모두 넣어 검색해보세요.

바퀴를 다시 발명하면 안되나?

다시 발명하지 말아야할 이유는 전임자의 노력을 조사하지 않고 무모하게 뛰어드는 것을 막기위해서 이겠지만,
우리는 바퀴에 대해서 곰곰히 생각해볼 몇가지 이유가 있다.

바퀴란 다음과 같은 조건을 만족하는 것이이라.

# 널리 쓰이고 있다.
# 척보면 그 원리가 뻔해서 비밀이 없다. (타이어의 복잡함을 말하는 것이 아니라, 표면이 원이라는 얘기)
# 조금 어렵다 싶은 것도, 상당히 많은 문서를 뒤져서 찾아낼 수 있다.

위와 같은 조건을 만족하지 않으면, 다시 발명해도 좋으리라. 이 글을 쓰는 것도 누군가 비슷한 글을 썼을 것임에도 불구하고, 다시 쓰는 이유를 바퀴 발명에 비유할 수 있을 것이라는 생각을 해보면서, 이 글은 3번에 대한 게으름 때문에 쓰는 것이다.

위와 같은 세가지 조건이 있음에도 불구하고 바퀴를 새로이 발명할 필요가 있다. 왜냐고?
바퀴를 한 번이라도 만들어본 사람과 만들지 않고 학습한 사람에게서의 차이는 명품에 대한 가치를 아느냐 모르느냐의 차이가 있는 것이다. 물론 명품의 가치는 많은 것을 보아온 사람도 알 수 있지만, 만들어서 아는 것과 보기만 해서 아는 가치를 어떻게 비교할 수 있을까. 마치 전문 축구 해설위원인 신문선과 선수 및 감독출신으로서의 차범근 해설위원의 차이를 생각하면 알 수 있지 않을까?

바퀴를 다시 발명하지 말라는 말에 모든 것을 포기하려는 생각일랑 당장 접어치우고, 오늘부터 바퀴가 다시 발명될 때까지 멈추지 말자.
  1. 2005.03.06 02:32 신고

    아직 오픈하기전에 주신 Carmel 님의 코멘트는 지웠습니다.. 쏘리.. :)

http://www.chriswetherell.com/hobbit/default.asp 호빗식 이름 지어주는 사이트
http://www.aspalta.cbc.ca/deaddog_asp/aininfo.asp 인디언식 이름 지어주는 사이트
http://www.emmadavies.net/fairy 요정식 이름 지어주는 사이트
diskmgmt.msc : 디스크 관리자
services.msc : 서비스 관리자
devmgmt.msc : 장치 관리자
fsmgmt.msc : 파일 공유 관리자
lusrmgr.msc : 로컬 사용자 관리자
gpedit.msc : 그룹정책
1. 서문

2. Local Scheduler / System Scheduler

3. Symmetric Job Unit / Asymmetric Job Unit

4. Process / Thread (per client)

5. Pre-spawned / Post-spawn (per connection-request)

6. Reuse / One-time use (job unit life cycle)

7. Configurable / Fixed job

8. Single port listening / Multiple ports listening

9. Level detected triggering / Edge detected triggering

10. Asynchronous / Synchronous Handling




1. 서문



서버를 설계할 때 다음 같은 요소를 가지고 선택하게 된다.



  1. local-scheduler / system-scheduler (non-block socket handler)
  2. symmetric / asymmetric job unit
  3. process / thread (per client)
  4. pre-spawn / post-spawn (per connection request)
  5. configurable / fixed job (job unit modifiablity)
  6. reuse / one-time use (job unit life cycle)
  7. single port listening / multiple ports listening
  8. edge detected triggering / level detected triggering


이들은 대개 서버 설계 초기에 주로 선택하나, 때로는 중간에 그 모델을 바꾸어 설계할 수도 있다. 그러나 어떤 것들은 임기응변식으로 서버 설계 변경이 가능하나, 어떤 변경은 처음부터 완전히 다시 작성해야하는 경우가 생기기도한다. 서버를 설계할 때 내외적인 상황에 대하여 고려해야할 사실관계들을 살펴보고 적절한 선택을 위해 정리해보고자 한다. 위에서 나열한 요소들은 하나의 서버를 설계할 때 부분적으로 선택되어지므로, 어떤 상황에 대한 서버를 설계할 것인지를 충분히 고려하지 않으면, 설계 변경시 상당한 충격이 있을 것이다.


2. Local Scheduler / System Scheduler



Non-block I/O, Thread Pool 개념을 사용할 것인가?

Process, Thread 전담형으로 만들 것인가?



  • 선택의 동기

  1. 흔히 non-block socket을 쓸 것이냐, block socket을 쓸 것이냐로 구분하기 쉬운 것을 job scheduler(작업 스케쥴러) 혹은 task switching 입장에서 구분해보았다. 그 만큼 non-block I/O를 통해 처리하는 서버에서는 작업 스케쥴하는 비용이 크게 고려되어야한다는 것이며, 프로세스나 쓰레드의 스케쥴링에 들어가는 시간보다 클라이언트 요구를 처리하기 위해 들어가는 시간에 집중하도록 설계하는 것을 의미한다.
  2. 시스템 스케쥴러를 사용한다는 것은 여러접속의 요구 처리를 프로세스 혹은 쓰레드 스케쥴링에 넘겨 처리하겠다는 것이다.
  3. 스케쥴러에 들어가는 비용을 아까워하는 경우에 Local Scheduler(로컬 스케쥴러)를 선택하게 된다. 예를 들어 데이터의 양도 많고 동시 접속도 많은 경우를 생각해보자, 동시에 1000개 이상의 접속이 생기고 이것들을 프로세스 1000개로 운영하는 것보다 2 개정도의 프로세스가 500개씩 나누어 처리하면, OS의 스케쥴에 해당하는 비용을 크게 줄일 수 있을 것이다. 여기에서 500개의 접속을 하나의 프로세스에서 효과적으로 처리하기 위하여 로컬 스케쥴러라는 말을 도입하였다.
  4. 로컬 스케쥴러라는 것은 User level thread 수준의 복잡도를 요구하는 것이 아니며, non-block I/O를 처리하거나 Thread-pool을 도입하여 소켓당 State machine을 잘 운용하는 수준의 스케쥴러를 말한다.



  • 이점 및 주의점

  1. Local scheduler는 하나의 프로세스에서 작업 분배를 논리적으로 구분한 것일 뿐, OS가 보기에는 하나의 프로세스에 불과하다. 즉, 간단한 User-level thread라고 생각해도 좋을 정도이다. 따라서, system call을 수반하는 무거운 context switching을 막을 수 있으며, 작업들간의 분배가 상당히 가벼운 것에 그 이점이 있다.
  2. 주의할 것은 non-block 소켓을 다룰때는 특히 대량의 접속에 대한 처리가 있을 때, 프로세스당 열 수 있는 최대 디스크립터 수에 도달할 가능성이 많다. 이 경우 똑같은 일을 하는 프로세스가 listen port를 공유하여 경쟁적으로 클라이언트를 접수하는 pre-forked 방식 서버를 사용하여야한다.
  3. 모든 작업은 하나의 프로세스내에 남기 때문에 쓰레드 프로그래밍과 같은 (함수 재진입 문제 등) 수준의 주의를 요한다.



  • 구현에 따른 고려사항

크게 영향을 받는 요인은 프로세스당 최대 열 수 있는 디스크립터 수와 CPU의 개수이다. 후자에 대해서는 CPU 개수의 두 배정도에서 작업전환 비용을 절감하는 이점을 최대화 시키는 것이 경험적으로 알려져 있다. 즉, non-block I/O를 처리하는 쓰레드 풀안의 쓰레드 개수는 1 CPU machine에서 두 개정도가 적당하며, 그 이상 늘여도 성능향상이 월등히 좋아지지는 않는다는 것이다.


3. Symmetric Job Unit / Asymmetric Job Unit



생성되는 프로세스/쓰레드가 모두 같은 일을 하는가?

생성되는 프로세스/쓰레드 마다 역할이 분배되어 있는가?



  • 선택의 동기

  1. 프로세스 혹은 쓰레드가 다수 만들어 질 때, 이들은 모두 같은 일을 하거나(대칭적 작업단위) 상호 협조(비대칭 작업단위)를 하는 모델로 만들어진다.
  2. 예를 들면, HTTP Proxy 설계에 하나의 접속건에 대하여 하나의 쓰레드가 만들어진다면, 이 쓰레드 하나가 클라이언트를 요구를 파싱하고 접속해야할 서버에 접속하며, 서버의 응답을 다시 릴레이하는 일련의 과정을 전담하도록 설계되거나, 두 개정도의 쓰레드로 나누어 하나는 클라이언트와 접속을 담당하고 다른 하나는 서버쪽 접속을 담당하는 형태로 설계될 수 있다. 그 외에 주기적으로 가비지 콜렉팅을 하는 쓰레드도 만들수 있고, 로그를 분리하기 위한 쓰레드도 만들어 질 수 있다.
  3. 대칭적인 서버는 모든 프로세스 혹은 쓰레드가 동일한 일을 하는 작업 단위로 만들어져 접속된 클라이언트의 요구사항을 전담하여 처리한다.
  4. 하나의 처리가 짧은 응답시간을 갖지 않는 경우 처리를 여러 단계로 나누어 각 단계마다 복잡할 수록 여러 프로세스 혹은 쓰레드로 나누어 처리시킬 수 있다.이는 경험적인 프로세스 수 조정 과정을 통해 병목이 생길 수 있는 단계에 여러 프로세스를 둘 수 있는 우아함을 지원하게 된다.



  • 이점 및 주의점

  1. 작업단위 쪼개어 만들어지므로 설계와 구현에서 고립화가 쉽다. 재사용이 가능하므로 쓰레드나 프로세스 수가 경제적으로 생성되며, 그 라이프 사이클도 상당히 경제적이다.
  2. 작업단위가 추상화되면, 업그레이드나 작업단계 추가등이 상당히 명료하다.
  3. 요청이 여러 작업단위를 뛰어 다니므로 중간에 분실될 우려가 있다.
  4. 단순한 요청사항인 경우 굳이 작업단위를 나누게 되면 오히려 복잡한 설계가 될 수 있다.


4. Process / Thread (per client)



하나의 접속에 대하여 한 프로세스를 만들어 처리할 것인가?

하나의 쓰레드를 만들어 처리할 것인가?


작업개체를 프로세스로 할 것인가?

작업개체를 쓰레드로 할 것인가?



  • 선택의 동기

이 문제는 프로세스를 생성하는데 드는 비용이 많다는 것에 기초한다. 전통적으로 fork를 하는데 들어가는 비용이 크기 때문에, vfork라는 개념도 생기며, 뒤에서 보게될 prefork라는 개념도 생기게 된다. 일이 발생했을 때, 무거운 시스템콜을 될 수 있으면 줄이려고 대신 thread를 택할 수 있다.

  • 쓰레드의 이점과 주의점

  1. 이점은 모든 쓰레드가 메모리를 공유하면서 생기는 클라이언트간 자료공유가 쉬운 것에 있다. 또한 많은 OS에서 쓰레드 생성비용이 프로세스보다 작다.
  2. 문제는 하나의 쓰레드는 완전무결 해야하는데 있다. 즉, 리소스 (메모리, 디스크립터 등)가 절대 새지 않아야하며, 쓰레드 자체가 치명적인 오류를 일으켜 프로세스 전체에 영향을 줘서는 안되는데 있다. 반면, 접속이 해제됨과 동시에 프로세스가 종료되는 경우 리소스는 자동으로 해제되므로 쓰레드 기반보다는 견고하다.

  • 구현에 따른 고려사항

  1. 리눅스의 경우 쓰레드의 생성이나 프로세스의 생성이 그다지 비용차이가 많지 않다. 즉, 리눅스의 쓰레드는 좀 무거운 편이다. 따라서 fork에 들어가는 비용을 고려하는 것만으로 쓰레드를 선택하지는 않는다.
  2. 쓰레드의 경우 User level 쓰레드와 Kernel level 쓰레드가 있다. 이 경우 User level일 때의 고려사항은 자칫 하나의 쓰레드에서 block 상황에 빠지게 되어 프로세스가 멈추게 되는 상황이다.
  3. 쓰레드의 경우 하나의 쓰레드가 차지하는 stack의 크기가 있으므로, 쓰레드 생성시 적절한 스택의 크기를 정하는 문제가 발생한다. 스택의 크기에 따라서 생성되는 쓰레드 최대 수가 달라지기 때문이다.
  4. 쓰레드의 경우 하나의 프로세스가 열 수 있는 최대 프로세스 개수에 제한이 있고 그것에 도달하는 경우는 어쩔 수 없는 한계에 도달한 것이라 생각하고 변경해야하는 경우가 있다.


5. Pre-spawned / Post-spawn (per connection-request)



connection 요구가 있을 때, 새로운 작업개체를 만들고 수신하여 처리결과를 전송할 것인가?

미리 만들어진 작업개체가 connection 요구를 accept하고 수신하여 처리결과를 전송할 것인가?



  • 선택의 동기

Process 생성에 들어가는 비용이 많이 들기 때문에, 사전에 Process를 준비하여 빠른 응답을 줄 수 있도록한다.



  • Pre-spawned의 이점과 주의점

  1. 접속을 전담하는 형태로 작성되며, 대개 전담하는 모델이 이미 접속된 소켓에 대하여 하는 것과는 달리, 접속요구를 accept하는 것부터 전담하게 된다.
  2. 동시에 두개의 port를 listen하는 경우 accept하기전 select를 사용하고, 이 select에 참여하는 작업개체(Process, thread)를 하나로 한정하기 위해 semaphore나 mutex 등을 둔다. 이는 accept 경쟁에 실패한 작업개체들이 한 포트의 accept에 멈춰있어 다른 포트에 accept할 기회가 상실되는 것을 막기 위함이다.


6. Reuse / One-time use (job unit life cycle)



접속을 전담하는 작업개체가 접속이 종료되면 같이 종료되나?

접속을 전담하는 작업개체가 접속이 종료되면 다른 접속을 받기 위해 대기하나?

몇번의 접속을 전담하고나면 종료되나?



  • 선택의 동기

  1. 작업개체의 생성에 들어가는 비용을 줄이기 위해 재사용하도록 한다. 주로 Pre-spawned(Pre-forked) 방식에서 사용된다.



  • reuse 모델에서의 이점과 주의점

  1. 이전 접속의 데이터가 다음 접속에 영향을 주어서는 안된다.
  2. 한 클라이언트의 접속/응답 시간이 작은 경우에는 효과적이나, 그렇지 않은 경우에는 고려하기 어렵다.



7. Configurable / Fixed job



접속을 받아 실제 응답을 주는 것은 고정되어 있나?

접속을 받아 실제 응답을 주는 작업이 바이너리 릴리즈 후에 추가되거나 수정될 수 있는가?



  • 선택의 동기

서비스 모델이 확장성은 고려되지 않는 경우 모든 작업은 컴파일되어 릴리즈 되지만, 버전업이 잦거나 접속이 종료되지 않은 상황으로 hotfix를 해야하는 경우를 고려하면, 선택해야한다.



  • 이점과 주의점

  1. 외부 모듈이 실행되는 형태로 작성되므로, 보안상 허점이 발견될 수 있다.
  2. 안정성이 해결된 바이너리라는 확인작업 없이 hotfix하면, 기존의 서비스도 중지될 수 있다.
  3. 외부 모듈을 통해 인증을 거칠 수 있다.



  • 구현시 주의점

  1. 구현을 inetd와 같은 방식으로 할 경우 accept후 fork/exec를 사용한다.
  2. 구현을 shared object 방식으로 할 경우 외부 object를 dlopen 한다.


8. Single port listening / Multiple ports listening



서비스 포트가 하나인가?

서비스 포트가 하나 이상인가?



  • 선택의 동기

외부에 두 개의 port를 보임으로서 다른 프로토콜 또는 다른 주소를 하나의 서비스안에서 구현한다.



  • 이점과 주의점

  1. 하나의 바이너리만을 배포함으로써 서비스를 간소화시킬 수 있다. 대표적으로 inetd, apache web server
  2. accept 경쟁이 일어날 경우 한쪽 port로 몰려 "port 왕따 현상"이 일어나지 않아야한다.



  • 구현 참고

  1. 서비스 구분은 getsockname을 통해서 local port를 구함으로써 알 수 있다.


9. Level detected triggering / Edge detected triggering



수신 요청 신호를 확인하여 응답할 것인가?

요청 버퍼를 확인하여 응답할 것인가?



  • 선택의 동기

시스템에서 제공하는 전통적인 select, poll 방식의 감지는 동시에 참여하는 descriptor 수가 많아질 경우 scan하는 비용이 많이 들어간다. 따라서, 수신요청이 있을 때 바로 처리하도록한다.



  • 이점과 주의점

  1. 대량의 접속을 처리해야하는 경우 서비스를 해야할 시점을 선택하는 문제를 접속 혹은 수신 통지 서비스를 이용하므로 응답시간을 단축할 수 있다.
  2. 한번의 수신 통지에서 버퍼에 남겨두는 것이 없도록 모두 비워주지 않으면, 버퍼 오버플로가 발생하여 서비스가 정지할 수 있다.
  3. OS에 의존하는 서비스를 이용하므로 이식성을 포기해야한다.



10. Asynchronous / Synchronous Handling



요청한 작업을 Callback함수를 통해 마무리 할 것인가?

요청한 작업이 종료될때까지 기다릴 것인가?
요청한 작업이 종료되었는지 확인하여 처리할 것인가?



  • 선택의 동기

  1. read/write 시스템콜을 사용하는 전송요청은 전송이 마무리 될때까지 대기하여 시간을 소비하게 된다. 이 대기 시간을 의미있게 사용하기 위해, 수신/전송 요청과 실제 수신 데이터 도착 / 송신 완료가 이루어지는 시점을 분리하여 그 사이에 다른 일을 하도록 한다.
  2. 사용자의 수신/전송 요청에 대한 결과를 확인하는 것과 요청에 대한 커널의 응답이 비동기적으로 한다.
  3. read/write 라는 하나의 명령을 사용하지 않고, asynchronous I/O 구현 Library의 request, callback 메커니즘을 사용한다.



  • 이점과 주의점

  1. 전통적인 signal-base async I/O는 signal 이라는 상대적으로 무거운 시스템콜을 통하여 일어나므로 매 처리가 signal handling 상황이라는 것에 주의해야한다.
  2. 대개 라이브러리에 의존하는 서비스이므로 이식성을 포기해야한다.
"나 자신의 한계를 잘 알아야한다"는 말은 간혹 사람을 무기력하거나 고착되게 만든다.

내 인생의 퀀텀 점프는 그런 한계를 갑자기 뛰어 넘어 다른 궤도에 올린다는 말인데,
한계를 아는 것과 그 한계를 넘어야한다는 생각을 하는 사람들에게는
퀀텀 점프라는 말이 멋있는 말처럼 들릴 것이다.

난, 내 자신의 한계를 인정하지 않는 사람이다. 애초부터 한계라는 것은 없었다.
선을 그어 놓고 사는 것은, 인간에게 있어서 어쩌면, 사람과 사람이 어울려 살면서
생긴 자연스러운 생활의 모습에서 나온 생활 패턴이 아닌가 한다.

그런 한계를 긋는 일을 일반화하여 자신의 능력에도 적용하는 것이 아닐까....

내 능력과 내 관심사를 제한하는 것은, 쉽게 어떤 일에 대해 배타적이 되거나
관심 밖의 영역이라 치부하여 대화를 멈추는 것으로 끝나기 십상이다.

한계는 애초부터 없었으며, 퀀텀점프도 따라서 없다.
그저.. 계속 나아지는 것 뿐이다.

세상의 모든 것에 대하여... 계속...
eπi + 1 = 0;

e = 2.71828182...

π = 3.1415926535...

i = root of -1
http://www.mytolkien.pe.kr/ 에서 허락 없이 가져왔습니다.

톰 봄바딜의 노래들

Hey dol! merry dol! ring a dong dillo!
Ring a dong! hop along! fal lal the willow!
Tom Bom, jolly Tom, Tom Bombadillo!


헤이 돌! 메리 돌! 링 어 동 딜로!
링 어 동! 깡총 뛰어! 팔 랄 버드나무!
톰 봄, 유쾌한 톰, 톰 봄바딜로!

Hey! Come merry dol! Derry dol! My darling!
Light goes the weather-wind and the feathered starling.
Down along under Hill, shining in the sunlight,
Waiting on the doorstep for the cold starlight,
There my pretty lady is, River-woman’s daughter,
Slender as the willow-wand, clearer than the water.
Old Tom Bombadil water lilies bringing
Comes hopping home again. Can you hear him singing?
Hey! Come merry dol! Derry dol! And merry-o,
Goldberry, Goldberry, merry yellow berry-o!
Poor old Willow-man, you tuck your roots away!
Tom’s in a hurry now. Evening will follow day.
Tom’s going home again water-lillies bringing.
Hey! Come derry dol! Can you hear me singing?


헤이! 오라, 메리 돌! 데리 돌! 내 귀여운 여인!
날개달린 찌르레기와 바람은 가벼이 날고,
언덕 저 아래, 햇빛이 반짝이는 곳,
차가운 별빛을 기다리며 물가에 서 있는
어여쁜 내 사랑, 강의 여신의 딸,
버드나무보다 날씬하고, 강물보다 맑은 여인.
늙은 톰 봄바딜은 수련을 가지고
깡총깡총 집으로 돌아간다. 그의 노래 들리는가 ?
헤이! 오라, 메리 돌! 데리 돌! 메리-오,
골드베리, 골드베리, 유쾌한 노란색 베리-오,
불쌍한 버드나무영감, 네 뿌리를 감추어라!
톰이 달려간다. 해가 지면 저녁이 오는 법,
톰은 수련을 가지고 집으로 돌아간다.
헤이! 오라, 데리 돌! 내 노래 들리는가 ?

Hop along, my little friends, up the Withywindle!
Tom's going on ahead candles for to kindle.
Down west sinks the Sun: soon you will be groping.
When the night-shadows fall, then the door will open,
Out of the window-panes light will twinkle yellow.
Fear no alder black! Heed no hoary willow!
Fear neither root nor bough! Tom goes on before you.
Hey now! merry dol! We'll be waiting for you!



깡총 뛰어, 꼬마친구들, 위디윈들강을 올라오게!
톰은 촛불을 켜야 하니 먼저 간다네.
서쪽으로 해가 지면 곧 엉금엉금 기어야 하니까.
밤의 그림자가 내려앉으면 문이 열리고
창 밖으로 노란 불빛이 반짝이지.
검은 오리나무도, 백발의 버드나무도 두려워하지 말게!
뿌리도 가지도 두려워말아! 톰이 앞장을 섰으니.
헤이 어서! 메리 돌! 자네들을 기다라겠어.

Hey! Come derry dol! Hop along, my hearties!
Hobbits! Ponies all! We are fond of parties.
Now let the fun begin! Let us sing together!



헤이! 오라 데리 돌! 깡총 뛰어, 다정한 친구들!
호비트! 조랑말! 모두 함께! 우리는 친구를 좋아하지.
자, 즐거운 잔치를 벌이자! 함께 노래부르세!


Now let the song begin! Let us sing together
Of sun, stars, moon and mist, rain and cloudy weather,
Light on the budding leaf, dew on the feather,
Wind on the open hill, bells on the heather,
Reeds by the shady pool, lilies on the water:
Old Tom Bombadil and the River-daughter!



자, 노래부르세! 함께 노래부르세!
해와 별, 달과 안개, 비와 구름.
새싹 위의 햇빛, 깃털 위의 이슬,
광활한 언덕 위의 바람, 야생의 히드꽃,
그늘진 연못가의 갈대, 물 위의 수련을.
늙은 톰 봄바딜과 강물의 딸!



Old Tom Bombadil is a merry fellow,
Bright blue his jacket is, and his boots are yellow.
None has ever caught him yet, for Tom, he is the master:
His songs are stronger songs, and his feet are faster.


늙은 톰 봄바딜은 유쾌한 친구,
자켓은 하늘색, 구두는 노란색.
아무도 그를 붙잡지 못하지, 그는 주인이니까.
그의 노래는 가장 힘찬 노래, 그의 발은 가장 빠른 발.



I had an errand there: gathering water-lilies,
green leaves and lilies white to please my pretty lady,
the last ere the year's end to keep them from the winter,
to flower by her pretty feet tilt the snows are melted.
Each year at summer's end I go to find them for her,
in a wide pool, deep and clear, far down Withywindle;
there they open first in spring and there they linger latest.
By that pool long ago I found the River-daughter,
fair young Goldberry sitting in the rushes.
Sweet was her singing then, and her heart was beating!

And that proved well for you - for now I shall no longer
go down deep again along the forest-water,
not while the year is old. Nor shall I be passing
Old Man Willow's house this side of spring-time,
not till the merry spring, when the River-daughter
dances down the withy-path to bathe in the water.



난 거기 심부름을 갔었지, 내 귀여운 여인을 위해
수련과 푸른 풀잎과 흰 백합을 꺾어 오는 일,
겨울이 오기 전 올해의 마지막 걸음이었지.
눈이 다시녹을 때까지 그녀의 어여쁜 발을 치장할 꽃,
해마다 여름이 끝날 때면 그녀를 위해 꽃을 찾으러 가지
위디윈들 강 저 아래에 있는 넓고 깊고 맑은 연못으로
이른 봄 가장 일찍 꽃이 피고 가장 늦게 꽃이 지는 곳,
그 연못가에서 먼 옛날 강물의 딸을 보았지
골풀 속에 앉아 있던 아름답고 젊은 골드베리!
그녀의 노랫소리는 달콤했고 그녀의 가슴은 뛰고 있었지.

그러면 이해가 잘 되었겠지, 이제 다시는
숲속의 강물을 따라 깊숙히 가지는 않겠네,
이 해가 가기까지는. 또한 봄이 오기까지는.
다시 버드나무영감의 집을 지나지 않으리,
즐거운 봄이 오기까지는. 봄이 와 강물의 딸이
춤추며 강변을 따라내려가 목욕할 때 까지는.


Ho! Tom Bombadil, Tom Bombadillo!
By water, wood and hill, by the reed and willow,
By fire, sun and moon, harken now and hear us!
Come, Tom Bombadil, for our need is near us!


호! 톰 봄바딜, 톰 봄바딜로!
물이나 숲, 언덕, 갈대, 버드나무 옆이나
불이나 해와 달 어디에 있더라도 이제 우리의 소리를 들어 주오!
오라, 톰 봄바딜, 우리는 그대가 필요해요!


(c) copyright 2002 by mytolkien.pe.kr all rights reserved.

  1. 폴로배어 2014.12.23 15:31 신고

    복사해 갑니다.

창조란 "공허와 혼돈에 질서를 부여하는 것"이다.
창조란 "질서와 상식에 대해 변형을 가하여 다른 질서를 만드는 것"이다.
결국 기존 질서를 부분적으로 파괴하는 속성이 있다.

결국 무에서 유를 창조하는 것과, 유에서 다른 유를 창조하는 것의 차이일까..

무에서 유를 창조하는 것은 중간 과정이 없이 마지막 모습을 이룬것일까?
중간존재를 가정하는 순간 무에서 유를 창조한 것이 아니므로 혼돈에 질서를
부여하는 것이나 질서와 상식에 대해 변형을 가하는 것은 유에서 유를 창조하는 것이다.
그러므로 무에서 유라는 것과 유에서 다른 유를 창조하는 것으로 대치될 수없다.


유에서 다른 유를 창조한 다는 것은 중간 존재를 먼저 만들고
중간존재의 재결합을 말하는 발명수준의 것과,
마지막모습에 대한 변형을 이루어, 다른, 하지만 비슷한 질서체계를
만드는 것으로 분리될 수 있을까?

창조가 공허나 혼돈에서 질서로 가는 과정을 말하는 것이라면,
공허가 아닌 혼돈에서 질서에 대한 것은 중간존재의 재결합을 말하는 것이며,
결국, 무에서 마지막 모습으로바로 귀결된 창조보다는
중간 존재를 건너이루어진 모습을 말함이리라..

내가 화학에서 놀란 것은, 원자들이 사실은 다양하게 있는 것이 아니라
양성자와 중성자와 전자의 숫자놀이에 불과하다는 사실이었다.
원자는 그러한 작은 입자를 중간존재로 하는 안정된 질서체계, 즉 마지막모습이라는 것이다.

그런 원자들이 분자를 이루고, 분자들이 모여 유기물과 무기물,
나아가는 호흡이 있는 생명의 근간을 이룬다.
결국, 생명에 대한 것을 단지 물질의 관점에서 보면,
흙으로 만든 것이며, 처음부터 무에서 탄생한 것이 아니게 된다.

내가 보기에 작은 입자들의 조합에 의한 다른 원자를 만드는 것부터
마지막 모습에 대한 변형을 이루어 비슷한 질서체계를 만드는 것으로 보인다.

창조란 재료와 결과에 대한 과정을 말한다기 보다는 "의도"의 존재에 대한 것을 말한다.

결국엔 공허와 혼돈에서 질서가 생겼고, 인간들은 비슷한 창조성으로
질서에 약간의 변형을 가하여, 기존질서에 대해서는 혼돈이라 여겨지지만,
다른 질서를 이루는 것은 극히 현상만을 다루는 문제이며
이들이 창조의 본질문제에 들어가서는 아니될 것이다.

창조란 의도가 있느냐 없느냐의 문제이다.

따라서 의도있게 진화되었으면, 그것도 창조아닐까?


뉴스엔조이의 기사에 대한 독자의 글중에 유시민 복장사건과 관련한 글을읽다가 생각난것을 전개시켜보다가.... 썼다.
전문가라 칭해지는 것 중에 프로그래밍만큼 그 허와 실이 다른 경우가 있을까?

내 이야기를 하고 싶다.
일반적인 이야기는 이 글을 읽고 있을 프로그래머에게는 너무 식상한것일테니
난, 8bit시절부터 컴을 다루던, 우리나라의 80년대 컴키드로 시작을했다.
그 부류의 사람들은 크게 게임을 하던사람들과 할 게 없어서 어셈블리까지
하던 부류로 나뉠 것 같다.

누구는 그렇지 않겠냐마는 나에게 있어서도, 컴에 대한 매력은 게임보다는
내가 작성한 베이식(당시에는 베이직으로 많이 불리었던..)언어를 돌리다보면
척척 결과를 내는 것에 매료되어 하다가하다가 변태(?)적인 성향을 띄던
사람들이 많았을 것이다.

중학교, 고등학교를 그런식으로 지냈으니 컴에 대해서 얼마나 단순했으랴.

그간의 수많은 일들을 제쳐두고, 나이 30이 넘은 지금 고민이 많다.
프로그램이라는 것은, 논리적인 문법과 OS, library에 대한 이해만 완벽하면,
모든게 두렵지 않은 것이 없고, 새로운 것이 없어 보인다. 그것이 네트워크
프로그램이건, System 프로그래밍이건, 베이식으로 된것이건, SQL로 됐든,
지겹다 하리만치 보고 또 봐도, 적정한 수준의 타협만 끝나면, 마치 알건
다 안다는 듯 거만한 생각이 비집고 들어선다.

이런 것일까? 어떤 일을 해도, 자만에 취해사는 것일까? 유독 프로그래머만 그러는 것일까?

이젠 사람들을 관리하는 책임을 요구하고 있고, 그것이 사회적인 요구사항이
돼가는 것 같다. 사람들이 싫다기 보다는 사람다루는 것이 서툴기 때문이다.
전문직 관리인, 중간 관리자로서의 역할은 쓴 모습을 많이 보아온 나에게는
도전과 포기의 두 마음이 공존한다.

결국 남는 것은 컴에 대한 지식과 사람다루는 법일 뿐인데,
사람다루는 법을 힘들이지 않고 배우려는 얍실한 생각이 문제라는 것이다.
이젠, 하기싫어도 해야하는 나이(?)가 자연스레 된 것일까?

좀 늦출 수는 없을까? 잠시 해야할 일이 남아 있는데, 못한 것이 몇가지 남아 있는데.
정말인데,

그것이 무엇이냐는 질문을 한다면, 난 그 사림이 내 가까운 사람이 아니고서는
쉽게 말할 수 없다. 다만, 이해해달라는 말밖에는...
아니 가까운 사람이 물을지라도 난 답할 수 없다. 그것이 말로 정확히
정리돼본적이 없으므로.

프로그래머로 산다는 것은 참으로, 어려운일이다.

10년 넘게 높은 급여를 받을 수도 없으며, 더 높은 급여를 위해서는 몇가지 수반되는
사람관리, 프로젝트관리라는 것이 필수가 되는 것. 즉, 코딩의 질보다는
납기준수에 대한 능력이 더 중요한 것이 현실이다.

현실은 고객으로부터 나오며, 고객과 먼 개발은 사실상 이윤추구와 거리가 먼 것이다.
그것은, 고객이 개발의 질보다는 원하는 기능이 적당한 시간에 나오는 것이므로,
나의 추론은 증명된다고 할 수 있다.

적절한 업무 프로세스에 대한 것을 위해 투쟁하는 것이 퍽이나 지쳤나보다.
업무 프로세스이후에 할 일도 많은데, 그것조차 없는 상황을 불평하는 것도
이젠 싫증이 났다.

혼자할 수 있는 전문직이었으면, 오히려 쉬웠을텐데...
왜 하필 프로그래머였을까?

내가 고민하는 것이 이렇게 단순한 것일까? 결국 밥그릇일뿐...
용기없는 거지의 한켠에 쪼그리고 있는 초라한 모습이라니...

-- 지민이를 보러 내려온, 대전 원내동에서 --
  1. chi hyun 2005.09.15 00:36 신고

    그려...
    다들 한번쯤 해보는 고민이구나.
    너무 초라해 하지 마라. 프로그래머 아닌 사람도 다들 생각해 보는 나인가 보다.
    오랫만에 네 글 보니 반갑다.

  2. 아쿠아 2007.05.02 10:56 신고

    읽을거리 많네요...............

    다 읽고 갈께요.

    언제 다 읽지......허더더더더;;;;

+ Recent posts