[npm] publish 하기 전에 테스트하기

npm publish 라는 명령어를 통해 내가 만든 라이브러리를 npm 을 통해 배포할 수 있다. 보통의 경우라면 문제없다. 하지만 TypeScript 나 CoffeeScript 를 이용하여 컴파일된 라이브러리를 배포하거나, webpack 같은 것을 이용해서 라이브러리들을 패킹해서 배포할 경우 npm publish 를 하는 것은 마음 놓고 할 수 있는 작업이 아니다. 배포 전에 명령어를 수행하기 위해 prepublish에 스크립트 를 저장하거나, npmignore 에 배포하지 않을 파일들을 추가하거나 하는데, 이런 것들이 제대로 되어 있는지 실제 npm에 올리기 전에는 알 수 없기 때문이다. 그럴 때 사용하기 좋은 커맨드가 npm pack 이다. npm pack 을 이용하면, 제대로 된 파일들을 배포할지 확인할 수 있다. npm pack 을 실행하면 prepublish를 실행시키고, npmignore에 들어있는 파일들이 빠진 파일들이 {라이브러리 이름}-{버젼}.tgz 라는 이름의 압축파일이 만들어진다. 그러면 해당 라이브러리를 사용하는 프로젝트를 만들고, npm install {압축파일 경로} 를 실행하면, 실제로 publish된 라이브러리를 설치한 것처럼 라이브러리를 설치하여 테스트할 수 있다.

[Python] Gil과 Python

지난번 에 언급했듯이 CPython 이나 PyPy 는 Global interpreter lock (a.k.a. GIL)을 이용해서 동시에 2개 이상의 스레드가 실행되지 못하게 함으로써 스레드 간 동기화를 보장한다. 하지만 이는 CPython과 PyPy가 thread를 구현하는 방법일 뿐, Python 스펙에는 동시에 2개 이상의 스레드를 실행시키지 말라거나, GIL을 사용하라거나 하는 말은 없다. 그저 CPython과 PyPy가 효율성을 떨어뜨리더라도 GIL을 사용하는 것이 이득이 되는 것이 많다고 생각해서 GIL을 사용하도록 구현한 것뿐이다. 그래서 Python 구현체 중에서 .net framework 위에서 돌아가는 Iron Python 이나 JVM 위에서 올라가는 Jython 의 경우 GIL을 사용하지 않는다.

sfuture - JavaScript에서 concurrent한 프로그램 작성하기

sfuture 는 JavaScript에서 사용할 수 있는 컨커런트한 프로그램을 쉽게 작성할 수 있도록 도와주는 라이브러리다. 이름에서 알 수 있듯이, Scala의 Future를 JavaScript로 포팅한 것으로, 내부적으로 ECMA Script 6 promise를 사용하고 있어서, promise가 구현된 환경(node.js 0.12.0 이상, 대부분의 모던 브라우저)에서는 아무런 디펜던시 없이 바로 사용할 수 있다. 만들게 된 이유는, 전에 rhino engine 을 이용해서 Scala로 작성한 beyond 라는 게임 서버 엔진이 있었는데, 여러 가지 문제가 있어서 이것을 node.js로 포팅하게 되면서 필요하게 되었다. Rhino를 사용할 때는 Java class를 그대로 재사용할 수 있었기에 인터페이스만 수정하는 수준이면 가능했는데, node.js로 포팅해오면서 그럴 수 없게 되었다. 처음에는 Future를 포팅해올지, async등 기존의 라이브러리들을 이용하도록 할지 고민했다. 하지만 async를 실제로 사용을 해보니, 이것도 결국 콜백 헬을 없앨 수 있는 건 아니고, 오히려 코드가 길어질수록, 가독성만 떨어뜨리는 느낌이라서 결국 새로 구현하였다. 구현은 타입스크립트로 되어 있지만, publish 전에 컴파일하여 자바스크립트 파일만 배포한다. 원본 소스를 보고 싶으면, 깃헙 리파지토리 를 보길 바란다.

타입스크립트의 단점

