잊지 않겠습니다.

* 사내 강의용으로 사용한 자료를 Blog에 공유합니다. Spring을 이용한 Web 개발에 대한 전반적인 내용에 대해서 다루고 있습니다.



WebApplication은 HTTP Protocol로 동작하는 네트워크 프로그래밍의 일종입니다. 

이 정의가 조금은 의문스러워보이실지 모르겠지만, 저희는 지금 네트워크 프로그래밍을 하고 있는것입니다. 다만 이 네트워크를 처리해주는 것이 Servlet Container가 됩니다. 네트워크 프로그래밍은 매우 어려운 작업이지만, 지금 우리가 할 수 있는 가장 큰 이유는 Servlet Container가 이 일을 처리해주고 있기 때문입니다. 이는 매우 큰 의미를 갖습니다. 더이상 개발자들은 이 어려운 네트워크 문제를 다루지 않고, 처리하고자 하는 BL에만 집중할 수 있다는 점이, 오늘날의 성공적인 web application 환경을 만들어주게 되었습니다.  네트워크 처리 부분만을 의미하는 것으로 web application server 라는 표현을 사용하기도 합니다. 

위에서 보시는것처럼 web application server는 web으로 동작하는 application만을 의미하게 됩니다. 또한 Java EE(java enterprise edition)의 명세 및 구현된 web application 기술에 대한 구현체가 servlet container라고 할 수 있습니다. 이에 따라 servlet container는 다음과 같은 정의를 내릴 수 있습니다. 

servlet container = web application server + Java EE web application 기술 구현체

가장 널리, 그리고 무료로 사용될 수 있는 servlet container는 다음과 같습니다. 

tomcat : 가장 오랫동안 servlet 기술 명세에 대한 reference 구현체였으며, 가장 잘 알려진 servlet container입니다. 
jetty : 실험적 시도를 가장 과감하게 도입하는 것으로 유명합니다. 또한 속도가 가장 빠르고 가벼운 servlet container로 유명합니다.
grizzly : 현 servlet 기술 명세에 대한 reference인 glassfish의 servlet framework입니다. 제한적 무료라서 그런지, tomcat에 비해서 대중성이 조금 떨어지고 있다는 느낌이 들긴 합니다. 


HTTP Protocol

HTTP는 다른 Protocol과는 조금 다른 특징을 가지게 됩니다. 일반적으로 network protocol은 size나 해석의 문제에 의하여 압축되고, 특정 문자로 해석되도록 데이터를 만드는 것이 일반적입니다. 주소번지 1번지부터 12번지까지는 특정 어떤값을 이용하는 식으로요. 그렇지만 HTTP Protocol은 String을 그대로 사용하고 있습니다.  만약에 daum 사이트에 갔을 때, http는 어떤 통신을 하는지 한번 간단하게 알아보도록 하겠습니다. 

먼저 request는 다음과 같이 발생됩니다.

GET / HTTP/1.1
Host: www.naver.com:8000
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
DNT: 1
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: UTF-8,*;q=0.5
Cookie: JSESSIONID=1q5bdgf2p3b22nz1n133l3qd

모든 HTTP Protocol은 기본적으로 CR + LF에 의하여 한개의 항목이 끝나는 것을 지정합니다. 그리고 데이터는 {Name}: {Value} 형태로 구성이 됩니다. 이 형태는 매우 중요합니다. 공백과 :의 위치까지 정확하게 잡혀있는 Protocol format이 됩니다. 만약에 우리가 HTTP Protocol을 직접 만들어서 보내주고 싶다면 이와 같은 형태로 데이터를 구성해서 보내주면 됩니다. 

지금까지 보신 위 코드가 HTTP Header 가 됩니다.  개발시에 자주 이야기가 나오던 HTTP Header에 특정 데이터를 넣어서 보낸다던지, 특정 데이터를 얻어오는 일들이 모두 위의 Text로 구성이 됩니다. 

다음은 response입니다. 

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 07 May 2013 01:24:54 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
P3P: CP="CAO DSP CURa ADMa TAIa PSAa OUR LAW STP PHY ONL UNI PUR FIN COM NAV INT DEM STA PRE"
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip

404


보시면 request와 비슷한 내용이 return되는 것을 알수 있는데, 아래 부분에 약간 다른 내용이 있습니다. 이 부분이 Body입니다. Body는 Header다음에 CR + LF + CR + LF 후에 나오는 text 영역이 됩니다. 우리가 만드는 HTML 부분이 되는 것이 일반적입니다. 

HTTP Protocol의 request type

request의 첫줄에 나오는 GET / HTTP/1.1에 주목할 필요가 있습니다. 이 부분은 지금까지 사용되는 부분과 조금 다릅니다. 이 부분을 http method라고 불리우는 영역입니다. HTTP method에 따라서 url의 parameter를 server에서 달리 해석하게 됩니다. 

1. GET
우리가 가장 자주 보는 형태입니다. parameter는 ?로 시작되고, =로 key와 value가 설정이 됩니다. 그리고 다른 key가 있는 경우에는 &로 연결이 됩니다. 따라서 형태는 다음과 같이 구성이 될 수 있습니다. 


가장 주로 사용되는 형태입니다. HTTP Protocol의 정의상으로는 GET는 정보의 조회시에 사용하는 형태입니다. <a> tag나 browser의 url로 접근하는 경우에는 모두 GET으로 동작하게 됩니다. 

2. POST
역시 자주보이는 형태입니다. parameter의 구성방법역시 GET과 동일합니다. 다만 parameter를 보내는 방법에 큰 차이를 가지고 있습니다. GET에서 parameter를 이용해서 구성을 했지만, POST는 body에 GET에서 보내줬던 paramter를 넣어서 보내주게 됩니다. 이 방법은 사용자에게 parameter를 노출시키지 않는 장점을 가지고 있고, GET에서 불가능한 대용량 대이터를 보내는 것이 가능합니다. 그리고 file upload 시에도 POST 방식을 사용하게 됩니다. HTTP protocol에서는 기본적으로 update의 의미를 가지고 있습니다. 

위 GET/POST는 가장 많이 사용되고 있는 HTTP method입니다. 그리고 Browser에서 기본적으로 지원을 하고 있습니다. 그렇지만, 아래 나오는 method들은 구형 browser에서는 지원되지 않고 있습니다. 그리고 GET/POST 이외에는 parameter를 보내지 못합니다. 이 부분은 RFC 문서에 정의된 내용으로 HTTP 1.1 이상의 버젼에서는 추후 지원할 수도 있습니다.  

3. DELETE
조금은 생소한 method입니다. HTTP protocol에서는 이름 그대로 delete의 의미를 가지고 있습니다. 

4. PUT
Create/Insert의 의미를 갖는 method 입니다. 

5. TRACE
보낸 request를 그대로 다시 보내주길 원하는 method입니다. echo server나 server의 상태가 원활한지를 알아보는 방법으로 사용됩니다.  이 method는 매우 심각한 문제를 가지고 있습니다. XST(Cross-Site Tracing)이라는 악의적 공격방법을 이용해서 사용자의 request에 들어있는 인증정보를 빼돌릴때 사용이 됩니다. 그래서 TRACE를 지원하는 web server들은 모두 심각한 오류를 가지는 것으로 보고되며, 모든 web server는 TRACE method를 무효할 것을 권장하고 있습니다. 

6. OPTIONS
Web Server에서 HTTP Method중 어떤 것들을 지원하는지 알아보는데 사용됩니다. 

7. CONNECT
Proxy에서 사용됩니다. Http TLS(Transport Layer Security) Tunnelling을 요청할 때 사용됩니다. CONNECT로 보내지는 method는 그 서버를 통해서 다른 서버에 접속하게 되는 것을 요청하게 됩니다. 

8. HEAD
GET과 동일한 정보를 return합니다. 다만 차이를 갖는 것이 GET은 Body에 데이터를 넣어서 보내지지만, HEAD는 Header에 Message-Body에 body를 모두 넣어서 보내게 됩니다. HEAD method는 browser에서 cache를 사용할 때 주로 이용합니다. 


위 method를 이용한 결과는 HTTP result라는 숫자로 표시가 되는데요. 이는 response의 첫줄에 나오는 숫자가 Return에 대한 결과입니다. 우리가 자주 보는 HTTP result의 결과가 바로 이것입니다. 

1. 2xx - Success
# 200 : OK
# 201 : Created - POST나 PUT에 의해서 새로운 Resource가 생성되었음을 나타내는 result code입니다.
# 202 : Accepted - async http request가 들어왔을 때, 그 request가 수용되었음을 나타냅니다. 
# 203 : Partial Information - return되는 정보는 cached된 것이거나, 내부 정보임을 의미합니다. 
# 204 : No Response - Response가 정상적으로 처리되었지만, Output의 내용이 없음을 의미합니다. 주로 Body가 비어있는 경우에 204를 return 합니다.

2. 3xx - Redirect
# 301 : Moved - 요청된 URL의 페이지가 다른 곳으로 이동되었음을 나타냅니다.
# 302 : Found - 요청된 URL의 페이지에서 다른 곳으로 이동하는 것을 원하는 것을 나타냅니다. 301과 비슷하지만, 302의 경우에는 Form을 POST로 넘겼을 때, 그 결과에 대한 Accept의 의미로 사용됩니다.
# 303 : Method - Found와 같은 의미로 사용되지만, Found는 URL로 이동됨을 나타냅니다. Method는 Body에 있는 Document를 이용해서 표시하는 것을 의미하게 됩니다.
# 304 : Not modified - 변경된 상황이 없기 때문에 Cache에 있는 내용을 이용해서 표시하라는 것을 의미합니다.

