January 2012
5 posts
1 tag
몇년 전만 하더라도 웹 접근성이니 웹 표준이니 하면서 장애인과 함께 주요 시나리오로 예를 들었던 게 모바일 장비들이였는데, 이제는 상황이 역전되어 오히려 모바일 장비에서만 돌아가고 컴퓨터에서는 쓰지도 못하는 카카오톡이나 Path 같은 서비스들이 한가득 세계를 점령하게 되었다.
생각해보면 이 모든 것이 “접근성”(accessibility)을 소극적으로 해석해왔기 때문에 일어난 일들이 아닐까 하는 생각도 든다. 접근성을 프로그램 가능성(programability)까지 포함하는 것이라고 광의적으로 해석하는 Steve Yegge의 관점도 생각해 볼만한 화두인 것 같다.
3 tags
JSON will be a core type in PostgreSQL 9.2 →
JSON이 PostgreSQL 9.2의 기본 타입으로 들어간다. 이미 이전부터 xml, hstore 등의 타입을 가지고 있었기 때문에 예상된 수순이었지만 그럼에도 놀라운 소식. 이게 들어가면… 긴 말 필요 없고 HN에 누가 단 댓글을 인용해보자.
이게 표현식 색인과 함께 쓰이면 JSON 데이터를 저장할 수 있을 뿐만 아니라 JSON 안쪽에 들어있는 값들을 색인할 수도 있게 된다. 즉, 달리 얘기하자면, PostgreSQL의 성숙한 구현을 희생하지 않고 NoSQL 데이터 모델의 장점중 하나를 누릴 수 있게 된다.
2 tags
Heuristics
실제로는 아무런 관련이 없는 독립적인 사건일지라도, 시간적으로 비슷한 시기 혹은 공간적으로 비슷한 장소에서 연달아 일어나는 사건들에 대해 특별히 과학적 사고 방법을 훈련받지 않은 대개의 사람들은 인과적 관계가 있다는 느낌을 받는다. 예를 들어 어떤 음식을 먹고 나서 식중독에 걸렸으면, 그 음식이 잘못된 것이라는 믿음이 생기는데, 진실은 그것만으로는 알 수 없는 법이다. (훈련이라 함은 그런 느낌을 애써 무시하고 의심하는 습관을 만드는 것이라고 볼 수도 있다.) 이는 매우 흔한 인지적 오류인데, 그렇다고 이것만 보고서 인간의 모든 인지 능력이 비합리적이라고 결론지을 수도 없다. 그것이야 말로 부분만을 보고 전체를 규정하는 인지적 오류의 하나이다.
비슷한 시점에 사건이 연달아 일어나기만 해도 인과성을 느끼는...
3 tags
비동기 I/O 라이브러리 아이디어
요즘 gevent 등의 비동기 I/O 라이브러리들을 쓰면서 생각하고 있는 새 비동기 I/O 라이브러리 디자인 아이디어들이 있다. 일단 크게 두 라이브러리로부터 영감을 얻었다.
Twisted
Twisted가 오래됐는데도 불구하고 여러 부분에서 봤을 때 가장 잘 디자인되어 있다. Twisted가 다 잘해둔 것들을 오히려 나중에 가서 그보다 못하게 리엔지니어링하면 안된다.
gevent
코루틴을 이용하여 직렬적인 루틴은 CPS 없이 자연스럽게 쓸 수 있어야 한다. node.js처럼 하면 안된다.
이미 있던 것들과 전체적으로는 비슷하고, 중요한 부분만 적자면:
Python 2.5에서 들어온 강화된 제너레이터(enchanged generators)는 사실 코루틴이다. CPython, PyPy, Jython...
1 tag
세상이 망하려는지 딕셔너리 키에 문자열밖에 안 들어가고, 문자열과 배열 외에는 변변찮은 자료구조도 전혀 없으며, 반복에 관한 공통 인터페이스도 없고, 모듈 시스템도 없어서 저마다 각자의 패키지 라이브러리를 만들어서 쓰지만 결국 그 패키지 시스템 스스로는 불러올 수 없으므로 손으로 엮어야 하는, 약 5년 전까지 과소평가를 받았다고는 하지만 또 지금 보기에는 현대적인 언어라고 하기에는 어색한 부분이 많은, 내가 보기에는 현대의 어셈블리에 가까운 언어가 사람들 입에서 다음 세대의 언어라고 찬양받는 것을 보니 참 답답하다. 과연 말세다.
December 2011
7 posts
2 tags
Twitter 어디선가 “혁신은 기술에서 나오는 것이 아니라 생각의 전환에서 온다”는 얘기를 보았다. 굉장히 부당한 주장이라는 생각이 들었다. 마치 기술은 사람의 생각이 아니라는 것 같다. 사실 딱 그런 소리다. 어째서 기술은 사고의 한 과정, 방식이 될 수 없는가?
기술은 사람의 생각이다. 기술의 발전은 모두 사고의 전환이다. 기술도 치열한 사고의 과정이다!
기술이 생각이 아니라고 당연스레 여기는 것은 추상화된 것들을 피상적으로만 접하고 그것의 숨겨진 진실에 관심이 없는 사람들의 흔한 착각이다. 하지만 사람이 이뤄낸 것들 가운데 사람의 생각이 아닌 것이 없다. 그런 사람들에게 기술은 사람이 이뤄낸 것이 아니라 하늘에서 뚝 떨어진 신탁 기계 같은 것이다.1
원래 도시에서만 산 사람들은 물을 기는...
1 tag
프로그래밍도 어느 정도 그런 게 있긴 하지만, 디자인은 특히 심한 것이, 눈으로 보이는 분야다 보니 비전문가도 자신이 어느 정도 디자인을 보는 눈이 있다고, 혹은 나름대로 공부한 영역이라고, 아니면 그 이상으로 자신이 전문가 수준의 견해가 있다고 착각하기 쉬울 것 같다.
디자인 작업을 하고 싶어하는 사람은 아무도 없지만, 다들 한 다리씩 걸쳐서 훈수를 해주고 싶어서 입이 근질근질 해지는 것이 바로 디자인이다.
디자이너들 일하기 참 힘들겠다. 디자인 전공도 안한 클라이언트, 상사, 주변 동료들이 디자인 좀 안다고 착각하면서 훈수 두는 것들 일일히 하나씩 다 디펜스하면서 작업 결과까지 내려면.
(그래도 프로그래밍은 그런 면에서 꽤나 다행이다. 이것도 눈에 보이는 프론트엔드 쪽은 비슷한 면이 많지만,...
2 tags
서베이와 뉴스의 중요성
빨리 만드려면 올바름을 놓아야 한다. 올바르게 만드려면 느림을 감수해야 한다. 빠르면서 올바르게 만들기 위해서는 이미 올바르게 구현한 것을 갖다 쓰는 것밖에 답이 없다. 이미 올바르게 구현한 것이 무엇이 있고 그걸 어떻게 써야 “올바르게” 쓰는 것인지 학습하기 위해서는 시간이 걸린다. 빠른 시간 안에 학습할 필요 없이 올바른 것을 갖다 쓰려면 평소에 그런 것들이 뭐가 있는지 알아둬야 한다. 결국 평소에 좋은 뉴스 소스1를 확보하고 꾸준히 모니터링하는 것이 중요하다. 평소에 해둔 서베이가 생산성과 품질에 주는 영향은 매우 크다. 하지만 그러한 혜택을 누리는 당사자들 외에는 누구도 그러한 것의 중요성을 깨닫지 못하며, 이렇게 글로 쓴다 해도 와닿는 법이 없다.
소프트웨어 마에스트로 멘티들이나 학교 후배들이...
3 tags
StyleShare Engineering Blog →
이번에 StyleShare에서 엔지니어링 블로그를 시작했다.
반갑습니다. 스타일쉐어 개발팀이 엔지니어링 블로그를 시작합니다!
위의 동영상은 스타일쉐어 서비스 메인 레파지토리의 Code Swarm입니다. 각각의 큰 아이콘들은 저희 팀의 개발자이고, 이리저리 돌아다니며 뭉치는 여러 파편들은 저희 프로젝트 코드의 변화를 의미합니다. 역사가 짧은 스타일쉐어 팀이지만 그 사이에 많은 작업이 있었답니다.
스타일쉐어 개발팀이 서비스를 만들면서 접할 다양하고 유익한 정보들과 재미있는 이슈들을 앞으로는 이곳에서 여러분과 공유하려 합니다.
패션 트렌드는 스타일쉐어에서, 스타트업 엔지니어링 트렌드는 바로 이곳에서 확인하세요.
StyleShare’s GitHub에서 저희 팀의...
2 tags
Thoughts on Python 3 →
Flask, Werkzeug, Jinja2 등을 만든 Armin Ronacher가 블로그에 Python 3에 대한 생각을 올렸다. 급진적인 주장은 별로 없고 뭐 다들 알만한 사람들은 아는 내용이지만 전체적으로 잘 정리되어 있으니 관심 있는 사람들은 전문을 읽어보면 되겠다. 여기에는 개인적으로 인상깊었던 부분만 인용해보겠다.
“Always complaining, not doing anything”. There is just so much stuff I would love to see Python go but at the end of the day, I’m a user of Python more than a developer.
세상에 Python 사용자는 많지만 Python 언어 구현을...
3 tags
Membase Server as Memcached
Membase Server를 memcached 대신 쓰기로 했다. Membase Server는 memcached 호환 프로토콜을 사용하기 때문에 memcached를 가정하고 만든 애플리케이션을 고치지 않고도 적용할 수 있다. 사용하려는 환경은 Ubuntu이므로 .deb 바이너리를 내려받는다. (커뮤니티 에디션 다운로드)
$ wget http://packages.couchbase.com/releases/1.7.1.1/membase-server-community_x86_64_1.7.1.1.deb
설치할 때는 의존성도 함께 설치해준다.
$ sudo dpkg -i membase-server-community_x86_64_1.7.1.1.deb
$ sudo apt-get -f install
...
누가 퍼뜨린 얘기인지는 모르겠지만, 가만 보면 사람들은 무엇에 대해 설명을 잘 하지 못하고 어렵게 말하는 것을 그 자신도 제대로 이해하지 못해서라고 굳게 믿는 것 같다. 하지만 골똘히 생각해보면 자신이 무엇을 이해하는 것과 그것을 말로 잘 표현해서 전달하는 것은 전혀 다른 종류의 능력이다. 그렇지 않다면 세상 모든 교수들과 전문가들이 Steve Jobs만큼 발표를 잘할 것이고 인기 소설가들처럼 그것을 잘 전달할 수 있었을 것이다. 양자역학을 일반인들에게 쉽게 설명할 능력이 없다고 해서 결코 모든 물리학자들의 양자역학에 대한 이해가 떨어진다고 볼 수는 없을 것이다.
반대로 생각해보자. 불교 선종(禪宗)에서는 불립문자(不立文字)라 하였다. 높은 수준의 이해는 말로 전할 수 없다. 스스로 궁리하여 깨달아야...
November 2011
4 posts
2 tags
AWS 한국 사용자 모임
…같은 건 없고, 그냥 비공식이지만 한국에서 Amazon Web Services 쓰는 사람들끼리 정보 공유를 하자는 의미로 IRC 채널을 작게 만들었다. (내가 만든 건 아니고 kkung 님이 시작.) 오징어 네트워크의 #aws 채널이다.
irc://irc.ozinger.org/aws
신생 언어 홍보 아이디어
밤 늦게 불현듯 떠오른 아이디어. IRC 봇 프레임워크를 아주 사용하기 좋게 만든 다음 Google App Engine처럼 PaaS로 제공하면 어떨까? 대신 그 프레임워크는 홍보하려는 언어로 만들어져 있고, 해당 PaaS에 자신이 원하는 봇을 올려서 운영하려면, 그 봇을 해당 언어로 스크립팅해야 한다.
미션 크리티컬한 서비스의 경우 이렇게 하면 PaaS가 망하겠지만, IRC 봇은 대부분 있으면 재밌고 좋지만 없어도 그만인 물건이기 때문에 오히려 직접 호스팅하는 쪽이 번거롭도 신경도 쓰이게 된다. 그런 것들을 그냥 PaaS에 올려서 디플로이도 쉽고 라이브에서 디버깅도 쉽게 해주면 각자 채널에서 소규모로 특수 목적 봇을 만드는 비용을 낮춰주기 때문에 많이 쓰이지 않을까? 설사 생소한 언어로 스크립팅해야...
8 tags
Celery + Amazon SQS 실패기
StyleShare1에서는 우선순위 큐(priority queue)가 필요해서 초기에 Celery를 쓰지 않고 직접 구현한 큐와 워커를 사용했다. 하지만 큐의 안정성이 떨어져서 우선순위 기능을 포기하고 RabbitMQ와 Celery를 쓰기로 결정했다.
사실 처음에는 Celery와 Amazon SQS를 쓸 예정이었다. StyleShare 인프라는 현재 Amazon Web Services 위에 구축되어 있고, AWS에 해당 용도의 서비스가 존재한다면 그걸 우선적으로 쓰는 걸 고려하고 있다. 예를 들어 우리는 L4를 직접 구축할 생각을 버리고 ELB를 쓰고 있고, 3개월 정도 지난 현재, 결과적으로는 좋은 선택이었다. 그런 의미에서 큐 역시 직접 구현하지 않고 SQS를 사용하는 쪽을 먼저 고려했던 것이다.
...
2 tags
세상에는 화장실에서 변기 물을 내리지 않는 사람들도 많다. 따라서 파일이나 소켓을 열고서 닫지 않는다거나 메모리를 할당한 뒤에 해제하지 않는 일들이야 뻔하게 예상할 수 있는 것들이다.
화장실 변기 청결 유지의 해결책은 아무도 읽지 않는 안내문이 아니라 센서를 달아 자동화하는 것이듯, 리소스 누수의 해결책은 “실수하지 않기”가 아니라 RAII1와 GC로 자동화하는 것이다.
C#의 using, Python의 with, Java 7에 추가된 try-with-resources 문 같은 것. ↩
October 2011
5 posts
1 tag
신생 언어로 웹 프레임워크를 만들 때 짜야할 것들
아예 새로 나온 언어 X에서 웹 프레임워크를 만드려면 짜야할 것들이 뭐가 있을까? 기반 라이브러리가 거의 없을테니 구현해야할 것이 많다. 개인적으로 나중에 쓰려고 만들어본 체크리스트.
웹 서버 게이트웨이 인터페이스
Python의 WSGI, Java의 Servlet, Ruby의 Rack 참고. 놓치면 안될 것은, WSGI는 그 자체로 사용자가 직접 쓰기 위한 인터페이스가 아니라, 웹 프레임워크와 웹 서버 사이의 통신을 위한 로우 레벨 인터페이스라는 것이다. 이걸 구현하기 위해 언어 기본 타입 이외의 자료 구조/클래스 따위가 필요하다면 별로 좋은 디자인이 아니다. 사용성을 고려하지 말고 이식성과 여러 웹 서버 디자인에 agnostic한 일반성을 중요하게 고려할 것. 세상 모든 웹 서버가 Apache...
2 tags
기호(記號)란 공학적으로 말하면 일종의 캐시(cache) 같은 것이다. 기호화된다는 것은 해당 개념의 히트율이 높아 캐시되는 것으로 볼 수 있다. 하지만 기호 역시 원본이 사라졌음에도 캐시와 마찬가지로 무효화(invalidation)되지 않고 잔상이 남는 경우가 있다. 플로피 디스켓은 사라졌으되, 소프트웨어의 저장 아이콘은 여전하다.
실제로 일어나는 모든 일은 물리적인 현상이다. 물리적이라는 말 자체에 실제로 존재한다는 뜻이 들어있기 때문이다. 태어나서 말을 하고 고뇌하며 사랑을 하기도 하고 주변 사람의 죽음에 숙연해하는 일들 모두가 우리에게 실제로 일어나는 것들이고, 그러므로 물리적 현상이다. 다만 중요한 것은 그 모든 것들이 물리적인 현상이라고 해서 생명의 소중함이나 숭고함, 죽음의 무게감 따위가 조금이라도 가벼워지는 것은 아니라는 점이다.
그런 의미에서 사람의 마음이 영적인 것이라고 말한다면, 인공지능 역시 영적인 것이라고 말할 수 있어야 한다. 실제로 존재하는 것에 대해 영적이라 말하는 것은 더이상 그것이 비물리적이라는 뜻이 아니며, 기실 아무런 뜻도 없는 공허한 말에 불과하기 때문이다. 만약 영적이라는 말이 비물리적이라는...
Art of Dalinaum: 어떤 하드웨어 →
어떤 하드웨어가 있다.
코어 i-3 2100, 4G 메모리, GTS540 1GB 그래픽 카드, 500GB의 하드디스크, 화면 사이즈는 벤더가 생각한 가정에 가장 적합한(?) 사이즈 21인치 모니터로 고정된다.
이태리 디자이너가 만든 멋있는 디자인의 하드웨어와 몇년간 심혈을 기울여 만든 운영체제가 설치되었다고 한다.
애플리케이션은 하나씩 밖에 못 띄우는 환경 마켓을 통해서만 앱을 받아야 하는 환경. 자신이 어떠한 애플리케이션도 만들 수 없다.
과연 이 제품을 200만원에 사겠는가?
나는 사지 않을 것이다. 하지만 대부분 사람들은 살만하다고 여길 것이다. 왜 그럴까?
화면 사이즈는 벤더가 생각한 가정에 가장 적합한(?) 사이즈 21인치...
1 tag
Steve Jobs
너도 나도 해대는 한마디 중 하나가 될 얘기지만, Steve Jobs의 타계(他界)1는 나에게도 여러가지 생각을 들게 만든다. 할아버지는 내가 태어났을 적, 혹은 그 이전부터 Macintosh 사용자셨다. 초등학생 때 Bill Gates의 위인전과 함게 Steve Jobs의 위인전을 읽었던 기억이 난다. 중학교 졸업 선물로 할아버지께 받은 PowerBook G4가 떠오른다. 그때 당신께서는 호빵처럼 생긴 iMac G4를 함께 구입하셨었다. 그 이후로 계속 Mac을 써온 것 같다. 그러면서 Apple의 철학에 동조하는 부분도 생기고 나쁘다고 생각하는 부분도 많이 생겼다. 하지만 나쁜 점이 있다고 좋은 점이 의미 없어지는 것은 아니다.
Steve Jobs의 업적이 다시금 화자되고 있는 가운데, 개인적으로...
September 2011
8 posts
4 tags
두번째는 아마존의 웹킷 선택이다. 모바일 브라우저의 대다수를 차지하고 있는 웹킷을 선택함으로서 완전한 대세로 자리매김하게 될 예정이다. 모바일에서 또 다른 오픈소스 렌더링 엔진을 배포하고 있는 Mozilla의 입장에서는 조금 아쉬운 대목일수도…
—클라우드 브라우저의 탄생
사실상 WebKit이 웹 브라우저 렌더링 엔진 세계를 지배한 지는 이미 오래되었다. 이렇게 된 데에는 이유가 다 있다. Gecko 엔진을 WebKit처럼 쉽게 붙일 수는 없다. Mozilla Firefox는 좋은 소프트웨어 제품이지만, Gecko 엔진만 따로 제품처럼 쓰기는 상대적으로 까다롭다. 반면 WebKit은 매우 쉽게 붙일 수 있게 되어 있다. 엔진 자체만으로 하나의 완결된 소프트웨어 제품이다. Gecko와...
3 tags
Brad Cox가 처음 Objective-C를 만드려고 한 이유는 사실 흔한 두 가지 미신에 기초한 것이 아닐까.
Smalltalk가 좀 섞이면 “진정한” 객체 지향 프로그래밍이 가능할 거라는 생각.
C가 섞이면 성능이 좀 빠를 거라는 생각.
어찌됐든 21세기인 지금에 와서도 Objective-C에 여전히 네임스페이스가 없는 이유는 어차피 C에도 없고 Smalltalk에도 없기 때문이다.
5 tags
Python에서 + 연산자를 더하는 용도로도 쓰고 연결(concatenation)하는 용도로도 쓴다. 비단 Python만 그런 것이 아니라 Ruby나 Java도 비슷하다. 나는 이것이 잘못된 디자인 선택이라고 본다. 둘은 엄연히 다른 연산의 추상화이고, 맞는 방향은 Haskell처럼 둘을 나누는 것이다. (Haskell에서 연결은 ++ 연산자를 쓴다.)
tuple을 상속 받아 Point와 Size 타입을 만들면서 Point(1, 2) + Size(3, 4)가 Point(4, 6)을 반환하게 만들려는데 (1, 2) + (3, 4)가 (1, 2, 3, 4)를 반환하는 tuple의 시멘틱을 깨야하는 문제에 봉착해서 든 생각.
3 tags
2 tags
소스 코드의 컬럼(폭)을 80자로 제한하는 것은 줄의 끝 부분 공간을 쓰지 못하게 만든다. 소스 코드에서 하드탭을 쓰고 그 폭을 전통적인 8자로 강제하는 것은 줄의 첫 부분 공간을 쓰지 못하게 만든다. 둘 모두 너무 깊은 들여쓰기를 하지 못하게 하는 효과를 갖는다는 점에서 동등한 제약이다. 둘 모두 들여쓰기가 깊어질 경우 새로운 함수를 만들도록 심리적 압력을 준다. 혼자 보는 소스 코드는 어떻든 상관 없지만 여럿이 보는 코드, 특히 오픈 소스 같은 경우 이런 낡고 오래된 관습이 약간이나마 평균적인 maintainability를 양호하게 만들기도 한다. 아직도 Linux 커널 소스 코드에서 하드탭 폭을 8자로 강제하거나, 많은 오픈 소스 프로젝트들이 컬럼을 80자에서 100자 정도로 제한하는 데에는 그런...
8 tags
오랜만에 갑자기 Warcraft III의 아기자기한 그래픽이 그리워서 Battle.net에 들어가서 인스톨러를 받았다. (Blizzard는 언제부터인가 Battle.net에 과거 자신이 샀던 씨디키를 등록하면 물리적인 패키지를 잃어버려도 Battle.net에서 인스톨러를 다운로드 받아서 게임을 할 수 있도록 해두었다.)
Warcraft III가 출시되었을 당시는 Mac이 Intel 프로세서를 쓰기 전이다. 그 때는 IBM에서 생산하던 PowerPC 프로세서를 사용했고, Mac OS X Tiger에 와서 양쪽 프로세서에서 모두 동작하는 하이브리드 바이너리로 컴파일하는 기능을 Xcode에 추가했다. 그 이후에 개발된 애플리케이션들은 양쪽 모두에서 동작하나, 그 이전에 출시된 Warcraft III는...
14 tags
개인적으로 템플릿 엔진 역사상 큰 전환점을 가져다 주었다고 꼽는 아이디어가 두 개 있다.
첫번째는 Kid1가 제안한 템플릿 상속 및 블럭 개념. 그 전까지 웹 개발의 템플릿 작업은 어떻게 잘 템플릿을 쪼개서 인클루드할 것이가, 정도의 개념에서 벗어나지 못하고 있었는데, Kid가 제안한 템플릿 상속 아이디어는 템플릿 엔진 설계에 있어서 IoC에 해당하는 것이었다. 결국 Kid 자체는 XML 기반이라는 불편함과2 썩 빠르지 않은 구현 덕분에 망했지만, 템플릿 상속이라는 아이디어 자체는 워낙 훌륭해서 Django 템플릿에도 이어지게 되고, Django가 성공하면서 최근의 템플릿 엔진은 모두 상속 기능을 지니게 되었다.
두번째는 문자열 치환을 잘 하자는 기존의 모든 템플릿 엔진이 고수하던 근본적인 방식을...
2 tags
WTForms는 입력 폼을 만들어주는 라이브러리이다. 폼을 선언적인 스타일로 정의하면 HTML도 만들어주고 유효성 검사도 해주는 식이다. 이걸 써서 회원 정보 수정 양식을 만들었는데, 일부 사용자가 이메일 필드에 ' hong@minhee.com '과 같이 끝에 공백을 실수로 입력하는 일이 일어났다. 입력 받은 문자열을 trim하는 방법을 찾아봤지만 현재로서는 그런 옵션이 없는 것 같다. 그래서 필드 타입을 ad-hoc하게 확장하는 함수를 만들었다.
import wtforms.fields
def Trimming(field_cls):
"""Makes a subclass of the given ``field_cls``, must be a subtype
of...
August 2011
6 posts
1 tag
회사에서 쓰는 코드를 훌륭한 오픈 소스 소프트웨어를 만들어서 릴리즈하는 것은 앞으로 그 회사의 직원이 될 사람들에게 가르쳐야 할 레거시 코드를 선행 학습시키는 것으로 볼 수도 있다. 단, 그 오픈 소스 소프트웨어가 정말 크게 성공해야 하지만.
4 tags
3 tags
Markdown Extra API →
글을 쓰다보면 바닐라 Markdown 그대로 쓰기보다는 테이블이나 각주 같은 것들 때문에 확장 스펙인 Markdown Extra를 쓰게 되는데,1 이 확장 스펙을 제안한 Michel Fortin이 직접 만든 레퍼런스 구현 비슷한 것이 PHP Markdown Extra이다. 그런데 Markdown이 여러 구현이 많지만 이 확장 스펙의 모든 기능을 제대로 구현한 것은 아직 PHP Markdown Extra 말고는 없다. 그래서 나처럼 확장 스펙의 모든 기능을 많이 활용하는 사람은 다른 구현을 쓰다보면 불편함을 느낀다. 하지만 이것 하나 때문에 모든 웹 애플리케이션을 PHP로 만들 수는 없는 노릇이라, 이번에 그냥 HTTP로 요청하면 결과를 던져주는 API로 만들었다. 개인적으로 Google App Engine...
3 tags
Linesman →
Linesman은 WSGI 프로파일러 미들웨어다. 일반적인 WSGI 미들웨어처럼 사용하면 된다. 만약 Flask를 쓰고 있다면,
from linesman.middleware import make_linesman_middleware
app.wsgi_app = make_linesman_middleware(app.wsgi_app)
같이 쓰면 된다.
프로파일러는 /__profiler__에 접근하면 볼 수 있는데, 이 경로 자체는 미들웨어에서 다음과 같이 설정이 가능하다.
app.wsgi_app = make_linesman_middleware(app.wsgi_app, profiler_path='/linesman')
Linesman은 호출 그래프도 보여주는데, 내부적으로 Graphviz의 dot...
3 tags
From Celery to gevent
내부적으로 만들어서 사용하는 빌드봇이 있다. Bitbucket 커밋 훅에 걸어놓고 쓰는 건데, 커밋했을 때마다 IRC 채널에 알려주는 일과 커밋 로그에 이슈 번호가 언급되었을 경우 해당 이슈에 코멘트로 커밋 로그를 링크해주는 일을 한다.
커밋 훅 인터페이스가 HTTP POST로 작동하는 일반적인 WebHook인데 지금까지는 요청을 받으면 Celery에 태스크를 던져놓고 Celery가 백그라운드에서 IRC에도 노티하고 이슈트래커에도 코멘트를 남기는 식으로 만들어뒀었다. 이 빌드봇은 ep.io에 올려놓고 있는데, 이상하게 어제부터 ep.io에서 Celery beat 프로세스가 작동하지 않길래 삽질하다가 그냥 Celery 쓰는 것을 포기하고 gevent로 spawn하도록 바꿨다. 간단한 프로그램이라...
July 2011
3 posts
1 tag
sqlalchemy-migrate의 문제점
SQLAlchemy는 자체적인 스키마 마이그레이션 도구를 제공하지 않는다. SQLAlchemy 최고의 단점인데 1.0 아니라고 지금까지 조금도 제공하지 않고 있다.
대신 sqlalchemy-migrate라는 확장 도구가 사실상의 표준 마이그레이션 도구로 널리 사용되고 있는데, 나 역시 별 수 없이 이걸 쓰고 있다. 하지만 실무에서 사용하기에는 여러가지 크고 작은 문제점이 존재한다. 그 가운데 치명적인 몇 가지 문제점만 나열해 보겠다.
마이그레이션 과정에 트랜잭션을 걸지 않아서 원자적으로 작동하지 않는다. 당연히 원자적으로 작동할 거라고 기대하고 별 생각 없이 마이그레이션 스크립트를 짰다가는 데이터에 눈에 쉽게 띄지도 않는 비정합 오류가 실무에서 생길 수 있다. 꼭 실무가 아니더라도 개발 환경에서도...
3 tags
Python Compatibility Table
이 글은 2011년 7월 10일에 작성된 글이다. 2011년 8월 21일 현재 PyPy의 최신 버전은 1.6이며 좀더 추천해줄만한 구현이 되었다.
(tl;dr: CPython 2.7.2나 PyPy 1.5 쓰세요.)
Ver \ Impl
CPython
PyPy
Jython
IronPython
Stackless Python
2.5
CPython 2.5.6
PyPy 1.4
Jython 2.5.2
IronPython 2.0.3
Stackless Python 2.5.5
2.6
CPython 2.6.7
IronPython 2.6.1
Stackless Python 2.6.5
2.7
CPython 2.7.2
PyPy 1.5
Stackless...
1 tag
Lisp 언어를 배우는 가장 좋은 방법은 Lisp을 구현해보는 것이다. 다른 언어와 달리 Lisp은 얼마든지 간소화해서 구현할 수 있기 때문이다. Python을 배우는 가장 좋은 방법이 Python을 구현해보는 것은 아니지만,1 적어도 Lisp은 그렇다.
물론 Miguel de Icaza처럼 C# 컴파일러 구현을 하며 C# 언어에 입문하는 경우도 있지만 정말 예외적인 경우. ↩
June 2011
4 posts
4 tags
6 tags
Polymorphism, multimethods and notations
90년대에 (그리고 지금까지도) 프로그래머들 사이에서 가장 성공했던 사기1 중 하나는 이른바 OOP일 것이다. OOP가 무엇일까? 사람들이 OOP의 근본적인(fundamental)한 특성과 우연한(incidental) 특성을 함께 생각하는 경우가 많은데, 장담하건대 OOP는 언어 차원에서 암시적으로 구현한 타입 쿼리(type query)이다. 그리고 우리는 이걸 다형성(polymorphism)이라고 부른다.
다형성은 메서드 호출시 특정한 인자에 대해 발생하는데, 그 특정한 인자를 Smalltalk 등에서는 리시버(receiver)라고 부른다. 예를 들어 array at: 0에서 array가 바로 리시버다. Java 등으로 치면 object.method(a, b)에서 object가 리시버다. 대개...
The best thing about mathematical jokes is left as an exercise for the reader.
– pozorvlak (via prolol)
There is a lot to this essay, but it is still primarily remembered for one...
– http://news.ycombinator.com/item?id=2628284
May 2011
3 posts
3 tags
Hacker Entropy
모든 IT 기업에는 (내가 임의로 이름지은) 해커1 엔트로피(hacker entropy) 법칙이 적용되는 듯하다. 일단 해커라는 족속의 특징을 나열해보자.
해커는 가만히 있어도 쉽게 업무에서 지루함2을 찾아낸다.
해커는 자신이 생각하기에 멍청하게 여겨지는 업무를 하기를 싫어한다.
해커는 멍청한 사람이나 그런 사람과의 협업을 싫어한다.
해커는 멍청한 사람이 만들어놓은 한뭉텅이의 멍청하고 깨지기 쉬운(fragile) 코드더미를 싫어한다.
따라서 해커는 매우 빠른 속도로 자신이 속한 회사에 정을 떨어뜨리고 회사의 모든 시스템이 잘못된 레거시라고 여기게 된다. 그리고 대부분의 경우 그건 사회적인 이유로 개선 불가능하다고 결론짓는다. 그래서 회사를 나가거나 자신의 능력을 전혀 발휘하지 않게 된다.
이는...
2 tags
Jeff Hawkins의 “On Intelligence”(생각하는 뇌, 생각하는 기계)에는 다음과 같은 구절이 나온다.
하지만 언어는 어떤 특별한 언어 전용 도구를 상정하지 않아도 언어–예측 모형에 잘 들어맞는다.
선율, 자동차, 집이 그렇듯이, 말과 글도 그저 세계에 있는 패턴일 뿐이다.
언어의 구문론과 의미론은 다른 일상적인 대상들의 계층 구조와 다르지 않다.
나는 이 주장에 동의하지 않는데, 다른 인지적 기능들과 마찬가지로, 언어 역시 단순히 “일반 목적 지능”(general-purpose intelligence)이 발달하면 자연히 발생되는 것이 아니라, 이를 위해 설계된 인지 기관이 존재해야 한다고 생각하기 때문이다.1 방대한 데이터를 입력하면 자연스럽게 필요한 인지 기능이...
1 tag
PyPy가 CPython보다 빠를 수 있는 이유
PyPy 1.5가 나왔다. Python 프로그래머에게 있어서 이번 릴리즈의 가장 큰 의의는 아마 Python 2.7.1 호환성을 제공한다는 데에 있을 것이다. (이전 버전은 2.5 호환성을 제공했다. 반년도 안되어서 2.5 → 2.7.1로 호환성을 올린 것이니 참으로 괴물 같은 개발 속도라 할 수 있다.)
해외에서도 그렇고 LangDev 채널에서도 그렇고 PyPy에 관한 가장 흔한 질문은 이것이다: PyPy는 Python으로 Python을 구현한 건데 어떻게 CPython보다 빠르다는 겁니까?
이것은 매우 자연스러운 질문이다. 비유하자면 가상 머신 안에서 돌아가는 프로그램이 실제 물리적인 컴퓨터에서 바로 실행되는 프로그램보다 빠르다는 얘기와 비슷한 소리 아닌가? 쉽게 생각하면 말이 안되는 이야기다....
April 2011
4 posts
네이버 웹툰 RSS →
http://navercomicfeed.ep.io/
네이버 만화는 RSS를 제공하지 않는다. 그래서 네이버 웹툰 RSS를 만들었다. 네이버 만화에 올라온 모든 웹툰, 베스트도전, 도전 만화를 RSS로 볼 수 있다. 물론 네이버의 허락을 받고 만든 것은 아니다. 그래서 언제 망할지 모르는데, 그걸 대비해 서비스 웹 애플리케이션 자체는 AGPL로 소스 코드를 함께 공개했다. (그러니까 망하더라도 소스 코드 가져다가 직접 돌려서 쓰면 된다.)
https://bitbucket.org/dahlia/navercomicfeed
서버를 부담하기 싫어 Python 클라우드 웹 호스팅 서비스1인 ep.io에 올렸는데 외국 서버라 많이 느리다. 꿍 님이 그래서 본인 서버에 미러링 서비스2를 제공하고 있는데,...
2 tags
Startup Nihilism
최근 개인적인 사건 몇가지를 겪으면서 나는 스타트업 허무주의에 빠진 것 같다. 스타트업 그딴건 부질 없고 도박 같은 투기 행위나 다름없지 않나 하는 생각이다. 도박과 마찬가지로 스타트업 역시 희망에 중독되어 포기하지 못하게 되는 그런 것이 아닐까. 불과 반년 전까지만 해도 이런 생각을 혐오했던 기억이 나는데 역시 앞날은 장담할 수 없다. 그래도 내가 언제까지나 이 허무주의에 빠져있을 것 같지는 않다는 사실 정도가 다행이랄까.
그리고 아드레날린이 넘치는 스타트업 현장에서 한발짝 물러나 스타트업을 하는 다른 사람들을 부러워하며 여러가지 생각을 했다. 그리고 요즘에 느끼는 바가 있었는데…
과연 스타트업 파운더는 좋은 리더여야 할까?
나는 지금까지 별 고민 없이 그렇다고 생각해왔다. 그런데 최근 들어...
포인터를 선언하는 방법의 차이
dalinaum-kr:
materiality:
loveholy:
“애스터리스크를 타입에 붙여 쓰는 사람(ex. int* aPointer)은 이 변수가 포인터타입 변수라고 생각하는 사람이고, 변수 이름에 붙여 쓰는 사람(ex. int *aPointer)은 이 변수가 해당 타입이되 포인터라고 생각하는 사람입니다.”
— Cyrus.H
나는 원래 개념적으로 전자가 맞다고 생각하는데 C/C++ 문법의 한계 때문에 후자처럼 쓰는 부류다. 이를테면 int* a, b;와 같은 경우. 아무 생각 없이 이렇게 썼다가 피 볼 확률이 0이 아니니까.
가끔 차라리 ...
...
March 2011
1 post
3 tags
sqlalchemy.ext.hybrid →
곧 정식 버전이 출시될 SQLAlchemy 0.7에는 sqlalchemy.ext.hybrid라는 이름의 재밌는 (그리고 매우 똑똑해서 놀라운!) 기능이 들어간다. 링크된 문서를 보면 자세한 것을 볼 수 있는데, 대략 다음과 같은 것들이 가능하다: (링크한 문서에서 인용)
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
from sqlalchemy.orm import mapper, Session, aliased
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
...