지난번 글 에서 너무 타입스크립트를 사용하면서 얻게 되는 장점만 말한 것 같아서 이번 글에서는 타입스크립트를 사용하면서 맞게 되는 단점들을 말해보도록 하겠다. 타입스크립트의 단점은 명확하다. 타입스크립트와 자바스크립트를 섞어서 쓸 수 있다는 점이다. 타입스크립트로 컴파일한 코드는 자바스크립트가 되기 때문에 타입스크립트로 작성한 모듈을 자바스크립트에서 불러올 수 있다. 하지만 이렇게 사용한다면, 지난번 글에서 말한 타입스크립트를 사용하는 장점 중 하나인 타입 체크를 위한 verbose 한 코드를 작성하지 않아도 되는 장점이 사라진다. 자바스크립트에서 사용될 것을 가정하고 코드를 작성할 경우는 여전히 verbose 한 타입 체크 코드를 작성해야 한다. 이것은 내가 자바스크립트 코드를 타입스크립트를 포팅하면서 딱히 좋은 점을 느끼지 못했던 이유 이기도 하다. 하지만 이는 자바스크립트를 사용했다면 언제나 발생했을 문제가 타입스크립트를 사용할 때 다시 발생하는 것뿐이다. 자바스크립트를 사용해야 하는 환경에서 타입스크립트를 사용하지 않을 이유는 되지 않는다. 이번에는 반대로 타입스크립트를 사용하면서 자바스크립트로 작성된 모듈을 불러오는 경우를 보자. 타입스크립트에서는 자바스크립트의 모듈을 그대로 가져다 쓸 수 있다. 덕분에 타입스크립트 생태계는 크게 노력하지 않고 자바스크립트의 생태계를 흡수할 수 있었다. 하지만 이것은 동시에 단점이 되기도 한다. 자바스크립트로 작성된 모듈은 타입 추론을 할 수 없어서 모든 API가 any 타입이 되고, 결국 이 부분이 unsafe 한 부분이 되기 때문이다. 이런 문제를 해결할 수 있도록 타입스크립트는 모듈의 타입만 분리해서 선언하는 선언 파일을 사용할 수 있게 해놓았다. 선언 파일과 함께 사용하면 자바스크립트로 작성된 모듈을 사용할 때도 잘못된 타입을 사용하면 타입 에러를 내준다. 물론 선언 파일을 만드는 것도 비용이다. 하지만 이는 큰 문제가 되지 않는다. 유명한 라이브러리에 대해서는 이미 DefinitelyTyped

TypeScript와 함께 한 4개월

내가 타입스크립트 를 처음 쓰게 된 것은 올해 3월이었다. 당시에 알바를 하고 있던 회사에서 작성하던 서버 사이드 자바스크립트 코드의 안정성을 향상하기 위해 타입스크립트로 포팅하는 일을 시작하였고, 당시 그 팀의 구성원은 전원 너무 바빴기 때문에 다른 일을 하던 내가 불려가서 포팅하게 되었다. 사실 처음에 포팅을 하기로 했을 때는 흥미로운 일이라고 생각하지만, 딱히 의미 있는 일이라고는 생각하지 않았었다. 당시 코드는 이미 뼈대에 해당하는 부분이 대부분 완성되어 있었고, 그 대부분은 이미 타입의 개념이 없이 짜인 코드였었다. 그래서 단순히 타입스크립트로 옮겨도 별 이득이 없을 것이고, 완벽하게 포팅하는데 들어가는 노력에 대비해서 안정성을 확보할 수 있을지에 대해 확신이 없어서였다. 그래도 돈을 받고 하기로 한 일이었으므로 작업은 시작하였다. 우선 이미 구현되어있는 코드가 너무 많았기 때문에 초반에는 손에 닿는 파일부터 타입스크립트로 변환하며 작업을 하였다. 그 뒤로 한 3개월은 코드를 바꾸는 일만 했다. 하지만 이때까지는 타입스크립트의 장점을 딱히 느낄 수 없었다. 변환하는 과정에서 몇몇 버그를 잡았지만, 이미 타입이 중요한 부분은 underscore.js 를 이용해서 타입체크를 하고 있었기에 타입스크립트가 추가로 해주는 일이 거의 없었다. 변환하는 과정에서 몇몇 버그를 발견하기는 했지만, 충분한 유닛 테스트로 잡을 수 있는 버그들이었기에 딱히 타입스크립트를 사용해야 한다고 느끼지 못했다. 오히려 리팩토링에 너무 많은 시간이 들었기 때문에 비용 대비 효용이라는 측면에서 비효율적이라고 느꼈다. 그러다가 타입스크립트에 대한 인식이 바뀌게 된 것은 다음 프로젝트를 시작하면서부터였다. 다음 프로젝트를 시작하게 된 것은 지난 5월 말이었으니 거의 한 달 정도 전이다. 하게 된 일은 기존의 스칼라 로 작성되었던 beyond 프레임워크 를 node.js 에서 돌도록 포팅한 beyond.ts 를 만드는 것이었는데, 이번 프로젝트는 처음부터 타입스크립트를 이용

변하지 않아도 되는 코드는 죽은 코드 뿐이다.