3. 4xx - Client Error
# 400 : Bad Request - HTTP Protocol에 어긋난 request가 입력되었습니다.
# 401 : Unauthorized - 인증되지 않은 HTTP Request가 들어왔습니다.
# 402 : Payment Required - Http Head에 있는 정보를 변경해서 다시 보내주는 것을 요청할때 사용됩니다.
# 403 : Forbidden - 인증되었지만, 권한이 없음을 나타냅니다.
# 404 : Not Found - Resource가 없는 URL에 요청되었음을 나타냅니다. 우리가 Spring으로 web을 개발할때, 처음에 자주 볼 수 있는 에러입니다. Controller 뿐 아니라 View File이 없는 경우에도 404 Not Found가 표시됨을 유의해주시길 바랍니다. 

4. 5xx - Server Error
# 500 : Internal Error - 서버 내부의 에러입니다. java나 .net에서 exception이 발생했을 때, 이것을 처리하지 않을때 나오는 에러입니다.
# 501 : Not Implemented - 아직 구현되지 않은 URL을 호출했습니다. 이는 404와는 다른 에러입니다. 404의 경우에는 아애 없는 URL이 호출된 상황이고, 501의 경우에는 구현되지 않았지만, URL resource는 존재할 때 사용됩니다.
# 502 : Timeout - RFC에 의해서 정의된 에러는 아닙니다. 그렇지만 몇몇 WebServer들은 구현되어있는 에러코드로, Server의 BL로직이 너무 오래 걸릴때, 에러로 return 해줍니다. 


웹의 구조적 아키텍쳐

apache httpd를 시작한 Roy Fielding은 web은 주요 제약점에 의해서 확장성이 좌우되는것을 알게 되고, 그에 대한 구조적 스타일을 다음과 같이 정의했습니다. 

1. Client / Server
웹은 client/server 기반 system으로 client/server 규약의 핵심은 관심의 분리입니다. 웹의 일괄된 인터페이스를 따른다는 가정하에, Client와 Server는 각자의 언어 및 기술을 이용해서 독립적으로 구현되고 배포가 가능하게 됩니다. 

2. Uniform interface
웹을 구성하는 Client/Server/Network 간의 interface는 일관성에 기반하고 있습니다. 이러한 구조가 붕괴가 되는 경우, 현 웹 커뮤니케이션체계는 붕괴가 되어버립니다. 
이 인터페이스는 다음과 같은 정의들을 보일 수 있습니다. 

# 리소스 식별 : URI로 구분될 수 있는 resource는 unique하기 때문에, 고유 식별자로 사용될 수 있습니다.
# 표현을 통한 Resource 처리 : HTML, JSON과 같은 web resource는 표현 방법이 정해져있지 않습니다. HTML을 그냥 text로 보여줘도 되고, web browser에서 보이듯이 rendering해서 표시를 해도 괜찮다는 뜻입니다. 이는 Document-View 구조와 같이 Resource에 대한 처리는 Client에게 맡긴다는 정의로도 볼 수 있습니다.
# 자기 서술적 메세지 : HTTP protocol의 header는 자신에 대한 서술적 메세지를 포함합니다. 그리고, 요청에 대한 처리는 전적으로 요청에 대한 응답자에서 결정하게 됩니다. 
# Application 상태 엔진으로서의 Hyper-media : resource의 상태표현은 resource의 link를 포함합니다. 따라서 모든 resource는 실타래처럼 연결되기 때문에 사용자들은 정보와 application을 직접적인 방식으로 훝어보는 것이 가능하게 됩니다. 이는 HTML의 표준적인 특징중 하나입니다.

3. Layered System
우리가 구성하는 MVC와 같은 Layered System이 아닌 Browser-proxy-gateway-switch-web server 와같은 Layer가 구성되는 network 기반의 중간계층을 사용할 수 있는 구조적 특징을 갖습니다. network 기반의 중간계층의 경우에는 보안의 강화 또는 응답 캐싱, 부하를 분산하는 용도로 주로 사용됩니다. 

4. Cache
cache는 웹구조의 중요한 제약조건중 하나입니다. 캐시는 웹자체의 전체적인 비용을 줄일 수 있는 기술적 요건이며 server, network, client 모두에 위치가 가능하게 됩니다. 

5. Stateless
웹의 가장 큰 특징중 하나입니다. web server가 client의 상태를 직접 관리할 필요가 전혀 없다는 것입니다. 따라서 client는 server와 상호작용하는 관련 상황정보를 직접 관리를 해야지 됩니다. 이는 web server가 client와의 복잡한 연결을 위해 필요한 상태 관리를 전혀 하지 않는다는 점입니다. 이를 다른 말로 FF(fire and forget)이라고도 합니다. 이는 장점도 단점도 아닙니다. 비용상의 trade-off라고도 할 수 있습니다. 

6. Code-on-demand
웹은 주문형 코드를 많이 사용합니다. 이 제약조건은 script나 plugin과 같은 실행가능한 program을 일시적으로 program에 전송하여 client가 실행할 수 있도록 합니다. 그렇지만 이는 client와 server간의 강한 결합을 가지고 오게 되는데. 이는 web에 대한 확장성을 막아버릴 수 있기때문에 최대한 지양해야지 되는 구조라고 할 수 있습니다.

이러한 구조적 스타일에 기반한 웹의 확장은 2000년 Roy Fielding에 의해서 'Representational State Transfer'라고 이름을 붙여 발표하게 되었습니다. 그리고 이 논문의 제목은 지금 REST라는 용어로 더욱더 많이 사용되고 있습니다. 

REST는 어느날 갑자기 나온것이 아니라, 웹의 구조적인 특징을 이용하고, 그에 대한 안정화로서 나온 기술입니다. 어찌보면 기술이라기보다는 'Style'이라고 할 수 있는 방법입니다. REST에 충실한 구조를 RESTful 하다는 용어로 사용하고 있고, 이는 다음과 같은 특징을 가지고 있습니다. 

1. URI 식별자 설계
# '/'는 계층 관계를 나타내는데 사용됩니다.
# URI의 마지막 문자로 '/'는 사용하지 않습니다.
# '-'는 URI의 가독성을 높이는데 사용합니다.
# '_'은 URI에서 사용하지 않습니다.
# URI는 소문자로 구성을 합니다.
# 파일 확장자는 URI에 포함하지 않습니다. 파일 확장자는 URI를 통해 얻어질 수 있는 media-type에 따라 결정이 됩니다.

2. URI 디자인
# Document/Object의 이름은 단수를 이용한다 (ex: http://www.daum.net/leagures/teams/players/report)
# Collection이 표시되는 경우, 복수를 이용한다 (ex: http://www.daum.net/leagures/teams/players)
# 제어가 발생되는 URI는 동사나 동사구를 이용한다 (ex : http://www.daum.net/students/morgan/register)
# CRUD 기능을 나타내는 것은 URI에 사용하지 않는다. 
- 이는 REST API를 구성할 때 사용되는 규칙입니다. 
- 위에서 살펴본 GET/POST/DELETE/PUT을 이용한 URI를 구성해서 CRUD 기능을 만들어주는 것이 권장됩니다.

3. input parameter
# parameter의 경우에는 URI query라는 이름으로 사용됩니다. 
# URI query의 경우에는 검색기준으로 사용되는 것이 일반적입니다. 이는 HTTP GET method의 사용방법과 연관있습니다.

4. http method
# GET method는 리소스의 상태표현을 얻는데 사용됩니다.
# HEAD method는 응답에 대한 header만을 얻어올 때 사용합니다.
# PUT method는 리소스를 생성하거나 갱신하는데 사용합니다.
# POST method는 리소스를 생성하거나 갱신하는데 사용합니다. POST와 PUT는 일반적으로 같은 목적으로 사용됩니다. 다만 사람들끼리의 암시적인 약속으로 Create시에는 PUT을, Update에서는 POST를 사용하는 것이 일반적입니다.
# Control이 발생되는 URI는 반드시 POST에 의해서 실행됩니다.
# DELETE는 Resource를 삭제할 때 사용됩니다.
# OPTIONS는 resource의 사용 가능한 action method가 무엇인지를 알기위해서 구성됩니다.


Summary 

이번에는 HTTP에 대한 기본적인 이론에 대해서 알아봤습니다. HTTP는 우리가 만드는 모든 web application의 핵심기술입니다. 다만 기술의 구현은 servlet container 또는 web server에서 담당하지만, 그에 대한 동작을 알아보는 것은 개발시 디버그등에 매우 유리하게 만들 수 있습니다. 그리고 URI의 디자인은 URI 자체의 문서화 뿐 아니라 Google에서의 검색의 가장 큰 기준이 됩니다. 여기서 나온 내용들은 꼭 알아두시길 바랍니다.


저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K
TAG http, Rest, servlet

Framework는 분명한 제어의 역전기능이 적용되어 있어야지 된다.

Application code는 Framework가 짜놓은 틀에서 수동적으로 동작할 수 있어야지 된다.


