MS Visual C++ 에서 함수에 임시 객체를 (non const) reference로 넘기기

작년 하반기에 VisualStudio 2013 기준으로 작성된 C++ 프로젝트를 linux (+ GCC)로 옮기는 작업을 했다.
그 때 제일 충격적이었던 것은 — 한 2년넘게 Windows 환경 작업을 (직업적으로는) 안한 탓이 크겠지만 — 이 글 제목의 그것:

void func(X &x);
// ...

func(X());

이런 코드가 문제없이 컴파일되고 동작하는 것.

문제는 이 코드는 GCC 혹은 clang 에서 제대로 빌드되지 않는다; 게다가 저게 단순히 저런 함수 꼴 하나였으면 참 좋았을텐데 (…), template + perfect forwarding이 섞인 코드라 반쯤 돌아버리는 줄 알았음.
여하튼 VisualStudio에서만 작업할게 아니라 다른 OS/Platform으로 포팅할 생각이 있다면 VS의 language-extension으로 지정된 부분들은 좀 버리고 갑시다.

2012, 내 프로그래밍 언어는…

작년에 이어, 올해에도 twitter에 적은 #code212에 덧붙여 글 하나 쓰기.

올해 주로 사용한 언어는,

  • Python
  • Bash script
  • C++
  • JavaScript
  • C#
  • Go

정도의 순서인 듯 하다.

작년의 순서와는 상당히 달라졌는데 그 배경은 역시 이직.

Windows 에서 C++ 코드베이스에서 작업하던 환경에서, linux 위에서 python 코드베이스를 작업하니 바뀐 게 많지(…).

 

Python

회사를 옮긴 이후로 C++ 코드는 한 줄도 안 짜고 python을 주 언어로 작업했다.

분산 서비스 (w/ restful interface)와 그 프런트엔드에 해당하는 웹 앱, 그리고 이를 테스트하는 코드들을 다 python으로 구성했다. 올해는 정말 python은 징그럽게(?)만진 듯.

감상을 적자면,

  • 편하다; 사실 이건 작년의 주 언어가 C++이라?
  • 생각을 코드로 표현하는데 부분에 걸리는 시간엔 거의 C++ 수준에 다다를 정도로 쓴 것 같다
  • 상대적으로 “뭘 만들지”에 집중하고 “어떻게 만들지”에는 조금 덜 신경 쓴다

여하튼 python으로 작성한 서비스가 내년 중엔 아마 라이브로 전환 할 듯…

Bash script

Python으로 프로그램을 만들긴 하지만 이걸 실제로 배포하고, 설치하고, 설정하는 부분은 전부 bash script. 특히나 debian packaging하면서 갈수록 bash script 짜는 기술이 늘어가는 것 같다. 어흑

C++

이전 회사에선 주로 C++을 썼다. 그리고 2월 말까지는 C++로 코드 짰음 (사실 3월에 남은 날 수 출근할 때 C++ 코드 디버깅도 했다(…) )

JavaScript (w/ html, css, …)

Python으로 짠 서비스의 프런트엔드는 결국 html + JavaScript + css.

들어가서 바닥부터 만든 한 프런트엔드의 css를 직접 짜며 삽질하다가 bootstrap으로 바꾸고 신세계가 펼쳐졌다 (…).
내가 작성한 JavaScript는 IE에서 안 돌기도 하고 – 나중에 합류한 프런트엔드 엔지니어 분이 해결해 주심 – 하여간 삽질이 Orz.

초반엔 사람이 없어서 짰는데 요즘은 거의 손 댈 일이 없는 듯. 그래도 어제 포스팅 한 일 같은 류를 처리하려면 어느 정도 알긴 해야 할 것 같은데;

C#

작년에 C# 배우면서 짰던 프로그램을 퇴사하기 전까지 유지 보수하다가 나왔음. 지금은 그 회사의 A모 게임과 B모 게임이 쓰고 있을 거라던데 난 모르겠다 (야).

