Interop Madness

클라이언트 서버간 암호화  관련해서 개념 증명 + 몇 가지 성능 측정을 해야해서 몇 가지 언어 + 플랫폼에서 libsodium 1 을 호출해봤다. 그 와중에 겪은 일 정리.

C++

이쪽은 평범한 C/C++ 인터페이스니 문제 없이 끝.

Python

위에서 구현한 부분을 클라이언트 쪽 구현을 (빨리) 만들어서 테스트하는 작업을 했다.

여기서부터 문제가 생기기 시작. Ubuntu 16.04 (xenial) 이 제공하는 libsodium 래퍼가 python-nacl 2 인데, 써보니 내가 쓰려는 함수가 여럿 없다. 특히 crypto_stream* 류 함수가 없더라. 그래서 다른 래퍼가 있나하고 PyPI 에서 몇 가지 써보고는 빠른 포기.

이제 cffi 를 쓸 타이밍. C 코드로 정의한 함수를 변환해서 만든  .py 파일로 동적 라이브러리 (.so, .dll, .dylib) 에서 가져오는 방식을 썼다. 3 예~전에 ctypes 로 로딩할 때 괴로웠던 부분이 확실히 줄어들었다. ABI 대신 API 수준에서 접근하는 차이는 정말 컸다. cdata의 buffer 인터페이스도 쓸만했다.

cffi 로 libsodium 에서 필요한 함수들을 가져다 쓰기 시작한 이후로는 금방 일이 정리.

…하지만 이 시점에선 어떤 비참한 미래가 기다리는지 모르고 있었다. (?)

C#

(나로써는) 슬프게도, 클라이언트 쪽 구현 중 하나는 C#으로 해야한다. (Unity3d + mono) 게다가 이건 여러 플랫폼을 지원해야 한다:

  • Unity Editor: Windows, MacOS
  • Android: 다행히도 ARMv7만. Unity가 ARMv6는 지원하지 않는다 (?)
  • iOS: 기기 + 시뮬레이터에서 모두 돌아야 한다.

Windows는 (내가) 당장 쓸 머신이 없어서 일단 미뤄두고, 나머지에 대해서 잘 도는지 시험하기 시작. 꼬박 2일 걸린 것 같다 — 생각해보니 절반은 C++ 기반인 cocos2d 랑 같이 처리하는 것 때문이었던 것 같기도?

우선 각 플랫폼 별로 크로스 빌드를 시도…해야하나 했는데, libsoidum 저장소에 플랫폼 별 빌드 스크립트가 있다. 4 iOS/Android 쪽에 내가 쓰려던 함수 중 몇 개가 빠져서 컴파일 플래그를 조금 고친 것 말고는 별 일 없이 진행. 그리고 Unity 에서 (native) 동적 라이브러리를 어떻게 가져가나 고민했는데 경험 많은 동료분이 설명해주셔서 매우 간단한게 통과.

대략,

  • DllImport 로  C에 있는 함수들을 CLR 쪽에 노출하고
  • C# 코드로 이 함수들을 래핑하고
  • 다시 이 함수들을 써서 실제 개발자가 쓸 고수준 API로 바꾸자

라는 방향으로 진행했다. 에디터(=랩탑 위)에서 잘 도는걸 보고 android  기기에 올리기 시작. 왠걸, 초기화 (=sodium_init()) 은 성공했고 몇몇 초기화도 했는데, 그 이후에 호출하는 함수에서 크래시 (SIGSEGV).  (당연하게도) 콜 스택은 native code에서 죽는 것.

원인을 추측하기 시작:

  • C 함수 원형을 잘못보고 옮겼는지 확인 시작. C는 타입 무시하고 심볼 이름만 보니 내가 잘못 옮겼다면 크래시할 수도 있으니 우선 여길 의심하고 C 함수 원형과 하나씩 대조. 별 이상 없어 보였다 (불행의 단초)
  • 크로스 컴파일을 잘못했는가 확인: 생각해보니 C/C++ 로 올렸을 때는 잘 돌았다 (…)