라이브러리를 사용하는 Application 코드는 Application의 흐름을 직접 제어한다.

단지 동작하는 도중에 필요한 기능이 있을 때, 능동적으로 Library를 사용한다. 


반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해서 사용된다. 

보통 프레임워크 위에 개발된 클래스를 등록해두고, 프레임워크가 흐름을 주도하는 중에 개발자가 만든 애플리케이션 코드를 사용하도록 만드는 방식이다. 

저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K

NoSQL Solution 검토중, Cassandra 설치 부분에 대해서 번역 및 참고 사항 추가


  • 설정환경 : JAVA 1.6 이상

설치 Progress

  • Download Cassandra application
  • conf/cassandra.yaml 파일 수정
    항목설명Example
    data_file_directoriesDB 파일이 저장될 위치 지정C:\cassandra\data
    commitlog_directoryDB Commit이 발생될 때, 메세지가 저장되는 위치 지정C:\cassandra\commitLogs
    saved_caches_directoryCache의 저장위치C:\cassandra\cache
    storage_portCluster 구성시에 저장 메체들간의 통신 Portdefault:7000
    rpc_portRemote Client Port. Client의 접속 정보를 저장하는 Portdefault:9160
    initial_tokenCluster를 구성시, 첫번째노드로 사용되는 경우에만 0를 설정한다. 다른 경우에는 모두 빈값으로 표시default:(공백)
  • conf/log4j.properties 파일 수정
    항목설명Example
    log4j.appender.R.Filelog4j의 파일 저장 위치/var/log/cassandra/system.log
  • cassandra-env.sh 수정
    항목설명Example
    MAX_HEAP_SIZEcassandra에서 사용할 heap의 사이즈 설정default : 4G, 절대로 작은 값으로 production에 보내지 말것!
    HEAP_NEWSIZEcassandra에서 새로운 heap 요청이 발생하였을 때에, 생성될 sizedefault : 800M, 절대로 작은 값으로 production에 보내지 말것!

위 값들이 너무 작은 경우, OutOfMemory exception이 발생할 가능성이 매우 높음


시작 progress

bin/cassandra.bat -f -- foreground로 실행, CTRL+C로 중지 가능
bin/cassandra.bat    -- background로 실행, Process kill로만 중지 가능

저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K

Redmine을 Backup하기 위해서는 file 폴더와 mysql db backup이 필요하다. 

일별 backup 을 관리하기 위해서 간단한 powershell script를 작성했다.


#utf8 포멧으로 windows command 변경

& CHCP 65001


$backupRoot = 'H:\redmine_backup\';

$mysqldump = 'C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqldump.exe'

$fileFolder = 'G:\Redmine\Files\*.*';


$date = (Get-Date).ToString("yyyyMMdd");

$desFolder = $backupRoot + $date;

$attachedFiles = $desFolder + '\files';

$dbBackup = $desFolder + '\redmine.sql';


mkdir $desFolder;

mkdir $attachedFiles;

cp $fileFolder $attachedFiles;

& $mysqldump -u root -pqwer12#$ redmine --default-character=utf8 | Out-File $dbBackup -Encoding UTF8;

# 기본 설정. MySQL/bin 의 위치와 Backup 위치, Redmine의 Attach된 파일 위치를 지정

$backupRoot = 'G:\TracBackup\';

$mysqldump = 'C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqldump.exe'

$fileFolder = 'G:\Redmine\Files\*.*';


#Daily Backup을 날짜별로 하기 위해서 Get-Date 함수 이용

$date = (Get-Date).ToString("yyyyMMdd");

$desFolder = $backupRoot + $date;

$attachedFiles = $desFolder + '\files';

$dbBackup = $desFolder + '\redmine.sql';


#Folder 생성 및 Attach된 파일 copy

mkdir $desFolder;

mkdir $attachedFiles;

cp $fileFolder $attachedFiles;


#MySQL dump 명령어 실행

& $mysqldump -u root -p[MySQL Password] redmine --default-character=utf8 | Out-File $dbBackup -Encoding UTF8;



작성된 script를 Windows Scheduler에 등록하고, 매일 실행하도록 설정하면 완료.

저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K

SVN 에서 post-command hook을 활성화시키면된다. 


POSIX 환경에서는 post-commit hook에서 wget를 이용해서 구성하면 되지만, windows에서는 wget이 없기 때문에 다음과 같은 vbs script를 작성한다. 



private const REDMINE_SERVICE_KEY = "<서비스키>" 

 Call HTTPGet("http://<redmine url>/sys/fetch_changesets?key=" & REDMINE_SERVICE_KEY)

 

 Private Function HTTPGet(sUrl)

   Dim oHTTP

   set oHTTP = CreateObject("Microsoft.XMLHTTP")

   oHTTP.open "GET", sUrl, False

   oHTTP.send

   HTTPGet = oHTTP.responseText

End Function



다음 svn hook에서 post-commit.tmpl 파일을 카피해서 post-commit.bat파일로 변경시키고 안의 내용을 다음과 같은 내용으로 변경한다.


cscript "<작성된 vbs 파일의 full 경로>"


작성이 모두 되면 이제 SVN에서 commit가 이루어진 이후에, redmine에서 다시 changeset을 읽어들여 구성하도록 변경된다. 



저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K

사용하던 Trac에서 redmine으로 이전하기로 결정하였다. redmine으로 이전하기로 한 이유는 다음과 같다.


1. Gantt chart 및 calandar를 이용한 프로젝트 관리가 용이하다.

2. Forum 기능이 기본으로 제공된다.

3. SVN 서버와 동일 서버에 설치될 필요가 없다. 

4. issue의 start date와 end date가 제공되며, issue work log를 작성 가능하다. 




redmine 설치 (for windows)


1. ruby instance download

http://www.rubyinstaller.org/ 에서 제공하는 windows용 installer를 이용

2. mysql download & install

3. ruby gem update

: gem update --system

: gem update

4. ruby devkit download & install

http://www.rubyinstaller.org/ 에서 제공. native build시에 필요한 파일들이 포함되어 있다.

: ruby directory에 dev folder 생성, 압축을 풀어서 넣어준다. 

5. windows path 등록

: mysql/bin, ruby/bin, dev/bin, dev/mingw/bin 를 windows path에 등록한다. 

6. ImageDrive 설치

: http://www.redmine.org/projects/redmine/wiki/HowTo_install_rmagick_gem_on_Windows

: set CPATH=C:\Program Files\ImageMagick-6.7.7-Q16\include

: set LIBRARY_PATH=C:\Program Files\ImageMagick-6.7.7-Q16\lib

7. install bundler

: gem install bundler

8. mysql DB 준비

  > create database redmine character set utf8;

  > create user 'redmine'@'localhost' identified by 'my_password';

  > grant all privileges on redmine.* to 'redmine'@'localhost';

9. redmine source download

10. redmine bundler gem install

: 개발환경이나 테스트 환경이 아니고, postgresql을 사용하고 있지 않기 때문에 이 부분을 제외하고 설치를 진행한다.

: bundle install --without development test postgresql

11. session token 생성

: rake generate_secret_token

12. mysql db schema 생성

: set RAILS_ENV=production

: rake db:migrate

13. default data load

: rake redmine:load_default_data --q

14. run redmine

: ruby script/rails server webrick -e production


* msvcrt-ruby18.dll 를 발견할 수 없다는 에러가 발생하는 경우, gem uninstall json을 시킨 이후에, bundle install 작업을 다시 한다.

14번과정까지 모두 마쳐지면, 이제 redmine을 사용할 수 있는 준비가 모두 된 상황이다. 






trac migration 작업


redmine은 기본적으로 trac에서 migrate되서 기본 project를 생성하는 기능을 제공한다. 명령어는 다음과 같다.

rake redmine:migrate_from_trac RAILS_ENV="production"


그런데, 이 migration 기능은 다음과 같은 문제점을 가지고 있다.

1. 한글명으로 된 첨부 파일이 ticket 또는 wiki에 있는 경우 migration 실패

2. trac에서 sqlite3를 사용한 경우, 날짜 값이 정상적으로 표시되지 않음

3. ticket과 issue의 데이터 차이로 인해, closed된 issue들이 모두 start_date와 end_date가 정상적으로 표시되지 않음

4. trac에서 사용된 head format이 redmine과 다르기 때문에 wiki 페이지가 정상적으로 표시되지 않음


이 4가지 문제점은 1, 2번은 migration을 수행하기전에, 3, 4번은 migration을 수행한 후 mysql의 데이터를 변경해서 수정 가능하다. (물론 3, 4번을 해결하기 위해서 migration부분 redmine 코드를 수정해서 migration을 수행해도 된다.)


1번 문제점은 노가다로 해결을 봤다.; 한글로 된 첨부파일 및 Image를 모두 제거하고, 영문으로 이름을 변경후에 다시 첨부하는 노가다 작업을 해서 해결을 했다. ruby에서 설정된 cp949 format의 한글을 정상적으로 decoding을 못하는 느낌인데... 일단 노가다로 되는 문제였어서;; 노가다로 해결;


2번은 unix에서의 timestamp을 mysql timestamp로 변경시킬 때 나오는 에러다.. trac.db 파일을 sqlite browser로 열어 다음과 같은 query를 실행한다.

UPDATE ticket SET time = time / 1000000 where time > 9999999999;