이젠 Windows 환경이 아니라서 더 이상 만질 일은 없을 듯. (작년 감상을 보고 생각해도 이건 잘 된 일?)

Go

Go로 동작하는 서비스를 작성하겠다는 야망을 품었으나… (내년에 계속?)

 

정리:

  • Python 코드베이스를 작성하는 일로 옮겨왔다
  • Linux로 옮겨왔으니 bash 나 기타 등등 만질 일이 늘어남
  • Go로 서비스 작성하고 싶다 (…)
  • 내년엔 C++ 만질 일이 생길지도…

KGC2012: Avoiding Developer Taxes

GDC 2012의 “Robustification Through Introspection and Analysis Tools (Avoiding Developer Taxes” 와 유사한 내용인 듯.

강연 내용에 해당하는 코드(clang-extract)는 https://github.com/sk-havok/clang-extract 에서 볼 수 있다.

내용 요약:

고질적인 게임 개발 비용들(taxes)

직렬화

메모리 정보 보기

스크립트 바인딩

버전 관리

Reflection

C++로 개발할 때 reflection 을 이용해서 푼다. 여기엔 이런 문제가 있다:

  • 어떻게 리플렉션을 만들까?
  • 어떻게 (소스 코드와 데이터에) 싱크가 맞을까?
  • 견고성 (robustness)

수동으로 처리하는 것은 문제가 많다. (buggy!)

regex 등으로 헤더를 처리하는 것도 마찬가지.

그리고…

  1. 하지만 C++에는 reflection이 없다
  2. GCC XML을 써봤다. 느리고 개발도 완성 상태가 아님[1]
  3. clang + LLVM frontend를 수정해서 reflection 생성기 개발

C++ headers –> LLVM + clang –> DB 로 변환
그리고 이걸 이용해서 리플렉션 생성, 스크립트 생성. 그리고 정적 분석.

그리고 이 리플렉션을 쓰면 직렬화는 껌(…).

메모리 alignment를 해석해서 구조체의 메모리 배치를 효율적으로 바꾼다거나 하는 것도 가능.

LLVM+clang pass는 견고하고, 싱크가 안 맞는 문제를 방지

DB Consumer pass 는 컴파일 이전에 논리적인 문제를 찾고, 런타임 문제를 컴파일 시간에 잡게 한다.

유닛 테스트 역시 (자동으로) 리플렉션 데이터를 검사할 수 있게 됨.

 

Language Binding

C++을 스크립트에 바인딩 하려면 문제가 많음. 다만 리플렉션을 쓰면 데이터는 자연스럽게 됨. 그렇지만 callable들은 여전히 힘듬.

함수 trampoline 의 경우 C++ 함수 signature를 처리하기 위해서 생성하는데, 함수 signature마다 bridge 함수를 만드는 쪽이 함수마다 wrapper를 만드는 것보다 싸다.[2]

메모리 리포팅

Leap frog 테크닉을 쓴다: (일부) 메모리 할당의 타입을 기록하고, 이 오프셋과 사이에 있는 데이터를 유추. (indirect pointers)

그리고 stack walk하면서 이에 대한 데이터를 추정해서 메모리 할당 맵을 offline으로 생성할 수 있게 된다. 그렇지만 일부 컨테이너 류 등에서는 false positive가 있을 수 있고, obfuscated pointer[3] 나 타입을 알 수 없는 void* 류는 처리 안됨. 그래도 디버그 모드는 콜스택과 시간을 남겨서 처리한다.

…로 annotated memory data를 만들 수 있게 함.

 

버전 관리

버전 관리는 쉽지 않음. 매뉴얼하게 하면 버그 나오기도 매우 쉽고 코드 관리도 힘들다.

이걸 snapshot versioning으로 구현. (reflection data의 CRC 이용해서 reflection 결과가 바뀌는 걸 추적)

하지만 이것의 오버헤드 때문에 좀 더 세밀한 단위로 변경 사항을 추적하고 이걸 patching하는 코드를 (semi-automatic하게) 만들게 함.

 

결론

코드 말고 데이터를 생성하자. 데이터가 더 작고 용도도 많다.

  1. 예전에 C++ 헤더들을 GCC-XML의 python bindiong으로 해석해서 이를 처리하기 위한 script 등을 만드는 작업을 했었다. 흑흑 이걸 좀 더 했으면 GDC감인가! []
  2. 함수 N개에 대해 400bytes 씩인 것 vs. 40 * N + 60 * 함수 signature 수 정도라서; 아 근데 60인지 manuscript 안 보면 확인을 못하겠다 ㅠㅠ []
  3. p ^=1; 같은 포인터 연산 []

NDC 참관기: 덤프 파일을 통한 사후 디버깅 실용 테크닉

슬라이드는 “NDC2012 덤프 파일을 통한 사후 디버깅 실용 테크닉“에서 볼 수 있음.

넥슨 김이선 님의 발표.

내용 요약:

돈을 벌기 전에는 배포 전 디버깅이 중요하다.
라이브 상황에서는 배포 후 디버깅이 더 중요해진다.

덤프 파일

특정 상황 — 특히 안좋은 상황 — 에서 프로세스 상태를 디버깅 용으로 남기는 것.
풀 메모리 덤프를 남기면 좋지만 커서(…) 미니 덤프를 남긴다.
상용 서비스까지 갔다면 미니덤프를 남기고 이를 수집해서 디버깅하는 시스템은 필수.

하지만 미니 덤프 디버깅의 현실은…

  • 덤프 파일을 열었는데 심볼이 없다고 어셈블리 코드가 보이는 경우
  • 여기서 죽으면 안되는데 왜 죽었나 싶은 경우?
  • 콜스택이 깨졌다거나
  • 풀 메모리 덤프를 남겼는데 내가 보려는 객체는 어디에?

덤프 파일과 pdb 파일 연결하기

  • 미니덤프 헤더는 RSDS 헤더, GUID, age, pdb-path 등이 들어감
  • pdb, exe, minidump는 이 GUID로 연결된다
  • 심볼서버는 당연히 써야
  • 보안 솔루션 (더미다 류) 을 사용하면 덤프 파일의 GUID가 바뀐다
  • 하지만 COFF file format의 링크 시간을 기록한 타임 스탬프는 유지
  • 클라이언트 덤프 수집단계에 미니덤프와 해당하는 PDB를 맺어주는 단계를 넣자(클라이언트 버전 정보; 타임 스탬프를 이용해서)

여러 개의 덤프 파일을 분석할 때

일어나지 않을 것 같은 일도 덤프 파일이 많으면 분석할 수 있음[1]

  • 분류 기준으로 EIP, callstack, 게임에 따른 정보(맵, 장비, …)
  • 외부 모듈이나 말이 안되는 곳이면 어떻게하지? 클라는 환경을 통제할 수 없으니 외부 변수를 추적한다
  • EIP와 다른 변인 (OS, CPU, GPU) 등을 보면 예상되는 것과 다른 분포인 경우가 있다 (=환경 편재)
  • OS라면 드라이버 버그, CPU의 문제 (보통은 mainboard), GPU 문제, 외부 모듈 (보안 프로그램이나 해킹 툴)

사례 분석

 

  1. DF의 코드 베이스를 VS 2003에서 VS 2008로 이전함.
  2. 특정 유저 (소수) 에서 채널 선택하는 순간 HeapAlloc/HeapFree 중에 크래시 하는 버그 발견
  3. Heap-corruption이라,
    • 게임 시작에서 채널 선택하는 부분까지의 코드를 리뷰
    • 이 영역에 많은 수의 trap code와 HeapValidate 코드 삽입
    • 하지만 문제는 발견되지 않음
  4. 모듈 목록에 환경 편재가 있음: BFCO0GAF.dll 등의 알파벳/숫자가 섞인 특정 패턴의 모듈 발견
  5. 해당 dll이 악성 프로그램이 삽입한 것; 2003과 2008의 heap 구현이 달라서 생긴 일

콜 스택이 깨지는 경우

  • EBP, ESP 중 하나만 깨져도 콜 스택을 복원할 수 없다
  • 이를 다음 휴리스틱으로 극복
    1. 스택 메모리에서 주소를 추려낸다 (모듈 정보의 주소 영역을 이용해서)
    2. 스택 메모리에서 스택 주소를 추려낸다
    3. 1 + 2를 해서 콜 스택을 추정
  • 프로그래머의 해석이 필수

힙 메모리 문제

  • 메모리 덤프가 있으면 디버깅에 큰 도움이 된다
  • 하지만 모든 메모리 객체에 접근하는 건 쉽지 않음
  • 메모리를 exhaustive하게 검색
  • vfptr 값 이용
  • typeid(T)의 구현 형태를 이용해서 타입 이름을 이용해서 검색

이걸 포함한 오픈소스 툴을 공개

 

 

감상:

이번에 네 개 세션 밖에 못들었는데, 그 중 제일 괜찮은 강연이었다. 다음 세션을 회사 돌아갈 시간이라 못 들은게 아쉬움.

내가 예전에 했던 유사한 시도는 통계적으로 분류하고 / 적당한걸 찾을 수 있게 도와준다 정도였는데 (VS 안띄우게 하는게 목표였으니..) 이렇게 실제 사례를 바탕으로 한 내용을 알고 있었다면 훨씬 좋게 할 수 있었을 듯.
그리고 바이너리가 수정된 경우의 처리는 제대로 못했는데 — ipkn 패치해서 돌아가게 수정 — 이 부분에 대한 정보도 얻게 되어서 좋았다.

게다가 강연자 분이 “이런거 되는걸 모아서 새로 짜서 공유했습니다”라고 말한건 대박(…).
아마 `지식 공유’란 점에서 모델이 될만한 수준.

summerlight 님이 녹화한 영상도 토런트 시딩되고 있을테니 (촬영 가능한 세션이었음) 관심 생기신 분들은 한 번씩 보는걸 추천합니다.

  1. 이건 이전 회사에 있을 때 내가 포스트모텀 디버깅, 그것도 최대한 많은 수를 수집해야 한다고 주장한 이유와 같음 []

VS 2010 빌드 속도 올리기

C++만 가지고 쓰는 얘기.

작년에 지급 받은 머신 셋팅을 수정해서 어떻게 빌드 속도를 올렸는지 정리. 아마 한동안 업으로 Win32에서 C++ 할 일은 없을 것 같아서 기억이 사라지기 전에 정리.
저 머신 자체가 내 손을 이미 떠나서 틀린 부분이 있을테니 발견하면 지적 좀 해주시길.

머신 스펙은  대략,

  • CPU: intel i7-2600
  • DRAM: 16 GiB
  • Storage: intel SSD 80 GB + SATA HDD 500 GB

그리고 SSD 용량이 적어서 아래 같은 일을 추가로 했다.

  • 4 GiB의 RAM drive를 할당하고, TEMP, TMP에 해당하는 디렉터리를 RAM 드라이브에 맵핑
  • VisualStudio와 Windows Platform SDK는 SSD에 설치
  • 기타 프로그램(오피스나 LaTeX)은 HDD에 설치
  • 소스 체크아웃은 HDD 쪽에
  • 빌드 스크랫치도 HDD 쪽에
  • IPCH 파일 저장되는 위치 변경. 방법은 민장님 블로그의 “Visual Studio (C/C++) 2010 몇 가지 팁” 참조

대략 이 정도만 설정해도 꽤 빨라지더라. 이전 머신 (Q8600 + 4GiB RAM + HDD only) 에서 빌드할 때 20+분 걸리던게 2+분 수준으로 줄어듦. 예전엔 인크레디빌드 써봐야 빌드 시간이 18분 수준이라 안 쓰느니만 못한 꼴을 몇 번 봤고, 머신 변경 후에는 아예 안 쓰게 되었음. 최대 코어 수도 12개던가로 제한되어 있기도 하고(구입한 라이센스 문제).
그 원인이 된건 다음 것들인듯.

  • IO가 두 디스크에 분산되서 소스 로드 속도가 빨라졌다; 어차피 Windows 헤더와 개발 중이 프로그램 헤더가 모두 로드 되야 하니…
  • VS가 북키핑 용으로 쓰는 듯한 일부 .log, build.unsuccessful[1] 파일들 (내용물이 없거나 매우 짧은) 을 임시 디렉터리에 해당하는 곳에 잔뜩 쓴다. 이게 RAM drive로 옮겨가서 디스크 IO 감소 + 분산
  • CPU 아키텍쳐 변화 (무려 두 세대) + 코어 수 증가(4에서 8로)로 단일 파일 컴파일 속도 증가
  • Win32/x64가 다 있는 경우 개발 중에는 x64 빌드만 사용. 빌드 / 테스트 수행 시간 모두 짧더라

등의 이유로 빨라졌다고 생각한다.

 

궁금한 것:

  • 모든 소스가 SSD 두 개, 혹은 SSD RAID 위에 올라가 있다면 좋겠지만 그런 설정은 받아본 적이 없으니 궁금증만…
  • 빌드 스크랫치 전체를 RAM 위에 올려놓고 싶긴한데, ECC RAM 아니면 살짝 불안하기도 하고, 그 정도로 메모리를 풍족하게 써본 적도 없고…
  • 여기에 unity build를 섞었다면 어땠을까 하는 것..

해보신 분들의 의견을 구합니다(…).

 

PS. 근데 가장 좋은건 Google이나 Microsoft 처럼 빌드 팜이 있는 거겠지만, 그 정도의 엔지니어링을 하는 건 아니었으니…

 

  1. 정확한 파일 이름은 누가 좀.. []

node.js 혹은 CPS 단상

지난 주에 둘째 태어나서 병원에 있는 동안 SNS와 블로고스피어를 스쳐지나간 글 중 제일 눈에 띄는 부분이 “CPS와 node.js” 관련된 내용이었다.

iPhone은 정리에는 그다지 좋은 기기라고 못하겠다. 내가 생각하던 문맥을 저장하기엔 내 활용 방법의 문제거나 기기가 부족하거나; 여하튼 기억나는 글들을 여기 정리하자면 (twitter는 정리가 불가능하니 제외),

웹 서버 아키텍처와 프로그래밍 모델의 진화 http://ricanet.com/new/view.php?id=blog/110903 (node.js의 I/O 모델을 점검하기에 좋은 글)

Node.js의 소개글 들에 대한 유감 http://himskim.egloos.com/3810574

이에 대한 홍민희 님의 글 http://blog.dahlia.kr/post/18300740247

그리고 다시 (홍민희 님의) 비동기 I/O 프로그래밍 모델 관련 글 http://blog.dahlia.kr/post/18355002657

 

이에 대한 내 생각을 정리하자면:

1. node.js는 hype이라 생각한다. node.js 광신도(…)들이 말하는 장점은 이미 오래된 얘기고 (이벤트 기반의 비동기 I/O 모델, 단일 이벤트 루프와 그로 인한 싱글 스레드의 단순함), 이런 시도를 하는게 node.js만 있는 것도 아니다. 다만 세상에 JavaScript 프로그래머가 많기 때문에 그렇게 느껴지는 것 뿐이지. 서버 혹은 백엔드 프로그래밍에선 너무 오래된 — (게임) 서버 프로그래밍을 주로 하던 이들 사이엔 이게 왜 이슈가 되는지 궁금해하는 사람들이 나온다 — 이슈라서 말이지.

다음 언어들로도 `흔히’ CPS 스타일의 프로그래밍을 할 수 있다. 그리고 이 언어들 모두에서 node.js에서 `하면 안된다’라고 주장하는 한 이벤트에서 긴 계산을 하는 일도 실행 모델에 따라선 해도 된다. 그리고 이 언어들에선 `흔히 하는 일’에 불과하다.

Go: goroutine 자체가 일종의 CPS 스타일 프로그래밍이다. 그리고 일반적인 이벤트 큐 처럼 쓸 수 있는 channel 개념 역시 존재한다. 그리고 이 두 개념을 최대한 활용해서 만든 언어가 Go다. 자세한 내용은 내 과거 포스팅을 참조하자 (https://rein.kr/blog/archives/tags/go) 개인적으론 이런 류의 I/O 비동기 / 멀티플렉싱을 생각하고 짠다면 Go가 가장 깔끔한 프로그램이 나온다고 생각한다.[1]

C#: C#의 익명 함수 (delegate라고 부르던데) 역시 이런 CPS 스타일로 프로그래밍 할 수 있다. Nexon의 `마비노기 영웅전’과 `마비노기 2’도 이런 개념을 활용해서 서버를 구현했다. 2011년 NDC 세션의 내용을 정리해놓은 것처럼 (https://rein.kr/blog/archives/2696https://rein.kr/blog/archives/2671) 이걸가지고도 JS에서 흔히 하듯이 성공/실패 처리를 cps로 작성한다.

C++: C++11의 lambda 혹은 그 이전의 std::function[2] 을 이용하면 역시 CPS 형태의 코드를 작성할 수 있다. 내가 작성한 게임 서버 라이브러리 역시 이를 이용한 CPS 스타일의 코드가 포함되어 있다.

 

2. node.js가 단일 스레드, 즉 단일 문맥만으로 처리하기 때문에, computation-intensive한 작업은 처리할 수 없다. 그래서 어쩔 수 없이 백그라운드 태스크 큐 등을 써야하고, 이로 인해 생기는 지연 시간(latency) 문제는 극복할 수 없다.
게임 서버에서도 node.js처럼 (혹은 그보다 낫게)

  • 복수의 스레드가 네트워크 이벤트(read/write)를 비동기로 처리하고,
  • 네트워크 이벤트를 서버 메인 스레드(그러니까 논리적으론 단일 스레드 프로그램)로 전달하고,
  • 서버 메인스레드가 내부 로직을 처리해서 다시 네트워크로 보내는

구조를 사용한 서버들이 있다. 다만 이 경우엔 계산 량이 많은 경우 지연 시간이 길어진다. 그것도 게임 상에서 상호 연관이 없어 보이는 부분들 사이에 영향을 주는 형태로 -_-;
게임 서버는 웹과는 좀 다르게 persistent storage에 다 저장하지도 못하고, 각 연결 간에 상호 작용도 많아서 어쩔 수 없이 생기는 문제이긴하지만 맨 첫 글에서 얘기하는 것 처럼 node.js가 `유니크’한 것은 아니다. JavaScript로 서버 프로그래밍을 진행한다는 것은 꽤 참신하지만 말이다.

그리고 서버 메인스레드가 1개가 아니라 복수개 일 수도 있고 — 내가 본 코드에선 이게 주류다 — 걔 중에도 IO 스레드가 full swing을 하돼 non-blocking한 알고리즘을 이용해서 복수의 큐를 사용하고, 블럭킹을 제거한 구현체도 있다.

 

3. 프로그래밍 모델은 CPS는 `쉽게 만들어낼 수 있지만’, 프로그래머에겐 꽤 골치거리라 생각한다. 홍민희 님의 말대로 가장 쉬운 형태는 co-routine일 것이라 생각한다. CPS처럼 이전 문맥에 대해 생각할 필요도 없고, 불필요한 nesting (node.js말하는 거임) 도 필요치 않다. 다만 이 경우에는 언어적인 수준에서 지원하지 않으면 안된다. 불행히도 내가 사용하는 주요 언어인 C/C++의 경우 co-routine을 사용할 수단은 OS fiber수준 정돈데, 이 경우엔 다른 동기화 객체들을 쓸 때, 동기화 단위가 스레드라서 fiber끼리 switching할 때 지옥을 보게 된다. 하지만 node.js 정도의 프로그래밍 모델에선 이게 가장 간편할 것이다. 각 연결 별 문맥끼리 상호작용이 적다면 더더욱 말이다.

  1. 이 언어를 만든 회사가 Google이란 생각을 하면 더 그렇다 []
  2. 혹은 그 이전 구현체인 std::tr1::function, 혹은 이거랑 별반 다를게 없는 boost::function을 생각하면 더 이전부터 []

2011, 내 프로그래밍 언어는…

twitter에 #code2011 에 덧붙여 글 하나 쓰기. 2011년에 주로 사용한 언어는,

  • C++
  • Python
  • C#
  • JavaScript
  • SQL
  • Lua
  • Go
순으로 쓴 것 같다. (트윗에는 Lua를 못 적었음…)

C++

우선 주 언어로 쓴 C++. 내년에 공개될 모 서버를 작성했다. 사내 테스트까지 나간 것 중 C++11을 사용한 것으론 처음일듯.
그리고 옮겨간 팀의 서버 역시 C++로 작성하고 있다. 크래시 보고 도구도 밑 단은 C++…

내가 주목한 특징을 꼽자면,

  • 바위에 끌로 새기는 것 같이 작업함 – 집중해서 빡쎄게;
  • lambda로 이전에 boost 쓰는 걸 대체 – C++11 만세!(…)
  • 괜찮은 성능 – 내가 사용하는 모든 언어 중 가장 월등한 성능을 자랑한다
  • Bare metal 위에서 돈다 (위랑 같은 의미?)
  • 원하는 수준만큼 저 수준에서, 원하는 만큼 세밀하게 제어할 수 있다
그래서 이걸로 여전히 게임 서버를 짜고 있는듯…
 

Python

팀 내의 코드 생성기나 대부분의 스크립트는 python으로 작성한다. 올해에는 대략,

  • 데이터 변환 도구; .xls -> sqlite -> (C++ internal form) 으로 몇 가지 데이터를 옮겼는데, 이 중 첫 단계는 모두 python에서 해결
  • 크래시 덤프 분석 및 집계 기능. 크래시 덤프를  cdb 수준에서 분석하면 이를 토대로 다른 덤프들과 비교하고, 이에 대해서 웹에서 볼 수 있게 했다
  • 덤프 수집 (web)
  • 크래시 덤프 뷰어 (web)
  • 빌드 도구나 덤프 관련 툴에서 메일 생성 / 알림 기능

에서 python을 주로 썼다. 물론 예전부터 쓰던 코드 생성기, 빌드 보조 도구에도 python을 쓰고 있다.

…덧붙이자면 요즘 .svg를 python으로 만드는 뻘짓을 했다. 근데 생각해보니 python-cairo를 쓰는 게 더 간단하잖아?;;;

 

C#

연초에 파일 전송 도구를 하나 짜야 했다. 원래 생각했던 건 python 기반으로 빨리 짜고 딴거 하고 놀자(…)였는데, 

이거 누가 유지 보수 하냐

라는 태클에 물건너 갔음. 흑흑.

그래서 실 서비스에서 써본적(…)도 없는 C#으로 짰음. 사실 태클건 사람들은 태클 걸면 C++로 짤 거라고 생각했다고…
애매하게 편하고, 애매한 수준까지만 제어할 수 있어서 개인적으로 불만이 좀 많았음. 내가 python을 안 쓴다면 모를까 Orz. 

누가 비슷한거 시키면 그땐 정말 python 쓸 테다… 일단 저거 linux에서 옮겨서 쓸 생각을 하니 눈 앞이 캄캄하기도 하고 — 누가 Mono 관련 조언 좀…

 

JavaScript

까놓고 말하면 js에는 완전 초보임. 그래서 python쪽에서 js를 쓰긴 했는데, 크롬에서만 돌길래(…) 포기하고 jQuery로 전부 옮겼다. JavaScript를 썼다기 보단 jQuery를 쓴 느낌이지만 (…).

CouchDB에서 map-reduce 용 언어로 js를 쓰긴하지만, 이건 그렇게까지 복잡하게 활용한게 없으니 좀 애매하다. 따지고 보면 올해는 js보다 json을 더 많이 본 것도 같다(운다).

올해 얻은 건 jQuery를 좀 더 익숙하게 쓰게 되었다 정도?

 

SQL

ORM하나 제대로 쓰고 싶었습니다만 꿈도 희망도 없어; 그냥 python위에서 클래스 수준으로 포장해서 하단의 데이터 스토어로만 쓴 듯.
위안이라면 MySQL / CouchDB를 선택해서 쓸 수 있게 만들었다 정도지만; 

Lua

팀 내에서 사용하는 서버 용 부하 테스트 툴은 (NDC에서 ipkn이 발표한 내용은 http://ipkn.upnl.org/ndc.html 을 참조) lua를 스크립트 언어로 쓴다.
그런 의미에서랑, 몇 가지 도구에서 lua를 썼다. 이쪽에선 내가 발전이 전혀 없는듯… 

Go

연초에는 좀 만졌지만 — 위에서 C#/Python으로 헀던 일 중 일부는 원래 Go로 하려던 건데 — 그 이후엔 망했음.
과연 내년에는 나의 야망(…)대로 Go로 돌아가는 서비스를 만들 수 있을까;

일단 올해에는 회사 안에서 / 실제 서비스에서 linux 기반으로 해도 된다는 건 확인했으니, 내년을 기약합시다(…). 

 

요약:

  • C++/python을 여전히 많이 쓰고 있다.
  • C#은 안 편했음; 내년에는 아마 다른 선택을 할 듯.
  • 웹 질(…)로 JavaScript/SQL을 좀 만졌다. 내년엔 기약 없음…
  • Go. linux 기반 서비스를 좀 더 해도 될 것 같으니 내년을 기약 

Rest in peace, dmr

Dennies MacAlistair Ritche (dmr) 사망. (실제 날짜는10/8일이라 한다)

여기서 그의 명복을 빌어본다.

지난 주의 스티브 잡스 사망도 슬픈 일이지만, 개인적으로는 데니스 리치의 사망이 더 임팩트 큰 일.

간단히 말해서, 우리가 현재 쓰고 있는 SW의 가장 밑 바닥을 지탱하는 기술과 개념이 데니스 리치 손에서 태어났다.

  • 시스템 프로그래밍의 가장 널리 쓰이는 C 언어의 창시자다; 우리가 쓰는 linux, Windows는(아마?)는 C 기반의 커널로 되어 있다. 대표적인 웹 서버 (아파치나 nginx) 역시 C로 만들었다. 그리고 이 C로 Unix를 재 작성(!)해서 `앞으로 OS를 어떻게 만드느냐’에 관해선 사실 상 결론을 내려버렸다.[1]
  • 내가 가장 사랑하는 *nix의 일관성 – 간단한 텍스트 기반 I/O의 프로그램을 연결해주는 파이프.
  • 현대적인 개념의 C-runtime IO 방식을 고안.
  • 내가 읽어 본 가장 간결하고 군더더기 없는 프로그래밍 책 – The C Programming Language의 저자.

좀 더 쓰자니 그냥 여길 링크: http://j.mearie.org/post/11385959754/rip-dennis-ritchie 에 더 잘 정리되어 있다.

  1. 더불어 이 두 업적으로 1983년에 켄 톰슨과 함께 튜링 어워드를 받았다 []