2012년 11월 23일 금요일

Meteor에서 file API를 사용한 upload 방법

https://gist.github.com/4132544
코드는 이쪽에.

Meteor.saveFile = (file)->
  fileReader = new FileReader()
  fileReader.onload = (blob) ->
    Meteor.call 'saveFile',
      file:file
      blob:blob.srcElement.result
  fileReader.readAsBinaryString file
  return
# event for upload
_.extend Tempalte.something,
  events:
    'change input[name=attach]': (e)->
      _.each e.srcElement.files, (file) ->
        Meteor.saveFile file

클라이언트에서 FileReader 객체를 생성하고 onload 시 파일속성과 바이너리를 인자로 Call을 해준다. submit을 타지 않고 Call을 사용하여 직접 전송한다는 점에 주목.

app=__meteor_bootstrap__.app
  fs=__meteor_bootstrap__.require 'fs'
  app.stack.unshift
    route: '',
    handle: (req, res, next)->
      Fiber(->
        unless /upload\/\/*/gi.test req.url
          next()
        else
          res.write fs.readFileSync("#{process.cwd()}/server/tests/upload/images/#{req.url.replace('/upload/','')}")
          res.end()
      ).run()
  Meteor.methods
    saveFile: (param)->
      if param.file.type.indexOf('image')+1
        Fiber(->
          fs.writeFileSync "#{process.cwd()}/server/tests/upload/images/#{param.file.name}",param.blob,'binary'
        ).run()

Meteor.methods부분 : 서버쪽에서 saveFile이란 method를 받으면서
file이름과 바이너리를 받아 파일 쓰기를 한다.
이때 경로는 tests 경로 아래로 두는데 프로젝트 디렉토리가 아닌 곳으로 해줘도 상관없지만
프로젝트 디렉토리 아래 업로드할 파일을 적재할 경우
Meteor가 파일 생성 여부를 스캔하여 어플리케이션을 재시작하는 것을 방지하기 위해
예외 디렉토리인 tests 를 사용한다.

이렇게 저장한 업로드 파일은 /public 디렉토리 아래에 있지 않아 직접 링크를 전달할 수 없다.

Routing 부분 : __meteor_bootstrap__.app 객체로부터 stack에 request 처리를 직접해준다.
route 를 '' 로 할 경우 모든 요청에 대한 처리를 할 수 있으므로 이를 사용한다.
그러면 handle에서 request별 처리를 할 수 있는데
우리는 /upload/xxxxx 형태의 요청에 대해서만 처리하고 나머지는 next()를 사용해 포워딩해주기로 한다.
해당 형식의 URL 요청을 받을 경우 methods 에서 저장한 디렉토리 경로를 붙여서 response 에 write 해준다.

서버 사이드에서 파일을 읽거나 쓸때 병목을 방지하기 위해서 깨알 Fiber를 붙여줌.
readFileSync 나 writeFileSync 대신 readFile / writeFile 을 써서 callback으로 처리해도 되지만 예외처리 등등 귀찮기도 하고 meteor 디자인 가이드에서 CPS 스타일을 참아달라는 부탁이 있어서 Fiber + Sync 로 구현.

이런 건 뭐 메뉴얼에도 없고 검색도 안되니 소스를 뒤져보는 수밖에.
누군가 보고 '이렇게 하는게 더 나아요'라고 제시해줬으면 싶지만 현재로는 이게 제일 맘에 든다.

2012년 11월 21일 수요일

play.node() 노드 컨퍼런스 코리아 종료.

우여곡절은 있었지만 발표도 잘 했고 재밌는 것들도 많이 들었고 나름 의미 있는 것들을 몇몇 건졌다고 생각한다.
Isaac(node.js 원년멤버.풀타임 node.js 개발자이지 npm을 만든 장본인)은 생각보다 아니 생각대로 싱거운 사람이었다.
몇몇 질답이 오갔는데 다 그가 알고 있거나 우리들이 아는 뻔한 이야기의 범주를 벗어나지 못했달까.
밀도의 차이는 있지만 우리랑 별로 다르지 않구나라는 안도감도 약간.

매끄럽지 못한 부분도 있었지만 1회 치곤 괜찮았고 네이버 행사장도 꽤 좋았음. 앞으로도 계속 이런 행사 유지했으면 한다.
근데 솔까 스피커/오거나이저한테 뭔가 좀 더 현실적인 보상이 있었으면
자봉문화(?)가 못마땅하달까. 뭐만 하면 다 자봉이야. 이런 거 애들이 배워서 나중에 "우리도 열정을 가지고 공짜로 했으니 너희들도 당연히 그래야지"라고 말하는 꼰대가 될까봐 후덜덜.
스폰서들이 쓰는 비용 전체에 비하면 적은 투자인데 반해 그들은 열성적인 홍보자라서 고효율 아닌가?
컨퍼런스를 무료로 하는 것이 컨퍼런스의 질을 떨어뜨린다고 생각한다면 스텝에 대해서도 마찬가지라고 생각.

오전 세션을 사정상 참여않아 못봤는데 해외 스피커들에게 영어로 질문하는 사람들이 있었다고 한다.
당연히 이런 거 사전에 미리 제재하고 명확한 의미 전달을 위해 한국어로 질문하게 하고 전문 분야의 지식과 한국어의 의미를 잘 파악하는 전문 번역자가 통역하게 해야한다.

그나저나 우리도 뭔가 언어나 프레임워크 같은 거 만들어서 전문 통역자(당연히 현지에서 준비해주는)끼고 한국말로 연설하는 전세계 투어 같은 거 하면 정말 재밌겠네.

마무리로 Isaac 하고 찍은 사진이랑 인증 샷들 몇개 투척.







2012년 11월 17일 토요일

Unicode 2.0 에서 한글의 이해

요즘 SNS이나 SNG등등 기계적으로 문장을 생성하는 프로그램들이 넘쳐나는 시대에 의외로 한글처리를 제대로는 프로그램들이 드물구나 하는 생각에 간단한 한글 자소 분석기를 만들어보았다.
링크는 이쪽(http://jsbin.com/ofoqal/10/edit)

애초에 만든 목적은 다음과 같다.
조사처리(은/는, 이/가, 을/를 등등)를 위해 단어의 마지막 글자의 종성을 조사하기 위함인데 예문을 들어보자면

"준기 강남에서 사진 찍었다."
"예슬 홍대에서 식사 했다."
"슬기 대화방에서 나갔습니다."

"준기님은 강남에서 사진님을 찍으셨습니다 고갱님" 이라고 말하면 할말 없다.

한국식 소프트웨어(꼭 소프트웨어가 아니더라도)의 특징이자 장점이 무엇이냐라고 물으면
귀찮을 정도로 깨알같은 디테일이라고 대답할텐데 한글 기계화 작업에 대한 중요성은 프로그램을 만드는 사람들에게도 별로 중요하게 다가오지 않나보다.

에또 사설이 길었다.
한때 우리는 한글코드체계의 비표준 숲속에서 너무도 괴로운 나날들을 보낸 역사가 있다.
KSC5601부터 시작해서 Microsoft통합형한글을 지나 Unicode 2.0의 시대가 왔다.

개인적으로 UTF-8을 사용하지 않고 EUC-KR이나 CP949를 쓰는 제품이나 서비스의 업체의 대표/관계자에게 1억 미만의 벌금 혹은 3년 이하의 금고형의 실형을 내려줬으면 할 정도로 너무나 많은 사람들을 불행하게 하고 막대한 비용을 지출한 악의 근원이라고 생각한다.

하지만 광명이 왔다.
기계적으로 납득이 가능한 검색 및 정렬이 용이한 Unicode 의 시대가 열렸단 말이다.
지금 당신이 복사해서 붙이고 있는 팁들 보다 훨씬 쉽고 명쾌하니 다음 그림을 한번 보자.
어떤가?
무쟈게 쉽지 않은가?

현대 한글은 초성 19자, 중성 21자, 종성 27자로. 총 19 x 21 x 28 (종성없음 포함) = 11172자 되겠습니다.
빈값이 없이 빽빽하게 들어찼단 말이다.

초성은 ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ (19자)
중성은 ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ(21자)
종성은 (없음)ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ(28자)

이것 밖에 없다.
교ㅑ
  ㄱ
이런거 안된단 말이다.

자 지금 당장 javascript console을 열고 이렇게 쳐보자.
저 대로라면 한글의 가장 첫번째 글자는 무엇일까?
당연 '가' 되겠다.

> '가'.charCodeAt().toString(16).toUpperCase()
"AC00"

그렇다. 이게 시작이다. 0xAC00. 10진수로 44032.
그럼 '문' 이건 어떻게 될까?
초성인 'ㅁ'이 6번째
중성인 'ㅜ'이 13번째
종성인 'ㄴ'이 4번째 되시겠다.
44032+6*21*28+13*28+4 = 47928 인거다.

> String.fromCharCode('가'.charCodeAt() + 6*21*28 + 13*28 + 4 )
"문"

아름답다. 아름다와.
같은 방법으로 초중종을 분리해보자.

47928(문)-44032(가)=3896 이니
3896 을 기준으로

초성 Math.floor(3896/21/28) = 6(ㅁ)
중성 Math.floor((3896 - 6*21*28)/28)=Math.floor(3896/28-6*21) = 13(ㅜ)
종성 3896 % 28 = 4(ㄴ)

이게 전부다. 코드도 그냥 이것대로 한거고.
애초에 초반에 말했던 을/를, 이/가 등의 조사를 구분하는 함수를 만든다면 어떨까?

var hasJongsung = function(word) {
  return !!(word && word[word.length -1].charCodeAt()>=0xAC00 && word[word.length -1].charCodeAt()<=0xD7A3 && (word[word.length -1].charCodeAt()-0xAC00)%28);
};

그저 이렇게 한 줄 코드로 해결할 수 있다.
종성이 있을 경우 true를
종성이 없거나 한글이 아닐 경우 false를 반환한다.

지금 만들고 있는 프로그램에도 한번 적용해보자. 고기덕후세종대왕느님들이 고생해서 만든 글인데 아깝지 않은가?

2012년 11월 2일 금요일

meteorite package에 d3.js를 올렸다.

http://meteor.com/authcast 를 보면서
벡터그래픽을 마치 DOM처럼 쓰는 게 너무 맘에 들어서 https://atmosphere.meteor.com/ 에 올려야겠다는 생각이 들었음.

https://gist.github.com/3327056 와 https://atmosphere.meteor.com/wtf/package
내용 참조해서 https://github.com/acidsound/d3js-package 이런걸 올리긴 했는데

submodule 을 처음 써봐서 삽질 좀 했다.
js 라이브러리의 경로를 잘못써서 몇가지를 수정하고 올리려고 했더니

/usr/local/lib/node_modules/meteorite/lib/atmosphere.js:82
          throw "This tag has already been committed to the repo.";
          ^
This tag has already been committed to the repo.
이런 오류가 나서 소스를 열어보았다.



80      exec('git tag', function (err, stdout, stderr) {
81        if (stdout.indexOf(versionName) >= 0)
82          throw "This tag has already been committed to the repo.";

versionName 이 뭔가 쫓아가보았더니 smart.json 에서 지정한 "version".
뭐 암튼 release 할때 "version" 키의 값에 "v"를 앞에 붙여서 tag를 만들기 때문에
git tag -d "v<해당버전이름>" 해서 지우고 다시 하니 잘되더라.
내 경우엔 git tag -d v0.5.0 했음.

어 근데 메인 패키지에 d3 가 있네?
근데 지우는 방법을 모르겠네. 소스 지우는 부분이 딱히 없구만;
두고두고 창피할 거리가 하나 생겼네. 다음에 잘하면 되지뭐.

제 1회 Node.js Korea Conference 에 나갑니다.

http://nodeconf.kr/2012/
자세한 내용은 이쪽 참고하시고

저는 Meteor Tutorial 세션을 진행합니다만 연습해보니 시간 맞추기가 만만치 않네요.
Node.js의 코어 커미터와 컨트리뷰터들이 오전 세션을 엽니다. 엄청난 섭외력!

Isaac Z. Schlueter / Joyent - npm을 만드신 분이고 node.js 코어 커미터입니다.
Michael Rogers Node.js contributor and community Organizer - 죄송합니다. (_ _) 누군지 모르겠습니다.
Charlie Robbins / Nodejitsu - Joyent 와 쌍벽을 이루는 node.js 호스팅 서비스 회사인 Nodejitsu의 대표죠.

두근두근 합니다.
흥해라 Node.js!