UPDATE ticket SET changetime = changetime / 1000000 where changetime > 9999999999;

UPDATE ticket_change SET time = time / 1000000 where time > 9999999999;

UPDATE milestone SET due = due / 1000000 where due > 9999999999;

UPDATE milestone SET completed = completed / 1000000 where completed > 9999999999;

UPDATE version SET time = time / 1000000 where time > 9999999999;

UPDATE auth_cookie SET time = time / 1000000 where time > 9999999999;

UPDATE session SET last_visit = last_visit / 1000000 where last_visit > 9999999999;

UPDATE session_attribute SET value = value / 1000000 where value > 9999999999 and name = 'query_time';

UPDATE attachment SET time = time / 1000000 where time > 9999999999;

UPDATE wiki SET time = time / 1000000 where time > 9999999999;

UPDATE revision SET time = time / 1000000 where time > 9999999999;


1, 2번 문제를 해결하면 migration 작업은 정상적으로 수행된다. migration이 수행된 후에 3,4 번 문제를 해결하도록 한다.


3번 문제점은 trac의 ticket은 start_date와 end_date 및 done_ratio를 지원하지 않기 때문에 issue의 값들이 null로 나오기 때문에 나오는 현상이다. 종료된 ticket의 생성날짜를 start_date로, 최종 변경날짜를 end_date로 변경해서 캘린더와 간트차트를 정상적으로 표시되게한다. 다음 query를 mysql에서 실행한다.

update issues set due_date = updated_on, start_date = created_on, done_ratio = 100 where status_id = 5;


4번 문제점은 migration된 trac wiki와 head format과, image 표시 방법, Table 표시방법이 다르기 때문에 나오는 문제상황이다.이 부분은 간단한 console 프로그램을 작성해서 해결했다. NHibernate를 기반으로 작성되어 있다. app.config에 redmine db 접속 정보만 넣어주고 실행시키면 된다.

RedmineWikiConvert.zip



trac에서 redmine으로 migration을 모두 마쳤다. T-T

약간 한가지 문제가 있는 것이, Grantt chart의 image export시에 한글이 모두 깨지는 문제가 발생하는데. 이에 대한 해결책은 gantt.rb 파일의 411 line에 다음과 같은 코드를 추가시켜주면 된다.


원 코드(굵은 색이 추가된 코드)

gc = Magick::Draw.new

gc.font = "G:\\Redmine\\font\\NanumGothic.ttf" (사용할 font의 ttf 파일 path를 넣어준다.)


저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K

Chapter 1. MongoDB 소개

  • 기본적인 RDBMS의 데이터인 row라는 개념을 document로 변경
  • 문서의 키가 미리 정의되거나 고정적인 형태의 스키마가 존재하지 않는다. 
  • 다양한 확장 기능 : 복제, 레플리카, auto sharded 지원
  • javascript 문법에 기초한 명령어 Set 지원
  • json format의 데이터 지원


Chapter 2. 시작하기

  • 데이터의 기본단위는 문서이다. (document, json format)
  • "_"로 시작되는 키는 예약어로 사용하는 것이 좋다. (암묵적)
  • Collection
    • system 으로 시작되는 collection은 시스템에서 사용하는 예약어이기 때문에 사용할 수 없다.
  • 기본 database
    • admin : 인증관념에서의 'root' database. 모든 데이터베이스 목록을 조회하거나 서버를 중지하는 등 서버 전역에 걸쳐 실행하는 명령어들이 실행되는 영역
    • local : 특정 서버에서만 저장되는 collection에 사용된다.
  • Command
    • mongod : mongoDB 실행 command
    • mongo : mongoDB Shell
    • 기본 명령어 :  insert, find, findOne, update, remove
  • 데이터형
    • null : 존재하지 않는 필드 및 null값을 표현
    • boolean : true / false
    • number : mongoDB에서는 모든 숫자들은 64bit 부동 소수점으로 표현이 된다. 
    • datetime : new Date() 를 이용.
    • 정규표현식형
    • javascript code
    • undifined : javascript의 undifined를 문서내에서 사용할 수 있다.
    • array 
  • _id
    • mongoDB에 저장되는 모든 문서들은 "_id"를 가지고 있다.
    • Timestamp | MachineId | PID | Increment 값을 이용해서 12byte의 데이터를 만들어준다.
    • document가 insert 될 때, 자동으로 추가된다.


저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K
TAG mongodb
.NET으로 Visual Studio를 이용한 개발환경을 꾸미게 될 때, 

Visual Studio의 Development WebServer는 32bit에서 동작하게 되며, IIS는 64bit에서 동작하기 때문에 2개의 client의 설치가 필요하다.
먼저 기존의 Oracle의 설정을 모두 날리는 작업을 하자. (Oracle의 uninstall은 매우 지저분 하다. -0-)

1. http://www.oracle.com/technetwork/topics/dotnet/downloads/index.html 에서 32bit, 64bit Instant Client를 모두 다운 받는다. (64bit는 Client XCopy version으로.)
2. 32bit -> 64bit 순으로 모두 설치를 해주고, 설치할 때에는 Oracle home name을 각각 다르게 해준다. oracle_x86, orcle_x64 등으로 알아보기 쉬운 이름이 좋다.
3. TNS_ADMIN 환경 설정 변수를 설정해주고,  tnsnames.ora 파일을 만들어서 TNS 설정을 넣어준다. 
4. 개발시에는 32bit를 이용하고, 배포할 때는 64bit를 이용해야지 된다. (local copy option을 반드시 설정해줘야지 된다.)



 
저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K
이 글은 컴퓨터 프로그래밍을 이미 자기 삶의 중요한 일부분으로 받아들였지만 잠시 주춤하고 있는 사람들과 프로그래머의 길 앞에서 그렇게 될 것인가 말 것인가 고민하고 있는 사람들에게 '삶의 과정으로서의 프로그래밍'이라는 관점을 갖고 작성했다. 이를 통해 프로그래밍하는 인간의 모습을 돌아보고 프로그래머로서의 인간 에너지를 충전시키는 시간을 제공하고 싶다.  


이만용 (리눅스코리아 CTO ) 2001/04/13  


필자는 이 글을 통해 지난 3-4 년간 프로그래머가 되고 싶어했던 사람들, 이미 직업으로서 프로그래밍을 하고 있다. 현재보다 더 나은 프로그래머가 되길 원했던 사람들이 필자에게 보낸 메일에 대한 답장 속에서 했던 이야기. 그리고 하고는 싶었지만 답장 메일로 적기에는 너무 길어 적지 못했던 마음속의 말들을 꺼내어 정리하는 시간을 갖게 되었다. 종종 일상의 지겨운 반복 속에서 좌표를 잃지 않기 위해 컴퓨터 앞을 떠나 편안하게 사색에 잠길 수 있기를 바라며 이야기를 시작한다.  

원래 창조적인 지적 유희이며 그러해야 한다  
필자에게 왜 프로그래밍을 하고 있냐고 묻는다면, 주저없이 '재미(fun)'라고 답할 것이다. 한 가지 덧붙이자면, 만약 프로그래밍보다 더 재미있는 일이 있다고 생각한다면, 역시 주저함 없이 프로그래밍 대신 그 일에 몰두할 것이다. 재미없는 일을 억지로 하면서 보내기에는 인생은 너무 짧지 않은가. 여러분이 이미 생계의 족쇄 속에 또는 사회적 위치 속에 결박당해 탈출할 수 없는 경우가 아니라면, 그리고 충분히 새로운 선택을 하여 재시도할 수 있는 사람이라면, 다시 한 번 진정으로 자신이 프로그래밍을 즐기고 있는지 생각해 보는 시간을 갖기 바란다. 꼭 프로그래밍을 해야 하는 절대절명의 이유란 없다. 앞으로 전개될 글을 읽기 전에 마음의 고리를 풀고 편안한 마음으로 자신의 사고가 흐르는 대로 방치하기 바란다.  

꼭 프로그래밍만이 재미있다고 말할 수는 없지 않겠는가. 당연히 재미라고 하는 것이 인간의 다른 모든 행위로부터 프로그래밍을 구별해 주는 유일한 요소일 수는 없다. 이 세상에는 프로그래밍 이외에도 이미 사람이 재미를 느낄 수 있도록 해 주는 일이 헤아릴 수 없을 정도로 많듯이 말이다. 예전에도 그리고 지금도 수억의 인구가 회화, 악기 연주, 운동 등에서 즐거움을 느끼고 있다. 이 활동들은 새로울 것도 없지만, 여전히 재미있는 활동이다. 프로그래밍도 시간이 지남에 따라 훨씬 더 대중화하고 똑 같은 취급을 받을 것이다. 하지만 프로그래밍이 똑같이 재미있는 수많은 일 중 그냥 하나라고 말하기에는 너무 극단적이다. 어떤 점에서 프로그래밍이 주는 재미가 다른 재미와 같고 또한 다른 것일까.  

프로그래밍은 이미 오랜 시간 동안 인간의 역사 속에서 사람들에게 재미를 제공했던 기존 활동과는 도구적 관점에서 다르다. 여기서 컴퓨터라고 하는 20 세기의 놀라운 발명품을 이야기하지 않을 수 없을 것이다. 책, 기관차, 전화와 같은 출판 기술, 증기 기관, 통신 기술이 인간 세상을 변화시킨 것처럼 컴퓨터가 현재의 인간 생활을 변화시켰다는 점을 부인할 사람은 없다.  