…대략 정신이 멍해져오는데 다시 함수 원형을 보다가 불현듯 깨달은 사실:

C 쪽의 size_t 를 C#의 ulong 으로 지정했는데 Unity + ARMv7 은 32bit ABI를 쓰니 uint 여야하는 것. Orz.

그래서 이걸 iOS / Android 플래그로 ulong / uint 처리하게 했다가, iOS도 아직 32bit인게 남아있는 걸 보고는 (iPhone 5 및 그 이전 + iPhone 5C) UIntPtr 로 처리하고 강제 캐스팅하게 수정해서 마무리했다. 그러고나니 잘 돌더라.

 

3줄 요약

  • ABI 맞추기는 삽질이다. 어떻게든 API 수준으로 해결할 수 있는 법을 찾자 — python의 cffi 처럼. 아니면 기계적으로 처리할 방법을 찾아야?
  • (부득이하게) ABI를 맞춰야 한다면 가능한 arch 목록을 잘 확인하자. C/C++에서 편했던 platform dependent type들이 대재앙
  • 여러 플랫폼 지원하는 라이브러리는 정말 인생에 도움이 된다. 잘 쓰고나면 널리 알려줍시다 (?)

 


  1. libsodium 페이지. 현 시점에 적합한 대칭키 암호화 + AEAD, ECC 함수들, system random source 를 래핑한 함수, side channel 공격을 피하는 비교, 해시, … 등등을 제공하는 잘 만든 라이브러리. 인터페이스도 보고 바로 쓰는게 그다지 어렵지 않다. 
  2. GitHub 저장소. libsodium 이 fork(?)한 NaCl 을 래핑한 것 같은 이름이지만 libsodium 을 래핑한다. 
  3. API 수준에서, 소스 코드 밖에서 정의 부분을 참고해서 작성했다. 
  4. 저장소의 dist-build 디렉터리 의 스크립트들이 이에 해당한다. 

Docker for Mac 베타 사용기

연휴 내내 하루 빼고 일하다가 드디어 짬이 났다. 그래서 한 달 반쯤 전에 공개된 Docker for Mac 을 써보기 시작. 베타용 토큰도 지난 주에 받아서 사실 그 전엔 시간 났어도 못 써봤겠지만.

일단 내 희망 사항인 linux 툴들과 Mac 용 GUI 툴을 같이 쓰는 걸 시도해봤다. 대략 docker volume 으로 로컬 디렉터리를 컨테이너에 마운트해서,

  • MacOSX 환경에서 GUI 툴을 가져다 쓸 수 있을 것: 예를 들어 git mergetoolp4merge 를 쓴다거나
  • linux 몇 가지 distro. — 특히 ubuntu 14.04/16.04, CentOS 6/7 — 에 대해서 빌드 환경을 쉽게 불러내서 사용할 수 있을 것: 예를 들어 ubuntu 14.04 gcc4 에서 빌드 + 테스트해보고 + centos 6 (w/ devtoolset) 에서 빌드 + 테스트해보기 등.

이었다.

VirtualBOX 를 중간에 껴 넣는 대신, xhyve 를 써서 상대적으로 더 빠를 것 + volume 이 제대로 동작할 걸 기대했다. 대략 기대한대로 돌았는데 …

CentOS 7 컨테이너에서 빌드를 시작했더니 끝나질 않아서 activity monitor 를 열어보니 상태가 심각하다:

something-wrong

Docker volume 을 위한 구현체인 com.docker.osxfs 가 CPU 를 다 잡아먹고 있다. Docker volume 아닌 곳에서 빌드해보면 그 차이가 더 뚜렷함. (com.docker.xhyve 가 CPU를 다 쓴다)

something-acceptable