내가 병특을 시작했던 회사에서 있었던 일이다. 그 회사는 그냥 흔한 SI 회사였는데 덕분에 코드 퀄리티는 크게 보장할 수 없었다. 정말이지 많은 것이 나를 괴롭혔지만, 그중에서 나를 가장 괴롭혔던 건 옛날에 작성되어 관리 안 되는 코드들이었다. 그 회사는 SI 회사답게 유지보수라는 명목으로 몇 년 전에 팔았던 프로젝트의 유지보수라는 이름으로 고정 수익을 벌고 있었는데, 그중에서 가장 심한 건 10년 전에 작성되었던 프로젝트도 있었다. 그 날도 여전히 그 코드에 괴롭힘당하고 있었다. 내가 괴로워하고 있으니 당시 내 사수였던 개발자 J 가 와서 한마디 해줬었다. 너무 그러지 마. 이거 그래도 네 학교 선배 K 가 병특할때 짰던 코드야. 조금씩 변경된 부분이 있지만 대부분 네 선배가 짠 거야. 위로의 말이었는지, 괴로워하는 거 티 내지 말라는 의미였는지 나는 모른다. 내가 아는 것은 그저 이게 내가 퇴사를 결심하게 된 계기가 되었다는 것이다. 어째서 저 말이 그렇게 내 마음을 흔드는 말이 되었을까? 당시에 K 가 퇴사한 건 거의 10년 가까이 된 일이었다. 즉, 저 코드는 작성된 지 거의 10년이 된 코드라는 것이다. 거기에 유지 보수하면서 추가된 기능 외에 큰 틀은 전혀 건드리지 않았었다는 것이다. 뭐 J 는 10년이 지날 만큼 안정적으로 작성된 코드라고 말하고 싶었을지도 모르겠다. 하지만 10년을 변하지 않은 코드가 좋은 코드일 리가 없다. 지난 10년간 프로그래밍 도구는 많은 발전이 있었다. 단적으로 생각해봐서 2003년에 visual studio 6.0으로 코드를 작성하는 것과 2013년에 visual studio 2013으로 코드를 작성하는 것을 생각해보자. 아무도 2013 대신 6.0을 선택할 사람은 없을 것이다. 10년이라는 시간은 이 정도의 발전을 가지고 왔다. 도구뿐이 아니다. 개발 방법론, 설계법, 분석법 모든 측면에서 지난 10년간 많은 발전이 있었다. 즉, 10년 전에 좋은 코드였다고 하더라도 지금 기준에서 좋은 코드라는 보장

[MySQL] Replication (3) - Replication을 사용하는 이유

이미지
지난번 글에서 MySQL replication이 무엇 인지 설명하면서, replication은 cluster와 다르게 동기화되는 것을 기다리지 않아도 돼서 빠르므로, 실시간 동기화가 필요하지 않은 경우에 사용된다고 하였다. 그렇다면 실시간 동기화가 필요 없는 경우는 어떤 경우들이 있을까? 이번 글에서는 MySQL이 추천하는 적절한 replication 사용 방법에 대해서 알아보도록 하겠다. 백업 replication의 주목적은 데이터를 백업하는 것이다. MySQL은 데이터의 지속성 을 보장해준다. 하지만 아쉽게도 데이터베이스 이외의 다양한 이유(e.g. 하드디스크)로 데이터베이스를 복구할 수 없게 되는 일이 있다. 이런 경우를 대비하여, 다른 컴퓨터에 데이터를 복사하여 마스터 데이터를 복구할 수 없으면 복사된 슬레이브의 데이터를 이용하여 데이터를 복구할 수 있게 한다. 아카이브 단순 백업을 위해서 뿐 아니라 아카이브를 만들기 위해서도 replication이 사용된다. mysqldump를 이용하면 데이터를 복사하여 아카이브를 만들 수 있다. 하지만 쿼리를 수행 중인 데이터베이스에 mysqldump를 실행하면, 깨진 데이터가 들어올 수 있다. 이는 MySQL enterprise backup을 이용하면 해결할 수 있지만, replication을 이용해서 해결할 수도 있다. 지난번 글 에서 설명하였듯이, 슬레이브의 SQL thread를 정지시키면, 마스터의 데이터를 읽어와서 relay log를 만들지만, 데이터베이스는 업데이트하지 않는다. 따라서 SQL thread만 정지시켜 놓으면, 안전하게 mysqldump를 실행할 수 있다. 이를 이용하여 서비스 중인 데이터베이스의 데이터를 서비스를 중지시키지 않고 아카이브를 만들기 위해서 replication을 사용하기도 한다. 부하 분산 서버별로 다른 슬레이브에서 값을 읽게 한다 혹은 쿼리를 분산시키기 위한 목적으로도 사용된다. 대부분의 웹 서비스는 데이터의 변경에 비해서 데이터를 읽는 작업이 많다.

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

RAII는 무엇인가

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API