인간은 그 동안 자신이 발견하거나 발명한 것을 즐기며, 도구를 통해 자신을 다시 변화시켜 왔다. 프로그래밍은 컴퓨터라고 하는 도구를 통해 그 안에서 인간의 상상력과 논리적 사고력을 실현해 내는 고급 유희다. 그러나 바로 이전 문장에서 표현했듯이, 인간이 지적 노력을 쏟아 지적인 재미를 만들어 내려고 하는 지적 유희라는 점에서는 그 이전의 모든 창조적 지적 유희와 하나도 다르지 않다. 여기서 필자는 다르다는 점보다 같다는 점을 강조하고 싶다.  

채 다 배우기도 전에 쏟아져 나오는 프로그래밍 언어, 선택해 보지 못한 메뉴가 아직도 많은데 버전업돼 나오는 통합 개발 환경에 치여 살다 보니, 프로그래머인 우리 자신이 인간이 최근 만든 가장 놀라운 발명품을 사용해 가장 재미있는 창조적 지적 활동을 하고 있다는 사실을 너무도 쉽게 잊어버리는 모습을 목격할 수 있다. 그리고 현실 속에서는 이러저러한 언어, 도구에 지배받으며 지쳐 있는 불쌍한 자신을 쉽게 발견한다.  

하지만 그 어떤 컴퓨터를 사용하든, 그 어떤 프로그래밍 언어나 도구를 사용하든 우리 프로그래머들이 본질적으로는 참 재미있는 일을 하고 있다는 사실을 망각하지 말아야 한다고 말하고 싶다. 그것도 매우 지적인 재미 말이다.  

그러한 자기 만족감이 없이 버틸 수 있는 프로그래머가 있을까. 프로그래밍 언어책을 보다 며칠씩 이해되지 않던 부분이 갑자기 슬슬 풀려 나갈 때, 작지만 자기가 예상한 대로 모든 일이 척척 진행돼 나갈 때, 하루 종일 찾지 못했던 버그를 커피 마시다 갑자기 찾아냈을 때 느끼는 자신에 대한 대견스러움, 만족감을 느껴보지 않고 어떻게 프로그래머라고 말할 수 있을까. 이런 즐거움은 이성 친구, 애인, 가장 가까운 친구에게도 어떤 말로도 전달할 수 없는 매우 개인적인 차원인 것이다. 때로는 자신의 소스 코드와 프로그램을 이해하는 지구 반대편의 프로그래머와 더 진한 동질감을 느끼기도 하는 것 또한 프로그래머다.  

자신에 대해 대견스러워하는 마음, 무엇보다 자신이 설계한 대로 컴퓨터가 작동하는 것을 보는 즐거움, 컴퓨터를 통해 자기만의 세계가 창조되는 즐거움을 느끼지 못한다면 앞으로 하는 모든 이야기는 별 의미가 없다. 취미로든 직업으로든 왜 프로그래밍을 선택했는지 그리고 왜 수많은 책과 읽을거리와 투쟁하고 있는지 자기 확신을 갖자. 아무리 생각해 봐도 프로그래밍은(유일하지는 않아도) 꽤 매력적인 고급 활동이다. 재미있는 일을 재미있게 하지 못한다면 그것은 큰 문제가 아닐 수 없다.  


프로그래밍의 본래 의미를 찾는다  
대학생 친구들을 위한 언어 교재를 만들면서 자주 등장하는 외래어 표현을 정리하고 있었다. 그런데 바로 프로그램(program)이라는 말 그 자체가 우리에게 시사하는 바가 많다는 사실을 발견했을 때 마치 보물을 발견한 양 즐거워 한 적이 있다.  

'program'이라는 단어는 'pro'와 'gram'의 합성어다. 여기서 'pro' 는 '어떤 일을 하기 전에...' 라는 'before' 의 의미를 갖고 있으며 'gram'은 '무엇인가를 쓰다' 즉 'write'의 의미를 갖고 있다. 따라서 program은 쓰거나 만드는 행위라기보다 '쓰기 전에 하는 일' 즉 계획적인 사고 행위를 가리킨다.  

현실적으로 우리가 우리 자신을 설계자나 기획자라고 생각할 수 있는 여유는 거의 없는 것 같다. 우리가 매일 확인할 수 있는 자신의 모습은 특정 언어나 특정 제품, 특정 프로젝트의 노예로 전락해 있는 초라한 모습이지 않은가. 프로그래밍은 어느 새 밤을 세며 코딩하는 중노동과 동일시돼 버렸다. 그래서인지 요즘 미국이나 한국 젊은이를 대상으로 한 설문조사를 보면 그래픽 디자이너가 되고 싶다는 답변이 프로그래머가 되고 싶다는 답변보다 월등히 많다고 한다. 이미 프로그래머란 컴퓨터 분야 중 가장 선호하는 직업이 아닌 것이다.  

프로그래밍 작업의 특성이 무엇을 이뤄내기 전에 먼저 머리 속에서 설계하는 정신적 유희라는 본질적인 의미를 자꾸만 잊게 하는 그 무엇을 갖고 있다고도 볼 수 있다. 프로그래머를 계속해서 괴롭힐 동전의 양면적 특성이 존재하는 것이다. 계획과 함께 실천이 있어야만 완성되는 것이 프로그래밍의 중요한 특성이다.  

설계한다는 점에서 프로그래머는 건축가와 유사한 점이 많다. 아무리 작은 프로그램을 만들지라도 프로그래머의 머리 속에는 이미 어느 정도의 프로그램 진행 과정에 대한 설계가 먼저 이뤄진다. 그러나 건축가가 실제 건물을 만들지는 않는다. 건물을 직접 만드는 일은 건축 노동자들의 몫이다. 이렇게 건축이라는 영역에서 건물을 설계하는 일과 짓는 일은 완벽히 분리돼 있다. 그러나 프로그래머는 결국 자기 손으로 건물까지 지어야 한다는 점에서 크게 다르다. 상상만 하고 코드를 입력해 실행 프로그램을 만들어내지 않으면 아무 것도 하지 않은 것과 같다. 그런 점에서 프로그래머는 어떻게 보면 화가나 조각가에 더 가깝다. 자기 내면에 비춰진 이미지에서 그치는 것이 아니라 캔버스나 대리석에 실체를 구현해야 하며, 생각하는 주체와 그것을 실현해 내는 주체가 같다.  

프로그래머인 우리가 결국 C, C++, 자바 등 특정 언어를 배워 우리의 아이디어를 실행 가능한 소프트웨어로 만들어내야 한다는 사실은 분명하다. 그러나 그렇다고 해서 프로그래밍이 언어를 잘 구사하는 것만으로 끝날 일은 아니다. 그림만 잘 그린다고 해서 화가라고 말하지 않는 것과 같다.  

시작은 언어 대신 사고력 부터  
그렇다 해도 여전히 훌륭한 프로그래머가 되기 위한 시작은 언어가 아니라 사고 능력이라는 점을 지겹도록 강조하고 싶다. 프로그래밍 언어책을 붙들고 공부한다고 해서 자연스럽게 프로그래밍을 잘 하게 되는 경우는 없다. 만약 그랬다면 이 글을 쓰고 있어야 할 이유조차 없었을 것이다. 언어 공부가 자연스럽게 자신을 프로그래머로 만들어 주지는 않는다. 이 사실은 독자 여러분이나 필자나 말하지 않아도 알고 있다.  

또한 그렇다고 해서 무조건 명상에 잠긴다거나 순서도 그리는 일을 다 마치고 나서 언어를 배우고 프로그래밍하는 것도 아니다. 원래 생각하는 과정과 도구를 사용해 실현하는 과정이 떨어져 있는 것도 아니다. 인간은 자유로운 상태에서 생각하며 도구를 사용하고, 도구를 사용하며 생각한다.  

인간의 놀라운 점 중 하나는 도구를 사용함으로써 자신의 사고 능력을 발전시키고 그 발전된 사고 능력으로 도구를 개선하거나 새로운 도구를 만들어 가는 무한 사이클을 이어간다는 것이다. 여러 가지 관점에서 설명할 수 있겠지만 필자가 강조하고자 하는 면은 다음과 같다. 생각하지 않으면서 언어를 사용하고 코딩하는 것은 계속 제자리를 맴도는 것과 같다. 생각없는 코딩은 생각하는 사람의 사고 능력에 아무런 영향도 미치지 않는다. 아니, 오히려 악영향을 미치기도 한다. 생각없는 반복적 행동은 오히려 생각을 굳게 만들어 반복적 행동을 또 다시 만들어 낼 가능성이 높다. 극단적으로 말해서 생각없이 코딩하느니 너무 지겨워서 다시 생각을 하고 싶을 정도로 빈둥대거나 잠을 푹 자두는 것이 현명한 일이다(필자는 실제로 그렇게 하고 있다).  

인간의 다른 지적 노동과 마찬가지로 현명한 반복만이 현명함을 낳는다. 학문이라는 것이 마치 강을 거슬러 올라가는 것과 같다는 옛말이 있는데, 사실 이보다 더 끔찍하다고 생각한다. 아무 생각없는 반복은 또 다른 생각없는 반복만을 낳을 뿐이며, 현명하게 반복할 수 있다는 사실을 잊게 만든다. 자연스럽게 어떻게 프로그래밍을 배워나가야 하는지 얘기를 이어나가고자 한다.  