VMware Fusion 도 그러던데, Docker for Mac 도 CPU core 수 최대 값을 4개로 잡는다 — 12″ 맥북에서 무슨 만행을… 이것도 2개로 설정. (기본 값이 2개였는데, 메모리 늘리면서 생각없이 늘려서 Orz)

docker-setting-cpu-cores

설정 자체는 원하는 방향으로 가능해졌지만, docker volume (=osxfs) 관련은 앞으로 더 패치된 후에 성능이 나아지길 기대해야. 아니면 지금처럼 build 디렉터리를 docker volume 외부에 두는 식으로 해야할 것 같다;;;

요약

  • GUI 는 Mac에서, 개발툴은 linux 에서 이용하는 (내가 생각하는) 이상적인 휴대 작업 환경이 가능해 짐
  • boot2docker 등과 달리 정식으로 docker volume 을 지원하고, OSX 에서 직접 hypervisor 를 제어하는건 좋음 (메모리, 디스크, …)
  • osxfs 를 이용한 docker volume 의 성능 문제는 개선되지 않으면 못 쓸 정도

프로그래머의 일상: 험난한 python 패키징

제목처럼 거창한 건 아니지만.

웹 페이지에서 JSON web token (jwt) 를 쓸 일이 있어서 pyjwt 를 가져다 쓰기 시작했다. 근데 이걸 서비스 중인 vm들에 배포하려면 .deb 패키지로 묶어야 한다. Python 라이브러리를 .deb (간단하게) 패키징 할 때는 python-stdeb 패키지를 이용해서 간단히 묶어 버리고 있다 – 이건 기회가 되면 나중에 설명할 일이 있었으면 한다.

하지만 문제 발생:

$ python setup.py  --command-packages=stdeb.command bdist_deb
...
Traceback (most recent call last):
  File "setup.py", line 77, in 
    'jwt = jwt.__main__:main'
  File "/usr/lib/python2.7/distutils/core.py", line 151, in setup
    dist.run_commands()
  File "/usr/lib/python2.7/distutils/dist.py", line 953, in run_commands
    self.run_command(cmd)
  File "/usr/lib/python2.7/distutils/dist.py", line 972, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.7/dist-packages/stdeb/command/bdist_deb.py", line 23, in run
    self.run_command('sdist_dsc')
  File "/usr/lib/python2.7/distutils/cmd.py", line 326, in run_command
    self.distribution.run_command(command)
  File "/usr/lib/python2.7/distutils/dist.py", line 972, in run_command
    cmd_obj.run()
  File "/usr/lib/python2.7/dist-packages/stdeb/command/sdist_dsc.py", line 139, in run
    remove_expanded_source_dir=self.remove_expanded_source_dir,
  File "/usr/lib/python2.7/dist-packages/stdeb/util.py", line 1061, in build_dsc
    -- %(maintainer)s  %(date822)s\n"""%debinfo.__dict__)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3: ordinal not in range(128)

문제의 원인이 좀 어이 없었는데 – 달력을 확인한다면 데미지 두 배,

  • 저자 이름에 non-ascii 문자가 포함되어 있고 (저자의 이름이 José)
  • stdeb 에서 문자열 치환할 때 이 처리를 하지 않고 있는 것

해당 버그는 아직 처리 중인듯.

그래서 문제를 우회할 방법이 두 가진데,

  1. stdeb 버그를 수정한다; 이 경우엔 저 위의 오류난 곳의 __dict__ 의 unicode 타입인 걸 하나 하나 찾아서 encode('utf-8') 하는 것
  2. 문제를 부정한다 (?): …이러면 안될 것 같지만 저자 이름을 수정

일단 2로 우회했는데 – stdeb 도 우분투 패키지라 이걸 덮어쓰게 배포하기가 찜찜해서 – 외부에 배포할 일이 생기거나 하면 결국 1안으로 가야할 듯 하다. 혹은 더 복잡한 다른 패키지 .deb로 만들 때 처럼 debian 파일들을 다 만들거나.

요약 (?)

  • Python 모듈을 .deb 로 변환하는 python-stdeb 패키지가 있다.
  • 근데 이 패키지가 unicode 를 제대로 못 다루는 부분이 있다.
  • 엄한 우회책은 있지만 매우 괴롭다. 지금 2016년인데…

2015 년, 내 프로그래밍 언어는 …

2014 년, 내 프로그래밍 언어는 … 에 이어서.

작년 한 해 동안 주로 사용한 언어는,

  • C++ (제한적인 C++1x,y,z)
  • Python
  • …과 거의 비등한 양의 shell script (거의 bash 지만)

회사에서 만들고 있는 게임 서버 엔진 (+ 이걸로 만드는 게임 서버 혹은 게임 서버 개발 지원) 으로 거의 C++ 만 쓰고 지낸 듯 하다. 그래도 엔진 자체만 빼고는 C++11 이후를 써도 되서 꽤 편하게 짠 듯.

Python은 대략 이전에도 썼던 log 분석, 웹 서비스 stub 등에서 많이 썼고, bash 는 패키징 (.deb, .rpm …) 할 때 주로 썼으니..

올해도 아마 C++을 제일 많이 쓰는 한 해가 될 것 같구만.

프로그래머의 일상: 어떤 디스크 풀

커널 보안 취약점 때문에 회사에서 쓰는 VM들을 패치하고 있는데, 디스크 풀이 뜬다.

?!?!?!?!

디스크 풀은 다른 방식으로 감지하고 있어서 대체 뭘까 하고 고민하다가, 같이 일하는 수원님이 “inode 풀 아니냐” 라고 하시기에,

$ df -i 
Filesystem Inodes IUsed IFree IUse% Mounted on 
/dev/xvda1 524288 517380 6908 99% / 
none 127041 2 127039 1% /sys/fs/cgroup 
udev 125746 388 125358 1% /dev 
tmpfs 127041 318 126723 1% /run 
none 127041 1 127040 1% /run/lock 
none 127041 1 127040 1% /run/shm 
none 127041 2 127039 1% /run/user

그것이 실제로 일어났습니다?

뭐가 이렇게 inode를 다 쓰고 있나 했더니 신경 안 썼던 리눅스 헤더 패키지 (linux-headers-{version}, linux-headers-{version}-generic) 가 inode를 다 쓰고 있더란;

$ find /usr/src/linux-headers-3.13.0-76-generic/ /usr/src/linux-headers-3.13.0-76 | wc -l
24813

버전마다 25k 정도 쓰고 있는데, 총 inode가 520k; 근데 헤더 패키지가 20개 깔려있더라.
dpkg -P 로 몇 개 헤더 패키지를 지우고 나니 설치가 정상적으로 설치가 된다.

세 줄 요약:

  • 디스크 풀은 디스크 용량이 아니라 inode가 모자라서 날 수도 있다.
  • df -h 말고 df -i 도 보자.
  • 리눅스 헤더 패키지 싸우자 (…주기적으로 obosolete 패키지를 제거합시다 (…))

Python 으로 JSON 빨리 처리하기

지난 며칠 동안 모 모바일 게임의 알파테스트가 있었다. 그리고 갑이 뽑아달라는 ad-hoc 통계를 뽑느라 로그 처리를 왕창 할 일이 있었다.

대략,

  • 로그 데이터는 하나의 JSON 문서로, 각 파일에 한 줄씩 차지하고 있다
  • 파일은 날짜 별로 쪼개져서 서버 로그 디렉터리에 남아있다

내부 테스트나 첫날 정도까지는 로그 처리가 순식간에 끝날 수준이라 (k초 수준; k < 10) 별로 신경 안 썼는데, 막상 데이터가 커지기 시작하니 오래 걸리기 시작.
(오래 걸린다 == 실행하고 결과 나올 때까지 걸리는 시간이 내 집중력이 유지되는 시간보다 길다)
그리고 ad-hoc 통계를 뽑으려다 보니 내가 실행하는 횟수가 계속 늘어서 걸리는 시간 줄이려고 삽질한 기록이 아래와 같다.

진행

대략 로그가 1 GiB 정도 쌓인 시점에서, 로그 처리를 완료하고 통계 데이터가 나올 때까지 55초 정도 걸리더라. (i7-2600 / 메모리 16 GiB / 샘숭 840pro)
일단 아래 두 가지로 급한 불은 껐고, 알파테스트가 끝나갈 때야 왜 빨라졌는지 알게 되었다.

일단 PyPy 를 끼얹어 본다.

메모리야 남아돌고, CPU가 100%로 튀는 상황이니 일단 PyPy 를 가져다가 써봤다.
Ubuntu 14.04 에는 PyPy 2.2.1 이 있다. 이걸 설치하고 동작하니 대략 33초까지 줄더라. (40% 향상)

최신 버전 릴리즈되는 PPA가 없나 검색해보니, 있더라: https://launchpad.net/~pypy.
여기서 PyPy 4.0.1을 가져다 쓰면 28초까지 실행 시간이 줄어들더라. (49% 향상)

mmap 도 끼얹어 봅니다.

이전에 하재승 군이 mmap 언급했던 게 생각나서 적용해보았다.
조금 더 빨라진다. 이젠 23초 수준.

여하튼 이 상태로 알파테스트 종료까지 갔더니 대략 로그 2GiB 처리하는데 53~55초 수준. 아마 처음 상태로 끝까지 갔으면 (끝나는 날 오후에도 갑이 통계 추가해달랬으니..) 내 멘탈은 더욱더 남아나지 않았을 듯 (…).

왜 빨라졌는가

왜 빨라졌는지 파악 하지 못하고 있었으니 측정해보자.
vmprof 프로파일러 를 붙여서 돌려봤다. (2:20 소요)

Python 2.7 실행 결과

loads 밑 그 하위 함수들 (decode, raw_decode) 들에서 잔뜩 시간을 쓰고 있다. 즉, 대부분의 시간을 JSON 디코딩하는데 쓰고 있다는 소리 (json.loads 함수라서)

PyPy 로 구동한건 다음과 같다. 0:55 소요.

PyPy 4.0.1 실행 결과

작은 루프를 계속해서 돌기 때문인지 대부분의 구간이 JIT 번역된 코드를 실행하고 있다. 여기서도 json.loads 호출의 비율이 크지만 Python 2.7 보다는 그 비율이 낮다.
왜 JSON 성능이 PyPy 쪽이 좋은지 확인해보니 PyPy 2.2.0 릴리즈 노트에 그런 내용이 있더란.

JSON decoding is now very fast (JSON encoding was already very fast)

근데 JSON 성능은 (보통은?) 외부 C library 에 의존해서 성능을 올린 경우가 많다. 그래서 전통의(?) simplejson 과 ujson 을 붙여서 테스트해봤다.
simplejson 으론 성능 향상이 없더라. (PyPy 의 경우 오히려 느려졌다)
C기반 JSON 구현체의 python 바인딩인 ujson 을 시도해봤다.

Python 2.7 + ujson 실행 결과

… ujson C 코드 디버깅 심볼이 없어서인지 제대로 프로파일링 안된 것 같긴한데, 같은 Python 2.7이면서도 시간은 대폭 줄었다. 1:19. (거의 절반)
그래도 통계 데이터를 실제로 해석하는 작은 루프들 성능이 JIT 쪽이 나은지 전체 시간은 여전히 PyPy 쪽이 더 좋다.

요약

  • vmprof 좋아요 씁시다.
  • Python 표준 라이브러리의 JSON은 너무 느리다. CPython을 써야한다면 ujson, 그게 아니면 PyPy 쓰자.

구글 두들에 나온 Hedy Lamarr 글을 읽고

며칠 전 구글 두들 (2015-11-09) 로 Hedy Lamarrs 라는 배우, 발명가인 여성에 대한 글을 읽었다. 트위터에 올라오는 것들 보다가 예전에 전공 과목 배울 때 내용이랑 섞여있는 게 있길레 간단히 정리.

흔히 약어로 쓰는 SS (spread spectrum), DS (direct sequence), FH (frequency hopping) 같은 걸 쓰고 있으니 참고해서 읽어주시길.

Hedy Lamarrs 와 FH

위키백과 항목에 따르면

Lamarr and Antheil realized that radio-controlled torpedoes, while important in the naval war, could easily be jammed, which caused the torpedo to go off course. With the knowledge she had gained about torpedoes from her first husband, and using a method similar to the way piano rolls work, they designed a frequency-hopping system that would continually change the radio signals sent to the torpedo.

즉, Lamarr 와 공동 발명자가 고안해 낸 것은 일종의 FHSS 시스템. Spread spectrum 방식 자체가 a. 전체 대역을 다 관찰하지 않고는 노이즈 플로어만 상승시키는 걸로 보이고 b. 특정 (좁은) 대역의 재밍으로는 통신을 재밍하기 어려운 장점 떄문에 풀려던 문제 (어뢰의 유도 신호를 재밍당하지 않게 하는 것) 에 적합하다는 것.

Wireless LAN, …

현재 사용하고 있는 무선랜 표준 (WLAN; 802.11) 과 발명 사이에 관계 있다는 설명글들이 쭉 올라오는데, 아주 거칠게 말하면 큰 관련은 없다 — 작게는 있다(?). 무선랜 대역인 2.4 GHz (다른 대역도 있지만) 에는 전자레인지가 동작 중인 경우 엄청난 양의 노이즈가 생기기 때문에 이를 피하기 위한 방법을 사용한다.

링크한 글에서도 얘기하지만 대부분의 사람이 경험해보지 못한 legacy 802.11 표준을 제외하곤 FHSS는 사용하지 않는다. (대부분의 경우 802.11b, g, n, ac 순서로 경험했으리라)
간단히 정리하자면

  • Legacy 802.11: DSSS or FHSS
  • 802.11a: OFDM
  • 802.11b: DSSS
  • 802.11g, ac: OFDM

그래서 (현재의) 무선랜 기술과 크게 관련있는 건 아니라고 적었던 것.

2G/3G 무선 통신

한국에서 사용하는 2G 무선 기술이 IS-95 인데 (혹은 그 이후의 IS-2000; 3G), 이 기술은 CDMA 를 써서 여러 사용자의 통신을 지원한다. 그리고 이 CMDA가 사용하는 방식이 DSSS.

GPS?

이건 왜지. P코드 때문이라고 하기엔 너무 먼데 (…….)

Bluetooth

이게 왜 안나왔는지는 정말 모르겠지만. Bluetooth 통신은 FHSS를 쓴다. 차라리 직접적으로 연관관계가 있는 이쪽을 위주로 정리해줬어도 좋았을지도.

음 그렇지만 FHSS도 spread-spectrum 자체가 맞기도하고, 넓은 대역에 pseudo-random number sequence를 써서 특정 형태의 재밍을 피할 수 있는 무선 통신 방식…을 생각하면 뭐 죄다 적용될 수는 있을지도?

nginx + ngx_pagespeed

꽤나 예전에 동아리 서버에는 적용해봤는데 — 동아리 서버는 apache 웹서버를 써서 구글에서 바이너리로 배포하는 mod_pagespeed 를 썼지만 — 이 블로그가 쓰는 웹 서버는 nginx를 써서 적용 못하고 있었다.
Nginx 는 다 좋은데 동적으로 로드 가능한 모듈을 지원하질 않아서 소스에 넣고 빌드해줘야하는 것. 개인 웹 서버라 개발툴 없이 돌리는 상태를 유지하고 싶어서 회사 개발머신을 빌려 데비안 패키지만 만들고 옮겨서 설치하는 것으로. 아래는 그 기록.

빌드 기록

빌드 과정은 소스에서 ngx_pagespeed 빌드하기 를 따라하되 nginx 소스코드와 빌드 자체는 ubuntu 14.04의 debian 빌드 스크립트를 이용했다.

소스 코드 얻기

nginx 소스 패키지와 ngx_pagespeed 소스 타르볼, 그리고 PSOL 타르볼을 얻는다:

# nginx (1.4.6) 소스코드 + 빌드스크립트
$ apt-get source nginx

# ngx_pagespeed 릴리즈 아카이브
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/release-1.9.32.10-beta.zip

# PSOL
$ wget https://dl.google.com/dl/page-speed/psol/1.9.32.10.tar.gz

# 압축 해제 및 필요한 구조로 변경
$ tar -zxf 1.9.32.10.tar.gz
$ unzip release-1.9.32.10-beta.zip

# PSOL 을 ngx_pagespeed 밑으로
$ mv psol/ ngx_pagespeed-release-1.9.32.10-beta/

# ngx_pagespeed 를 모듈 디렉터리로 이전
$ mv ngx_pagespeed-release-1.9.32.10-beta/ nginx-1.4.6/debian/modules/

nginx 빌드룰 수정

데비안 패키지의 빌드룰은 “{패키지-버전}/debian/rules” 에 있다. 여기선 nginx-1.4.6/debian/rules 를 열어 nginx-full 에 해당하는 config.status.full 항의 맨 뒤에 “--add-module=$(MODULESDIR)/ngx_pagespeed-release-1.9.32.10-beta \” 를 추가해서 아래와 같이 수정하다:

config.status.full: config.env.full
  cd $(BUILDDIR_full) && ./configure  \
      $(common_configure_flags) \
      --with-http_addition_module \
      --with-http_dav_module \
      --with-http_geoip_module \
      --with-http_gzip_static_module \
      --with-http_image_filter_module \
      --with-http_spdy_module \
      --with-http_sub_module \
      --with-http_xslt_module \
      --with-mail \
      --with-mail_ssl_module \
      --add-module=$(MODULESDIR)/nginx-auth-pam \
      --add-module=$(MODULESDIR)/nginx-dav-ext-module \
      --add-module=$(MODULESDIR)/nginx-echo \
      --add-module=$(MODULESDIR)/nginx-upstream-fair \
      --add-module=$(MODULESDIR)/ngx_http_substitutions_filter_module \
      --add-module=$(MODULESDIR)/ngx_pagespeed-release-1.9.32.10-beta \
            >$@

데비안 패키지 생성

$ cd nginx-1.4.6/
$ debuild -uc -us -rfakeroot -b
$ ls -1 ../*.deb
../nginx_1.4.6-1ubuntu3.3_all.deb
../nginx-common_1.4.6-1ubuntu3.3_all.deb
../nginx-core_1.4.6-1ubuntu3.3_amd64.deb
../nginx-core-dbg_1.4.6-1ubuntu3.3_amd64.deb
../nginx-doc_1.4.6-1ubuntu3.3_all.deb
../nginx-extras_1.4.6-1ubuntu3.3_amd64.deb
../nginx-extras-dbg_1.4.6-1ubuntu3.3_amd64.deb
../nginx-full_1.4.6-1ubuntu3.3_amd64.deb
../nginx-full-dbg_1.4.6-1ubuntu3.3_amd64.deb
../nginx-light_1.4.6-1ubuntu3.3_amd64.deb
../nginx-light-dbg_1.4.6-1ubuntu3.3_amd64.deb
../nginx-naxsi_1.4.6-1ubuntu3.3_amd64.deb
../nginx-naxsi-dbg_1.4.6-1ubuntu3.3_amd64.deb
../nginx-naxsi-ui_1.4.6-1ubuntu3.3_all.deb

…적당히 기다리고 나면 탑 디렉터리에 .deb 파일 수 개가 생긴다. 위에서 빌드 룰 수정한 nginx-full 패키지를 가져가서 서버에 설치.[1] 빌드 시간을 줄이고 싶다면 debian/control 을 수정하는 것도 (다음 번엔) 고려해야겠다.

설정하기

ngx_pagespeed : Nginx의 PageSpeed 모듈 :: Outsider’s Dev Story 를 참조해서 설정했다. 기본 값 + JavaScript 비동기 로딩 정도 설정함.

총평

Google PageSpeed Insight 점수가 15점 쯤 올랐다 (…). 행복하군 (야)
대신 앞으론 ubuntu 쪽 패키지 업데이트 / Google 쪽 릴리즈 마다 새로 빌드해야한다 (이쪽은 전혀 달갑지 않다…)

PS. (아마도) GPL인 debian/rules 파일을 일부 인용했는데, 이 글 라이센스를 CC-BY 대신 GFDL로 해야하나? 아니면 공정 사용이니 그냥 CC-BY 해도되나?(…)

  1. 빌드할 때 좀 괴롭더라. -j8 주니 빌드 실패한다. 빌드 스크립트에 무슨 삽질을 해놓은걸까? []

리뷰: 마션 – 리들리 스콧

2D로 보고 옴. 나쁘진 않았지만 — 영상만 보면 훌륭한 편이었고 — 맘에 썩 드느냐 하면 그건 아니라서 좀 아쉬운 영화.
원작 유지에 목 매는게 아니고, 볼거리도 많은 편인라면 볼만함. 특히 하드SF 류를 좋아한다면 더더욱 추천.

이하엔 원작 (마션 – 앤디 위어) 과 영화의 내용에 대한 스포일러가 포함되어있으니 주의

원작에서 워트니가 독백하는 부분이 많은데 대략,

  • 자신이 ㅈ 되었음에 대한 한탄
  • 그리고 이 상황에 대한 과학적 분석
  • 이런 계산이 되니까 가능은 하다

가 있고, 이거랑 대비되는 NASA 측 인물들의 생각이 나오는 부분이 있는데 이 부분 처리를 어떻게 하나했는데, 대부분을 지워버림. 뭐 영화적 허용이라고 하자 (…).

다만 사라진 주요 장면들이 있는데:

  • 접지 문제로 패스파인더 통신 모듈 날려버리는 부분
  • MAV를 향해 이동할 때 폭풍이 오고 이걸 어떻게 인지 하고 탈출 하는지에 관한 부분
  • 헤르메스 호 인원들이 지구를 이용한 sling-shot 할 때 가족들과 교신하는 부분이 있는데, 영화에선 아주 편리하게도 “실패하면 어쩌나”를 무시하고 지나감

난 이게 원작의 본질적인 테마랑 맞닿아 있다고 생각하는데 — 현실 인식 + 해결책 + 안되면 어떻게 해야하는가?
그래서 보는 내내 찝찝했음. 뭐 이 부분은 헐리웃 영화론 부적절했을지도.

마지막으로, 귀환 이후 부분은 왜 필요한거야? 원작에서 헤르메스 호에 도착하는 걸로 — 그리고 냄새 (…) 에 대한 동료들이 반응이 나오는 걸로 — 끝나는게 참 매력적이었는데; 굳이 저런 사족을 달 필요가 있었나 싶다.
짧지 않은 — 광고 포함 2:30쯤? — 상영 시간이었는데 원작을 어느 정도 담아내면서도 헐리웃화 했다는 면은 성공적일지도.