중첩된.오브젝트.프로퍼티.가져오기.성공적 = getobject 

TypeError: Cannot read property ‘..’ of undefined 는 매우 흔히 발생하고 오랫동안 개발자를 괴롭혀온 에러다.

이 에러는 오브젝트의 프로퍼티에 접근하려 하는데 그 오브젝트가 undefined 인 경우 발생한다. 즉, 아래 같은 상황이다.

> var opt = {};
undefined
> opt.a.b.c.d
TypeError: Cannot read property 'b' of undefined
...
> 

특히 API 연동처럼 외부에서 생성된 오브젝트를 가져와 사용할 때 프로퍼티가 누락되면 자주 만나게 된다. 특히 스키마가 없는 NoSQL 데이터베이스를 사용하는 경우에 자주 만나는 오류이기도 하다.

그래서 여러가지 방법으로 돌파를 시도하는데, 변하지 않는건 단계가 깊어질 수록 조건문이 길어진다는 것이다. 커피스크립트 등에서는 ?. 이라는 존재연산자(existential operator)를 지원하고, JavaScript 완벽가이드에도 비슷한 코드가 수록되어 있다.

이렇게 중첩된 프로퍼티들을 조건문을 사용하지 않고 가져올 수 있다면 꽤 편리할텐데 이런 기능을 가진 패키지를 찾았다. 바로 Ben Alman 이 만든 getobject 이다. Ben Alman 은 Gruntjs 의 최초작성자이기도 하다. 이 패키지는 Gruntjs 에도 포함되어 있다. (사실은 이 패키지를 Gruntjs 코드를 살펴보다 알게되었다.)

패키지는 NodeJS 에서 사용할 수 있는 node-getobject 와 jquery 및 클라이언트쪽 자바스크립트에서 사용할 수 있는 jquery-getobject 패키지 두가지 이다. jquery-getobject 라는 프로젝트 명을 가지고 있긴 하지만 jquery 를 사용하지 않는 경우도 이 패키지를 사용할 수 있다.

node-getobject

먼저 node 쪽의 node-getobject 를 살펴보자. 프로젝트 홈은 http://github.com/cowboy/node-getobject 이다.

설치

npm install getobject

사용법

getobject.get(object, parts, create);

중첩된 프로퍼티에서 값을 편리하게 가져온다. 값이 없는 경우에는 undefined 를 리턴한다.

  • obj 는 대상이 되는 오브젝트이다.
  • parts 는 오브젝트 내에 접근하는 중첩된 키들을 문자열로 적는다. 예를들어 opts.a.b.c 를 가져오고 싶다면 ‘a.b.c’ 로 적는 식이다.
  • create 은 parts 에 접근하는과정에 undefined 를 만나는 경우 이들을 생성할지 설정하는 옵션이다.

 getobject.set(obj, parts, value);

중첩된 프로퍼티에 값을 적는다.

  • obj 는 대상이 되는 오브젝트이다.
  • parts 는 오브젝트 내에 접근하는 중첩된 키들을 문자열로 적는다. .get 에서의 parts 와 같다.
  • value 는 적을 값이다.

getobject.exists(obj, parts);

중첩된 프로퍼티에 값이 존재하는지 검사한다.

예제