프로그래밍, 어떻게 배워나가야 하나  
'닭이 먼저냐 달걀이 먼저냐' 하는 전통적인 질문이 여기서도 그대로 적용된다. 똑똑해지려면 똑똑하게 배워야 한다. 현명해지려면 현명하게 배워야 한다.  

어떻게 똑똑하게 배울 수 있는가  
반대로 설명하는 것이 좋겠다. 프로그래밍은 매우 지적인 유희라고 앞서 몇 번이고 반복한 바 있다. 현재 대부분의 프로그래머 지망생이 학습하는 방법은 크게 다르지 않다. 학습이 매우 단순 반복적이다. 단순 반복에 의해 지적인 성장이 이뤄진다고 생각하는가. 게다가 학습 과정이 지겹기 때문에 유희적인 측면도 이미 상실한 지 오래다. 무엇보다도 몇 번의 반복 속에 자기 자신을 지치게 만들면 이미 게임은 끝난 것이다(물론 꾹 참고 꾸준히 하면 언젠가 길이 보일 것이라고 얘기할 수도 있다. 그러나 이렇게 말해 버리면 역시 이 글의 의미가 완전히 사라진다).  

똑같은 책, 똑같은 도구를 갖고 배우는데 서로 다른 결과물이 나온다면, 조금만 논리적으로 생각해 봐도 차이를 결정짓는 것은 책이나 도구가 아니라 다른 곳에 있다는 결론을 내리게 된다.  

여기서 프로그래밍 학습에 있어 가장 중요한 부분이라고 말할 수 있는 언어 선택 및 학습 과정에 대하여 짚고 넘어가겠다. 먼저 거의 대부분 첫 번째 언어를 잘못 선택함으로써 프로그래밍의 본격적인 재미를 느끼기도 전에 탈락한다. C/C++/자바는 원래부터 만만한 언어가 아니다. 현실적으로 많이 사용하고 있는 이 언어를 많은 사람들이 배우기 어렵다고 말하는데 그 대답은 당연하다. 이 전문언어는 매우 다양한 일을 해낼 수 있는 다목적 언어이며 전문 프로그래머의 경험 속에서 진화해 온 언어이기 때문에 어렵다. 그냥 열렬한 컴퓨터 사용자였다가 갑자기 자기 손으로 프로그램을 만들고 싶다고 해서 제일 먼저 덤빈 언어가 C, C++, 자바와 같은 전문 언어라면 여러분은 열 명 중 여덞, 아홉은 탈락할 것이다.  

필자 나이의 다른 프로그래머와 마찬가지로 필자의 첫 번째 언어는 베이직이었다. 필자는 아직도 이 언어에 대한 향수를 갖고 있을 정도로 좋아한다. 이제 생각해 보니 행 번호 개념과 GOTO 문이 유치하게 느껴질 정도로 까마득하지만, 사용자에서 프로그래머가 되기 위한 첫 번째 단계에서는 매우 유용한 중간 단계라고 생각한다. 베이직은 필자에게 인간의 논리가 아니라 컴퓨터의 논리 입장(물론 이것도 창조한 사람이 만들어낸 것이지만)에 서서 자연스럽게 프로그래밍하는 것을 가르쳐 주었다. 지금은 전혀 사용하지 않지만 매우 중요한 언어임에 틀림없다.  


단순 조급증에서 벗어나야 한다  
프로그래머가 되고 싶어하는 수많은 사람을 처음부터 확실하게 걸러내 준 악습 중 하나는 프로그래머가 되려면 마치 C, C++, 자바 중 하나로 꼭 시작해야 한다는 강박 관념이다. 사람들의 책꽂이에는 최소 2~3 권의 C/C++/자바 책이 꽂혀 있다. 모두 1/3도 보지 않은 채 방치되고 있을 것이다. 바이블에 해당하는 몇 개의 책을 구입했다가 포기하고 결국에는 '며칠 내에 완성하기', '그냥 따라하기'라는 유혹적인 제목의 책을 마지막에 구입한다. 하지만 '21 일 완성하기'를 21일 안에 끝내는 사람은 거의 보지 못했다. 원래 어려운 것을 쉽게 설명하는 일은 더 어렵다.  

현실에서 가장 널리 사용하고 있는 매우 현실적인 언어가 C, C++, 자바이기 때문에 처음에 언어를 배울 때부터 이 언어로 시작하면 뭔가 큰 이득이 될 것이라고 생각하는 것이 바로 앞서 표현한 단순 조급증이다. 물론 뭔가에 빨리 도달하고 싶겠지만 생각처럼 되지 않는다. 오히려 꽃도 피워보지 못하고 초반전에서 프로그래머의 세계로부터 탈락하는 지름길을 선택하게 된다.  

꿋꿋하게 버텨 살아남은 한두 명도 결국에는 잘못된 믿음의 피해자가 된다. 그들은 어렵게 어렵게 배운 C, C++, 자바로부터 벗어나려고 하지 않는다. 마치 이 세상에 그 세 가지 언어만 있는 것처럼 살아가는데, 사실 살아남기는 했어도 어처구니없게도 언어라는 도구의 노예가 되어 버리고 만다. 이들의 프로그래머적 성장은 이미 끝나버렸다.  

상처받은 사람들을 위한 언어, 파이썬  
물론 사회적으로 준비가 잘 되어 있는 것은 아니다. 서점에 가봐도 C와 C 유사 언어 외에 다른 언어에 대한 훌륭한 책이 많지도 않다. 여러 가지 언어를 잘 구사하는 훌륭한 프로그래머도 많지 않고 강사는 거의 없다고 봐도 무방하다. 현재 훌륭한 정보의 대부분은 인터넷에 뿔뿔이 흩어져 있고 대부분 영어로 작성돼 있는 것이 현실이다.  

이런 상황 속에서도 지금 막 프로그래머가 되고 싶어하는 사람들을 위한 첫 번째 언어로서, 그리고 기존 언어를 모두 맛보고, 패배감을 가진 사람들이 자신을 재정비하고 다시 프로그래밍의 즐거움 속으로 빠져들기 위한 재충전용 언어로 '파이썬'이라는 언어를 권하고 있다.  

아직 첫 번째 교육 언어로 채택하기에는 훌륭한 서적과 과정이 나와 있지 않은 상황이어서 필자가 처음 시작했던 베이직보다는 어려울 것이다. 그러나 다른 언어에 의해 상처받은 사람들을 치유하는 치료용 언어로서는 상당한 효과를 볼 수 있다. 이 언어를 통해 언어가 중요한 것이 아니라 인간의 사고력을 풍부하게 발휘하는 것이 중요하다는 사실을 배울 수 있다.  

여러분이 오히려 컴퓨터 언어를 단계적으로 여러 가지 배워감에 따라 자신이 진정 원했던 결과를 더 빠르게 그리고 더 견고하게 세워 나갈 수 있다는 사실을 느끼길 바란다. 언어는 결국 교체 가능한 도구라는 사실을 알게 되고, 여러분의 필요에 따라 새롭게 배우고 구사할 수 있다는 자세를 갖추는 것이 중요하다. 또한 2~3 가지 언어를 구사할 수 있어야 한 가지 언어만 알았을 때보다 훨씬 더 심도깊게 언어를 사용할 수 있다는 사실도 깨닫게 될 것이다.  


다양한 오픈소스의 세계  
컴퓨터 언어를 배우는 플랫폼도 중요하다. 필자로 하여금 C, C++, 자바 이외에도 이 세상에는 수많은 언어가 있으며 수많은 새로운 아이디어가 있다는 사실을 일깨워 준 것이 바로 리눅스와 오픈소스 세계다. 오픈소스는 필자에게 프로그래머로서의 새로운 의지를 수혈해 준 주역이다. 여기서 파이썬을 포함해 LISP, 펄, Ada 등등 많은 언어를 접할 수 있었으며, 여러 번의 외도(?)를 통해 오히려 이미 알고 있던 C 언어를 훨씬 더 잘 이해하고 어디에 어떻게 적절하게 사용해야 할 지 알게 되었다. 무엇보다 각 언어마다 나름의 이유가 있으며 그 창조자의 생각을 어느 정도 이해할 수 있다는 즐거움도 만끽할 수 있었다. 다양한 욕구를 가지고 있는 독자라면 리눅스에서 다양한 오픈 소스 언어를 만나 보기 바란다. 그리고 여러분이 눈길을 주기를 기다리는 어마어마한 분량의 소스 코드가 널려 있다. 또한 멋진 것은 매우 초보적인 소스 코드부터 매우 전문적인 소스 코드까지 선택의 폭이 넓다는 것이다.  

한편, 윈도우 플랫폼에서는 좋으나 싫으나 마이크로소프트의 제품 정책에 따를 수밖에 없으며(그나마 예외는 자바 정도) 따라서 제품의 노예가 되어버리기 쉽다. 예를 들어 현재 프로그래머 사이에 논란이 되고 있는 C# 이라는 언어는 새롭게 출현해야 할 정당한 논리적 이유없이 자바와의 전쟁 속에서 나온 사생아라는 지적이 나오고 있다. 직업적 프로그래머라면 새로운 언어와 규칙을 배워야 하는 수고를 마다해서는 안되겠지만, 프로그래머가 되어 볼까 생각하는 사람들에게는 짜증나는 현실이다.  

조금이나마 다행스러운 것은 오픈소스 진영이 매우 성숙해 훌륭한 소프트웨어의 대부분이 윈도우와 매킨토시 등 리눅스/유닉스가 아닌 플랫폼에서도 동작한다는 사실이다. 여러 플랫폼에서 동작하는 멀티 플랫폼 언어나 도구를 사용하는 것도 현명한 선택 중 하나다.  

웹 프로그래밍 언어에만 집착하지 말자  
마지막으로 언어 선택에 있어 웹 프로그래밍과 관련한 PHP, ASP, JSP에 대한 의견을 개진하고자 한다. 결과를 즉시 확인할 수 있으며, 현재 유행하는 개발 영역의 언어이기 때문에 많은 사람들이 쉽게 시작하고 있지만, 이 언어들은 모두 실용 언어로서 인간에게 프로그래밍하는 더 좋은 방법을 알려주지는 못한다. 따라서 전문 프로그래머가 되려면 이 언어에만 집착해선 안된다. 또한 프로그래밍 본연의 지적 유희를 즐기려는 취미 프로그래머도 역시 이 언어에만 집착해선 안된다. 실전의 전문 프로그래머는 이들의 한계를 분명히 인식하면서 사용한다. 실용 언어와 함께 일반 언어도 동시에 익혀 나감으로써 프로그래밍 사고력과 실용성을 모두 성취할 수 있기를 바란다.  


직업적 프로그래머가 되고 나면  
프로그래밍이란 생계와 결부되는 매우 실용적인 영역임에도 불구하고 의도적으로 이 이야기를 지금까지 피해 왔다. 직업으로 프로그래밍을 하고 있는 사람은 이 글을 읽으며 무슨 지적 유희냐고 화를 내고 있을 지 모른다. 실전에 들어가면 프로그래머의 생활이란 다음과 크게 다르지 않다.  

* 자바 프로그래머로 입사했는데(사실 이 말 자체가 우습다. 프로그래밍 언어 중 자바도 구사할 수 있는 프로그래머라고 표현해야 한다) 실제 프로젝트는 별로 사용해 본 적 없는 C++로 해야 한다고 팀장이 전달한다. 자기가 잘 모르는 언어로 프로그래밍을 해야 한다는 부담감 때문에 매일 짜증내면서 어쩔 수 없이 새롭게 책을 구입해 쫓기듯 학습한다.  

* 쉬엄쉬엄 컴퓨터 앞에 앉아 이런 생각 저런 생각을 하면서 코드만 작성하고 만들어내기만 하면 되는 줄 알았는데, 거의 대부분의 시간을 보고서와 설명서를 쓰는 데 허비하고 있다. 과연 내가 프로그래밍을 하고 있는지 문서 작성을 하고 있는지 한탄스러울 때가 많다.  

* 열심히 만들었더니 주문한 고객의 마음이 또 바뀌어 모든 부분을 일일이 다 고쳐야 하는 일이 다반사다. 창조적이라기 보다는 코딩 막노동(?)이라는 느낌이 들면서 자신이 한심하게 느껴지기 시작한다.  

* 거의 대부분의 시간을 버그 잡느라고 머리털 빠지고 있다. 재미없는 디버거와 함께 하는 시간이 코드 짜는 시간보다 월등히 많다.  

이런 현실적인 문제들을 하나씩 짚어 가기 전에 필자는 독자 여러분에게 이 세상에 재미를 느끼게 해 주는 수많은 일들이 있는데 프로그래밍을 자기 직업으로 삼은 이유가 무엇이냐고 우선 반문하고 싶다. 마음속으로 자기만의 답을 생각해 보고 앞서 나열한 네 가지 문제를 하나씩 다뤄보자.  


새로운 언어를 적극 받아들이자  
번 문제를 살펴보자. 회사나 팀장의 요구가 부당하다고 생각할 지 모르지만, 자신이 모르는 다른 언어로 프로그래밍해야 한다는 요구가 무조건적으로 틀린 것은 아니다. 사실 여러분이 직업적 프로그래머로서 직장 상사나 팀장에게 '나는 이 언어밖에 못합니다'라고 말하는 것은 프로그래머로서의 자신의 진짜 가치를 고백하는 것이나 다름없다. 굳이 사회적으로 통용되는 표현을 쓰자면, 한 가지 언어만을 전문으로 구사할 수 있다고 말하는 사람은 그 언어만 다룰 수 있는 기능사일 뿐이다. 기술자라면, 아니 진짜로 프로그래머라면 새로운 언어를 배워야 한다는 것이 짜증나는 일이라고 단언해서는 안된다. 새로운 언어를 배워 나가는 것은 전문 프로그래머의 일상 업무이다.  

물론 지금 당장은 답답할 지 모른다. 그러나 필자의 논지에 수긍한다면 어떤 언어든 자기가 구사할 줄 아는 언어의 전부가 아니라 그 중 하나일 뿐이어야 한다. 팀장의 요구가 없다 하더라도 사실 유행에 따라 어쩔 수 없이 또 다시 끌려가야 하는 경우도 있지 않은가. 원래부터 피할 수 없는 일이므로 적극적으로 받아들이자.  

문서화는 결코 어려운 일이 아니다  
번 문제를 살펴보겠다. 필자도 보고서를 쓰거나 설명서를 쓰는 작업은 태생적으로 싫어한다. 그러나 보고서나 설명서를 쓰는 작업 자체가 프로그래머의 몫이 아니거나 또는 무가치한 일로 보는 입장에는 동의할 수 없다. 물론 형식화한 보고서, 설명서를 쓰는 것은 매우 지겹고 화나는 일이다.  

보고서와 설명서를 쓰는데 많은 시간이 걸리는 이유는 두 가지를 들 수 있다. 원래 문서화 작업이라고 하는 것이 생각보다 시간이 많이 걸리는 작업이다. 우리의 머리 속에 있는 것을 글로 표현한다는 것이 쉽지 않다는 사실은 어렸을 때부터 독후감 쓰는 일이 쉽지 않다는 경험으로부터 잘 알고 있을 것이다. 글로 표현한다는 것은 자유롭게 흘러가는 생각을 그대로 반영하는 것이 아니라 한 번 더 숙고해 체계화하는 과정이기 때문이다(필자 또한 지금 이 원고 쓰는 일을 흔쾌히 승낙해 놓고서는 얼마나 후회하는지 모른다).  

그러나 무엇보다도 자신이 글을 쓰는 일에 익숙하지 않다고 스스로를 묶어 버림으로써 문서 작업을 싫어하고 집중할 수 없게 되는 수도 있다. 자기 최면을 통해 집중하지 않음으로써 여러분은 자기가 싫어하는 일에 더 많은 시간을 할애할 수밖에 없고 그 만큼 여러분이 원하는 작업에 필요한 시간을 허비하고 있다.  
리눅스나 오픈소스라고 해서 마냥 코딩만 하고 문서화는 전혀 안한다고 생각하면 오산이다. 최소한의 README, 잘 만들어진 문서가 없는 오픈소스 소프트웨어는 초보 프로그래머의 작품일 뿐이다. 이미 수준 높은 품질의 아파치, 삼바, 리눅스 커널을 보면 상당히 친절한, 하지만 작성한 사람 입장에서는 많은 노력을 들인 문서들이 포함돼 있다는 사실을 알게 될 것이다.  

문서화 또한 현명한 대처가 필요하다. 막무가내로 불필요한 분량의 문서를 요구하는 팀조직이 있다면 매우 고루한 조직임에 분명할 것이다. 이러한 조직에 대해 말할 수 있는 해결책은 없다. 그 조직은 여러분이 선택한 것이다. 너무 불합리한 경우가 아니라면, 문서화 작업을 소프트웨어 디자인의 일부로 여기는 능동적인 자세가 필요하다.  
코딩을 할 때 소스 코드에 주석(comment)을 넣지 않는 것은 전문 프로그래머로서의 자질이 없음을 단적으로 보여 주는 것이므로 주의하자. 직업적 프로그래머라면 어떤 일이 있어도 소스 코드는 주석으로 시작해서 주석으로 끝나야 한다.  

문서화란 어떻게 보면 그렇게 어려운 것도 아니며 프로그래밍의 필수 과정이기도 하다. 기본적으로 소스 코드의 주석, README, INSTALL, 그리고 TODO(앞으로 할 일), 각 버전간의 변경 사항을 적는 Changes 문서는 모든 문서화의 기초가 된다. 아직 직업 프로그래머로 취업하지 않는 예비 프로그래머는 지금부터라도 이를 습관화하기 바란다.  
많은 사람들이 오해하고 있는 것을 하나 지적하고자 한다. 대부분 프로그래밍을 코딩에 쏟은 시간만 갖고 평가하려는 경향이 있다. 그러나 앞서 'program'의 어원을 알아보면서 확인한 것처럼, 프로그래밍에서 가장 중요한 것은 계획이다. 계획하고 기획한 것을 좀 더 구체적인 방법으로 설계하고 언어를 통해 구현하고 중간 과정을 기술하는 모든 행위가 프로그래밍이다.  