var getobject = require(‘getobject’);
var opt = {};
getobject.get(opt, ‘a.b.c.d.e’, true);
typeof getoject.get(opt, ‘a.b.c.d’);  // object
getobject.set(opt, ‘a.b.c.d.e’, ‘hello');
getobject.get(opt, ‘a.b.c.d.e’); // hello

jquery-getobject

프로젝트 홈은 http://github.com/cowboy/jquery-getobject 이다.

클라이언트측 자바스크립트에서의 사용법은 Node 에서의 사용과는 조금 다르다.

jQuery 를 사용중이라면 jQuery 내의 메서드처럼 동작하고 없는 경우에는 window.Cowboy 라는 객체 아래에 메서드들이 위치한다.

즉, window.jQuery.getObject(),window.jQuery.setObject() (물론, window.jQuery 는 $ 로 줄여쓰는 경우가 많다.) 이거나 window.Cowboy.getObject(), window.Cowboy.setObject() 가 된다.

사용법

$.getObject(parts, create, obj);

중첩된 프로퍼티에서 값을 편리하게 가져온다. 값이 없는 경우에는 undefined 를 리턴한다.

  • parts 는 오브젝트 내에 접근하는 중첩된 키들을 문자열로 적는다. 예를들어 opts.a.b.c 를 가져오고 싶다면 ‘a.b.c’ 로 적는 식이다.
  • create 은 parts 에 접근하는과정에 undefined 를 만나는 경우 이들을 생성할지 설정하는 옵션이다.
  • obj 는 대상이 되는 오브젝트이다.

$.setObject(name, value, context);

중첩된 프로퍼티에 값을 적는 메서드이다.

  • parts 는 오브젝트 내에 접근하는 중첩된 키들을 문자열로 적는다. .getObject 에서의 parts 와 같다.
  • value 는 적을 값이다.
  • context 는 대상이 되는 오브젝트이다. context 는 생략가능하고, 생략한 경우 window 객체에서 찾아내려간다.

$.exists(parts, obj)

중첩된 프로퍼티에 값이 존재하는지 검사한다.

예제

jQuery 를 사용 중인경우

window.$ === window.jQuery; //true
var opt = {};
$.getObject('a.b.c.d.e', true, opt); //undefined 
$.setObject('a.b.c.d.e', 'hello', opt);

jQuery 를 사용하지 않는경우

window.Cowboy.getObject('a.b.c.d.e', true, opt); //undefined        
window.Cowboy.setObject('a.b.c.d.e', 'hello', opt);
Growth Hacking Cover Image

스타트업, 제품 시장 궁합과 고객찾기 – 사내 그로스 해킹 세미나

재직하고 있는 KStyleTrip 에서 그로스 해킹(Growth Hacking) 관련 세미나를 했다.

그로스 해킹에 대해 위키피디아에서는 이렇게 정의한다.

그로스해킹이란 기술기반 스타트업에서 개발된 마케팅 기법으로 (기존의 것과 다른) 창의적인 방법, 분석적인 사고, 소셜 지표 등을 통해 제품을 노출하고 판매하는 것이다. (Growth hacking is a marketing technique developed by technology startups which uses creativity, analytical thinking, and social metrics to sell products and gain exposure.)

최근 번역서가 출간되어 사내에서 함께읽고 그 내용을 전파하는 자리를 마련했다.

지금까지는 막연히 페이스북 뉴스피드에서 단편적인 지식만 얻어왔다. 예를들면 링크드인은 “이메일의 3~4번째 안에 위치해야 개봉률이 높다” 같은 인사이트를 얻었다는 것 들이었다. 하지만 이런 노하우 보다는 어떻게 그런 생각을 할 수 있었는지 궁금했었다. 이 책은 그 부분에 대해 명쾌하게 이야기 한다. 지금까지의 사고 방식을 바꾸라는 것이다.

책을 자세히 읽다보니 나는 지금 그로스 해킹을 적용하기 매우 좋은 상황과 위치에 있다는 것을 알게됐다. 지금 회사가 스타트업이고 이런 세미나를 개최할 정도로 사내에 새로운 마케팅 기법에 우호적이다(그로스 해킹은 특히 대표님께서 항상 강조하는 것이기도 하다). 그로스 해킹에는 기술적인 도움이 많이 필요한데 내가 바로 개발자이고, 지표에 대한 이해가 있으며 분석을 직접 할 수 있다.

세미나를 위해 제작한 슬라이드를 공유하고자 한다. 내가 맡은 부분은 Step 1, 2 이다. 책 내용 중 일부를 공유하지만 지금까지의 생각을 어떻게 바꿔야 하는지 인사이트를 얻기에는 충분하다고 생각한다.

책의 내용에 대해 너무 많이 공개하지 않는 선에서 이야기 해보자면, 이 책에서는 전통적인 마케팅 방식을 영화 산업과 같다고 이야기 한다. 9개 영화가 망해도 블록 버스터 1개가 많은 매출을 내면 상쇄할 수 있다는 것이다. 그리고 많은 비용을 들여 산탄총을 쏘는듯이 마케팅한다. 하지만 스타트업은 그럴 수 없고 우리 인생도 그렇지 않다.

그리고 마케팅이란 에스키모인에게 냉장고를 파는게 아니라 시장에 먹히는 제품을 만들고 개선해 파는 것이라 이야기한다.

특히 스타트업 종사자라면 이 책을 꼭 한번 읽어보시기를 추천한다.

Google Chrome 에서 Grunt 사용하기

KStyleTrip 에서는 프론트엔드 영역에서 디자이너와 개발자가 협업하고 있다.

나는 사실 HTML CSS 를 어느 수준으로 다루기는 하지만 퍼블리셔는 아니어서 픽셀 단위의 디테일을 구현하는데는 어려움이 있다. 디자이너는 디자이너 대로 원하는 만큼의 디테일을 구현하기 어려워하는 내 모습을 보기 안타까워 했다. 그래서 현실적인 수준에서 협업을 시작했다.

개발자가 디자인을 보고 큰 덩이에 대해 마크업과 CSS 처리를 하면 디자이너가 원하는 수준의 디테일을 구현하는 방식이다.

그런데 역시 개발자와 비 개발자간의 협업은 환경구성에 어려움이 있기 마련이다. 예를들어 서버를 띄우거나 하는 일들 말이다. 물론 이것도 쉘 스크립트 등을 사용해 할 수 있는 한 단순하게 만들어 관리하고 있었지만 더 쉬운 방법을 찾게 되었다.

바로 크롬 개발자도구에서 Grunt 를 사용하는 것이다. 쉘스크립트로 관리되던 작업들을 Gruntfile 에 통합하고 grunt-devtools 를 사용해 여러 작업들을 GUI 로 작동할 수 있게 만들었다.

설치과정과 실행방법을 공유하고자 한다.

설치

크롬 익스텐션과 grunt-devtools npm 패키지를 설치해야 한다.

크롬 익스텐션 설치

크롬 익스텐션은 크롬 웹스토어에서 설치할 수 있다. 바로가기

익스텐션을 설치하고 크롬 개발자도구를 열어보면 Grunt 탭이 추가된 것을 알 수 있다.

abstract

grunt-devtools 명령어 설치

명령어를 실행할 것이므로 -g 옵션을 주어 패키지를 설치한다.

$ npm install -g grunt-devtools

사용방법

Gruntfile 이 있는 경로에서 grunt-devtools 를 실행하고 개발자 도구의 gruntjs 탭으로 이동하면 프로젝트가 추가된다.

$ grunt-devtools

여러 디렉토리를 옮겨가며 추가하면 상단 프로젝트 바에 여러 프로젝트들이 추가된다. 이 프로젝트들은 일시적인 것으로, grunt-devtools 와 크롬을 종료하면 사라진다. 따라서 크롬을 다시 시작하면 프로젝트마다 다시 실행해줘야 한다.

그리고 왼편에 위치한 태스크 리스트 아이템을 더블클릭하면 태스크가 실행된다.

태스크에는 Background Tasks, Alias Tasks, Tasks 가 있다.

Alias Tasks 나 Tasks 는 Grunt 의 기본기능이다. Background Tasks 가 생소한데, 간단히 말하면 콘솔을 점유하는 watch 같은 태스크를 Background 로 실행시킬 수 있는 기능이다. 콘솔을 점유하는 태스크들은 종료하지 않으면 다른 태스크를 사용할 수 없다. 이럴 때 Background Tasks 로 실행시켜두면 실행을 종료하지 않고 다른 태스크를 동시에 실행할 수 있다.

태스크를 일단 실행시키고 그 위에 B 아이콘을 클릭하면 Background Tasks 로 실행된다.

background-task

이제 디자이너는 grunt-devtools 라는 명령 하나만 외우면, 혹은 단축 아이콘을 더블클릭하는 것으로 서버를 띄우고 스프라이트 아이콘을 빌드하는 등의 작업을 할 수 있게 되었다. 더 쉽게 더 많은 권한을 드릴 수 있게 되어 기분이 매우 좋다 🙂

P.S. Gulp 에도 gulp-devtools 라는 프로그램이 있다.

페이스북에 Gruntjs 관심그룹을 운영 중입니다. 가입을 언제나 환영합니다 😀

OS X, Case Sensitive 볼륨을 Case Insensitive 볼륨으로 변경하기

최근 들어온 정보에 따르면 El Capitan 에서는 HFS+ 의 Case Sensitive 볼륨을 만들 수 없게 되었다고 합니다. 자세한 사항은 정식버전 출시 후 업데이트 하겠습니다.

OS X 디스크 볼륨은 파일의 대소문자를 구분하지 않는(Case Insensitive) 것이 기본값이다.

하지만 주 업무가 리눅스 서버에 설치되는 프로그램들을 만들다보니 가끔 파일 이름에서의 실수가 발생하는 경우가 있었다. 예를들어 파일이름은 foo.json 인데 프로그램에선 Foo.json 을 로드한다던지 하는 문제가 발생했다. 이런 문제는 서버에 설치되기 전까지는 알아챌 수 없는 문제이다. 그래서 Yosemite 을 설치하면서 대소문자를 구분하는 포맷으로 사용하기 시작했다.

헌데 OS X에서는 Case Sensitive 를 사용하면 각종 애로사항이 발생한다. 구글에서 검색해보면 절규가 들려온다. 특히 어도비 제품들은 최신판인 CC 에서도 주 볼륨이 Case Sensitive 로 포맷되어 있으면 인스톨러가 실행조차 되지 않는다.

추정하기로는 OS X 기반 개발자들이 파일의 대소문자를 민감하게 따지지 않아 애플리케이션에 잠재적인 오류 가능성이 있어 설치를 막는 것으로 보인다. 내 경우에도 포토샵 등은 CS6 에서의 Workaround 를 찾아 어찌어찌 해결했지만 Adobe Extension Manager 가 동작하지 않아 플러그인들을 설치할 수 없었다. 참고:CS6 에서의 Workaround

그런데 Adobe Extension Manager 를 사용해야만 하는 이슈가 발생해서 Case Insensitive 로 변경해야만 했다.

검색해보니 iPartition 이라는 앱이 이런 일을 편하게 해준다고 하는데, 가격이 너무 비싸 수동으로 작업했다. 이 작업으로 컴퓨터를 사용하지 못하는 상황은 원하지 않아 2일에 걸쳐 작업했다.

백업은 Carbon Copy Cloner 라는 앱을 트라이얼 상태로 사용했다. 이 앱은 Rsync 를 사용해 하드디스크를 증분 백업해준다. 그래서 첫번째 백업 이후에는 굉장이 빠르다. 자기 전에 하루 저녁동안 백업해두고, 그 다음날 저녁에는 한번 더 백업한 다음 디스크 유틸리티로 복사해놓고 잠들었다. 다음날 아침에 보니 정상적으로 동작하는 것을 확인할 수 있었다.

(350GB 정도 사용한 500GB SSD 와 USB 2.0 외장 500GB HDD 을 사용함.) * Day 1: Carbon Copy Cloner 로 백업 (4시간 소요된 것으로 추정) * Day 2: Carbon Copy Cloner 로 증분 백업 (30분 소요), Yosemite 설치 디스크로 Disk Utilities 실행, 백업한 것을 리스토어 (6시간 소요된 것으로 추정)

Case Insensitive 볼륨에서 Case Sensitive 사용하기

공교롭게도 위 과정을 거친 바로 다음날 Case Sensitive 관련 문제가 발생했다. git 에서 어떤 파일을 수정한 일이 없는데 계속 수정된 상태로 나오는 것이다.

리모트 리파지토리를 살펴보니 동일한 이름에 대소문자만 다른 두 파일이 있었다. 예를들어 foo.csv 와 Foo.csv 파일 두개가 동시에 존재하는데 대소문자를 따지지 않는 파일시스템을 사용하니 문제가 생긴 것이다.

이 문제는 OS X 의 기본기능인 디스크 이미지를 만들어 해결했다. 디스크 이미지는 겉으로 보기에는 파일 형태이지만 실행(마운트)하면 별도의 디스크 처럼 동작하는 기능이다.

볼륨과 별도로 Sparse Bundle 을 Case Sensitive 로 포맷해 이 쪽에서 내용을 살펴보았더니 파일이 두 개 존재하는 것이 보였다.

Screen Shot 2015-06-01 at 9.20.05 PM

그래서 내용을 잘 처리하고 하나의 파일로 다시 만들어 해결했다.

대소문자를 구분하는 디스크 이미지를 만드는 방법

Disk Utility 에서 새로운 이미지를 만들도록 선택하고 이 이미지의 포맷을 Case-sensitive 계열로 선택해 만들면 된다. 생성된 파일을 실행(더블클릭) 하면 디스크로 동작한다.

15DCF2DB-C1B4-403B-B8CB-FFEDACCD0CD5

skitch

Title Image - Merge 와 Rebase

Git Merging 과 Rebase 의 상황별 사용법

Git 을 사용하기 시작한지가 벌써 3년이다. 한번은 문상환님하고 Git 의 Merge branch 커밋에 대해 이야기를 한 적이 있다. 대화가 진행될 수록 Rebase 와 Merge 를 머리로만 알고 있을 뿐, 제대로 이해하지 못하단 걸 알게됐다. 일종의 산파법이랄까.

Git 에서 코드를 합치는 방법에 대해 탕수육의 뿌먹파와 찍먹파처럼 Rebase 파와 Merging 파가 있다. 나는 Merging 파였다. Rebase 에 대해서 알고는 있지만 그저 “충돌나면 머리아프니 안써” 라며 배제 했었는데 좋은 글을 찾아 요약하게 되었다.

개인적으로 중요한 내용인, 각각의 장단점과 활용방법에 대해서만 요약했다. 원문은 소스트리 블로그 에서 볼 수 있다.

각 기능의 장단점

Merging 장점

  • 이해하기 쉬움
  • 원래 브랜치의 컨텍스트를 유지함.
  • Fast-Forward Merge 를 하지 않는다면 브랜치 별로 커밋을 분리해 유지. 특히 이런 분리는 기능 브랜치에 유용.
  • 원래 브랜치의 커밋들은 변경되지 않고 계속 유지되어 다른 개발자들의 작업과 공유되는 것에 대해 신경쓸 필요가 없음.

Merging 단점

  • 단순히 모든 사람들이 같은 브랜치에서 작업하기 때문에 머지해야할 때는 merge 가 커밋 히스토리상으로 전혀 유용하지 않고 어지럽기만 하다.

Rebase 장점

  • 단순한 히스토리
  • 여러 개발자들이 같은 브랜치를 공유할 때 커밋을 합치는 가장 직관적이고 깔끔한 방법.

Rebase 단점

  • 충돌상황에서 다소 복잡. 커밋 순서대로 Rebase 를 하는데, 각 커밋마다 충돌해소를 순서대로 해주어야 한다. SourceTree 가 가이드하기는 하지만, 역시 복잡한 것은 사실이다.
  • 해당 커밋들을 다른 곳에 푸시한 적이 있다면 히스토리를 다시쓰는 것에 부작용이 발생한다. Mercurial 에서는 간단히 푸시를 할 수 없다. Git 에서는 Push 할 수 있으나 당신 혼자 쓰는 리모트 브랜치에만 가능하다. 만약 다른 사람이 그 브랜치를 체크아웃 받은 후 당신이 리베이스 한다면 꽤 혼란스럽게 될 것이다.

결론

Rebase 와 Merging 모두 나름의 가치가 있는 것으로, 논란의 대상이 아니고 상황에 따라 사용해야할 것이 다른것이다.

  1. 여러 개발자들이 같은 브랜치를 공유할 때는 Pull & Rebase 가 히스토리를 깔끔하게 유지하는데 좋음.
  2. 완료된 기능 브랜치를 다시 합칠 때는 머지를 사용.
  3. 기능 브랜치에 부모 브랜치의 변경 내용을 반영하고 싶을 때는
    1. 아래 상황에서는 리베이스가 낫다.
      • 이 브랜치를 다른 곳에 푸시한 적 없는 경우.
      • (Mercurial 이 아닌) Git을 사용하고 다른 사람이 이 기능브랜치를 체크아웃할 일이 없을 것이라 확신하는 경우.
    2. 이 외의 상황에는 머지가 낫다.

따라서 KStyleTrip 는 Git 그라운드 룰을 다음처럼 정하기로 했다.

  • Remote 와 Local 에 동시에 존재하는 브랜치를 Pull 할 때에는 Rebase 를 사용하도록 한다.
  • 기능 브랜치에 대해서는 Merge 를 사용, Rebase 와 비슷한 동작을 하게되는 Fast-Forward Merge 를 사용하지 않는다.
  • 기능 브랜치에 그 부모 브랜치의 내용을 합칠 때는 로컬 브랜치일 때만 Rebase 로 합침.

p.s. Github 클라이언트는 Pull 시 자동으로 Rebase 한다, Sourcetree 도 해당 기능을 설정할 수 있다. 설정법은 원문 참조.