'간략한' 프로그램을 위해 노력하자  
번 문제로 넘어가겠다. 일단 계획이 서면 거침없이 코드를 작성하고 고치지 않을 것 같지만 몇 명의 천재적인 프로그래머를 제외하고(실제로 그런 사람이 있는지 궁금하다. 자기가 수없이 반복하면서 얻은 경험에 의지해 거침없이 하는 것은 아닐까?) 거의 모든 프로그래머는 그런 식으로 프로그래밍하지 않으며 할 수도 없다. 열심히 프로그래밍했다고 생각했는데 일 년이 지나 소스 코드 개수와 줄 수를 세 보고나면 자괴감에 빠질지도 모른다.. 실제로 우리는 끝없이 고치고 고치고 또 고친다. 그러면서 소프트웨어가 견고해 지는 것이다.  

그리고 현실 세계에서 고객의 요구는 첫 번째로 중요하다. 그들의 요구가 변화하는 것은 당연하다. 훌륭한 프로그래머는 고객이 처음부터 정확한 요구 사항을 제시하도록 유도하고 변화의 폭이 제어할 수 있는 범위 안에 들 수 있도록 잘 안내한다.  
소프트웨어의 기능을 잘 구분하고 반복적인 패턴을 함수/라이브러리/모듈화하지 못하는 초보 프로그래머는 똑같은 소스 코드를 여기 저기 복사해서 쓰게 되는데, 이 때는 소프트웨어를 고치는 일이 곤역스러울 수밖에 없다.  

전문 프로그래머라면 반복적인 패턴을 훨씬 더 많이 찾아내고 압축하는 기술을 가꿔 나가야 한다. 다시 한 번 말하지만 반복적인 경험에서는 얻을 것이 별로 없다. 그 수많은 경험 중에서 문제 해결을 위해 고민한 시간만이 소중한 경험이다.  
고객의 변덕에 따라 짜증이 날 정도로 많이 고쳐야 한다면, 그것은 오히려 여러분에게 더 많은 경험과 사고가 필요하다는 증거이다. 같은 일을 하더라도 지난번보다는 더욱 더 간략하게 프로그램을 작성할 수 있도록 노력하라.  

디버깅은 불필요한 일이 아니다  
번 문제를 생각해 보자. 우리의 예상과 달리 프로그래밍 중에서, 특히 프로그래밍의 일부분인 코딩 중에 새로운 코드를 만들어 내는 시간보다는 기존의 코드를 개선하거나 잘못된 코드를 찾아내는 일에 절대적으로 많은 시간을 쏟는다고 한다.  

필자의 경우도 예외는 아니었다. 그러나 경험을 토대로 스타일을 바꿔나가기 시작했다. 필자가 제일 많은 시간을 쏟는 부분은 자료 수집과 연습 코드 부분이다. 필자의 경우에는 무조건 책이나 웹을 통해 관련 자료를 수집하고 재빨리 훑어 내려간다. 다 이해하지 못해도 상관없다는 듯이 읽어 내려간다. 특히 요즘은 노하우보다 노웨어가더 중요하다고 말하지 않는가. 이미 많은 문제의 일부분을 다른 사람이 해결했을 가능성이 높다. 이를 반복할 필요는 없다. 현 시대에서 요구하고 있는 프로그래머의 자질 중 하나는 처음부터 다시 만드는 것이 아니라, 기존의 것을 취사 선택해 창의적으로 결합시키는 능력이다.  

그 다음에는 짧은 연습 코드를 많이 작성한다. 핵심적인 부분에 대한 연습 코드를 몇 번 작성하다 보면 프로그램의 절반이 끝났다고 해도 과언이 아니다. 개인적으로 자료 수집과 연습 코드, 특히 연습 코드에 신경을 많이 쓰는데 이렇게 함으로써 프로그래밍 과정에서 절대 빠질 수 없는 디버깅(debugging)을 최대한 피할 수 있다고 생각하기 때문이다.  

하지만 어떤 식으로든 디버깅 과정을 피할 수 있다고 생각하지 말라. 사실 버그를 얼마나 빨리 잡는가, 그 짜증나는 시간을 어떻게 빨리 마칠 수 있는가는 그가 얼마나 유능한 프로그래머인지 판단할 수 있도록 해 주는 잣대이다. 디버깅이 마치 불필요한 과정이라고 생각하지 말았으면 한다. 여러분이 만든 버그야 어떻게 잘 피할 수 있을 지 몰라도 실전에서는 남이 만들어낸 버그를 찾아야 할 때가 많다. 그런데 남이 만들어낸 버그를 잘 찾는 사람이란 결국 알고 보면 자기 자신도 똑같은 버그를 만들어 보았고 고통스러운 시간을 통해 버그를 찾아낸 경험이 많은 사람이다.  

디버깅에서 중요한 자세는 절대 짜증내지 말고, 적군을 무찌르겠다는 식의 투지를 갖고 단시간 안에 돌파하는 것이다. 만약 한 가지 방법이 실패했다면, 잠시 먼 발치에서 새로운 구상을 한 뒤, 다시 전투적으로 임한다. 지루하게 디버깅을 하면 시간도 많이 걸리고 정신도 피폐해진다.  

결론적으로 정도의 차이가 있을 뿐, 여러분이 현실 세계에서 당면하고 있는 모든 문제는 피해야 할 어떤 일이 아니라 사실 프로그래밍이라고 하는 전체 과정에 원래부터 속해 있던 일부라는 사실을 인식하고 이에 대해 짜증을 내는 수동적인 방식이 아니라 좀 더 현명하게 그리고 적극적으로 자기만의 해결책을 찾아나가길 기대하겠다.  


몇 가지 실천안  
다음 실천안은 여러분이 좀 더 프로그래밍을 즐길 수 있고 직업적으로도 유능함을 발휘할 수 있게 되길 바라며 마음속에 떠도는 생각을 아주 간략하게 정리해 본 것이다.  

◆ 프로그래밍이란 절대 코딩이 아니다. 먼저 생각하고 만든 것을 정리하고 문제점을 해결해 나가는 모든 과정이 프로그래밍이다. 이 점을 자기 자신에게 충분히 납득시켜야 한다. 코딩은 프로그래밍의 일부이다.  
◆ 각 언어는 모두 나름의 탄생 이유가 있으며 그 언어를 만든 사람의 아이디어가 담겨 있다. 언어를 먼저 선택하려 하지 말라. 유능한 프로그래머는 절대 한 가지 언어에 집착하지 않는다.  
◆ 언어를 처음 배울 때에는 그에 걸맞게 쉬운 언어부터 시작하라. 실전에서 사용하는 언어를 먼저 배워두면 더 이득이 될 것이라고 생각하지 말라. 전문 프로그래머가 되려면 최소한 세 개 이상의 언어를 익혀야 한다. 물론 세 가지 언어를 똑같이 잘 할 필요는 없다. 자기 주 종목 언어를 갖지 말라는 말이 아니다.  
◆ 책을 다 읽고 나서야 프로그래밍할 수 있다고 생각하지 말고 배운 만큼만 갖고도 연습 코드를 작성할 수 있어야 한다.  
◆ 언어 그 자체는 여러분의 상상력을 키워주지 않는다. 상상력은 여러분 스스로 인생의 모든 영역에서 듣고 배우면서 채워야 한다. 언어는 상상력을 실현할 도구만 제공할 뿐이다. 과학과 수학에 관심을 가져 보라(그렇다고 해서 A 등급을 맞을 만큼 잘 할 필요는 없다).  
◆ 주석 및 문서화 버릇을 들이자. 프로그래밍의 귀찮은 일부가 아니라 매우 중요한 핵심 부분이다.  
◆ 언어책이 줄 수 있는 지식의 양은 딱 그 만큼이다. 여러분의 상상력과 프로그래밍 능력을 살찌워주는 것은 다른 사람, 다른 프로그래머다. 적극적으로 프로그래밍 사용자 모임 또는 뉴스그룹에 참여해 남을 돕고 남으로부터 도움을 받는 것이 자기 계발의 원천이다.  
◆ 자기가 습득한 지식은 자신만이 볼 수 있는 형태든 아니면 홈페이지를 통해 누구나 볼 수 있는 형태든 상관없이 정리하는 습관을 갖자. 무엇이든 막상 글로 적으면 자신이 얼마나 피상적으로 알고 있는지 각성하게 되고 지식을 좀 더 견고하게 만들게 된다.  
◆ 현실은 현실이다. 영어를 잘 못하고 두려워하는 사람이 최고의 프로그래머가 되기는 거의 불가능하다. 여러분이 한국어만 하면 한국 프로그래머의 지식만 습득할 수 있을 뿐이다. 영어를 두려워하지 않는다면, 그 대가는 전세계 프로그래머의 지식 습득이 된다(영어를 잘 하는 방법은 영어를 잘 하는 사람에게 물어보라).  

아무튼 여러분이 프로그래밍의 본질을 재확인하고 프로그래밍하는 그 과정을 즐길 수 있는 사람이 될 수 있기를 바라며 글을 마친다.  
신고
Posted by xyzlast Y2K
TAG 개발자
좀 색이 맘에 안들긴하지만... 까만 배경에 EnvyCode R을 사용하는 setting이 얼마 없어서.;;

저작자 표시 비영리 변경 금지
신고
Posted by xyzlast Y2K


티스토리 툴바