다른 프로그래밍 언어와 같은 부분이 많아 큰 어려움은 없었지만 타입 변환 등 자바스크립트만의 특성으로 잘 읽어봐야 할 부분이 많았다. 특히 typeofinstanceof 부분은 JavaScript를 더 이해하는데 도움이 되었다.


Chapter 4 표현식과 연산자 Expressions and Operators

표현식 : 값을 구하기 위한 표현 방법

연산자 : 표현식의 구성요소 (값을 반환하거나 연산함)

4.1 Primary Expressions

상수, 문자열 값, 키워드, 변수 레퍼런스 (eg. true, false, undefined)

4.2 객체, 배열 생성자 Object and Array Initializers

  • 객체 : {}
  • 배열 : []

4.3 함수 정의 표현식

var square = function(x) { return x * x; };

4.4 프로퍼티 접근 표현식

expression.identifier  // 식별자가 이렇게 써도 문법에 위배되지 않을 때 사용 가능
expression[expression] // 배열일 때 특히

4.5 구동 표현식 Invocation Expressions

square(10)
Math.min(x, y, z)
foos.sort()
  • 아규먼트의 연산을 먼저 한 후 함수가 실행됨 (in common sense)
  • 실행 가능 객체가 아니라면 TypeError
  • return
  • 함수(OO에선 메서드)가 실행될 때 this

4.6 객체 생성 표현식

var o = new Object()
var d = new Date()
  • 초기화 할 때 생성되는 this

4.7 연산자 미리보기

  • p.62 표 참조. 다른 프로그래밍 언어랑 크게 다른게 없음.
  • typeof, instanceof
  • 문자열 합칠 때와 숫자 계산할 때 둘 다 + 사용
  • 형변환이 자유롭게 발생하므로 유의 "3" * "5" // => 15

4.8 산술 표현식 Arithmetic Expressions

  • *, /, %, +, –
  • NaN
    • 연산자 : 값을 합칠 때 해당 값이 객체이면 3.8.3에서 본 것처럼 toString() 또는 valueOf()로 형변환 시도
  • 비트연산자 : &, |, ^, ~, <<, >>, >>>

4.9 관계 표현식 Relational Expressions

  • ===== : 타입 변환 허용 var point = { x : 10, y: 20 };

    “x” in point // => true

    “s” in point // => false

    var data = [3, 2, 1];

    “0” in data // => true

    // 배열은 값이 들어 있는지 확인하는 것이 아니라 해당 index에 값이 있는지 확인해줌

  • instanceof : 어떤 클래스인지 확인할 때. 상속되는 모든 클래스에 대해 true

4.10 논리 표현식

  • &&, ||, !

4.11 배정 표현식 Assignment Expressions

  • =, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, |=, ^=

4.12 평가 표현식 Evaluation Expressions

  • eval(): 하나의 아규먼트를 js 코드처럼 처리해줌.
  • ES5에서 global eval
  • IE 전용 execScript()

4.13 그 외 표현식

  • 3항 연산자(?:) : var age = birthyear > 2000 ? "yong" : "old";
  • typeof : p.82 표 참조
    • “undefined”, “object”, “boolean”, “number”, “string”, “function”, “object”, “<구현한 객체>”
    • null"object" 반환
    • 호출 가능한 객체 callable object 가 정확하게 함수function는 아님. 하지만 typeof에서는 호출 가능한 객체에 대해 “function”을 반환
  • delete
    • ES5 strict에선 못지울 것 지우면 SyntaxError
    • garbage collection이 있으므로 일일이 지워줄 필요는 없음
  • void : 프로토콜에서 사용하는데 (주. 쓰지말자.)
  • , : a=1, b=2, c=3;

tmux를 어디선가 보고 엄청 멋지다 싶어서 검색했더니 @nanhapark님이 재미있게 정리한 글이 있어서 편하게 볼 수 있었다. 읽은 글들은 다음 목록에서 확인할 수 있고, 읽으며 요약해 정리했다. (nodeqa.com에 해당 글이 있었는데 사이트가 더이상 운영되지 않아 링크를 제거했다.)

tmux 설치하기

맥에서는 brew로 설치 가능

$ brew install tmux

tmux 구성

  • session : tmux 실행 단위. 여러개의 window로 구성.
  • window : 터미널 화면. 세션 내에서 탭처럼 사용할 수 있음.
  • pane : 하나의 window 내에서 화면 분할.
  • status bar : 화면 아래 표시되는 상태 막대.

명령어 정리

tmux는 prefix 키인 ctrl+b를 누른 후 다음 명령 키를 눌러야 동작할 수 있다. 다음 내용에서 ctrl + b, 어쩌고 내용이 있다면 tmux 내에서 쓸 수 있는 단축키다.

ctrl + b, <key>

일부 직접 명령어를 입력해야 할 때는 명령어 모드로 진입해야 한다. 명령어 모드의 key는 :다.

ctrl + b, :

세션 관련

# 새 세션 생성
$ tmux new -s <session-name>

# 세션 이름 수정
ctrl + b, $

# 세션 종료
$ (tmux에서) exit

# 세션 중단하기 (detached)
ctrl + b, d

# 세션 목록 보기 (list-session)
$ tmux ls

# 세션 다시 시작
$ tmux attach -t <session-number or session-name>

윈도우 관련

# 새 윈도우 생성
ctrl + b, c

# 세션 생성시 윈도우랑 같이 생성
$ tmux new -s <session-name> -n <window-name>

# 윈도우 이름 수정
ctrl + b, ,

# 윈도우 종료
ctrl + b, &
ctrl + d

# 윈도우 이동
ctrl + b, 0-9 : window number
            n : next window
            p : prev window
            l : last window
            w : window selector
            f : find by name

틀 pane 관련

# 틀 나누기
ctrl + b, % : 횡 분할
          " : 종 분할

# 틀 이동
ctrl + b, q 그리고 화면에 나오는 숫자키
ctrl + b, o : 순서대로 이동
ctrl + b, arrow : 방향키로 숑숑

# 틀 삭제
ctrl + b, x
ctrl + d

# 틀 사이즈 조절
(ctrl + b, :)
resize-pane -L 10
            -R 10
            -D 10
            -U 10

# 틀 레이아웃 변경
ctrl + b, spacebar

단축키 관련

# 단축키 목록
ctrl + b, ?

# 키 연결 및 해제 bind and unbind
(ctrl + b, :)
bind-key [-cnr] [-t key-table] key command [arguments]
unbind-key [-acn] [t key-table] key

# 옵션 설정 `set` and `setw`
set -g <option-name> <option-value>  : set-option
setw -g <option-name> <option-value> : set-window-option

copy mode 1

copy mode에서는 콘솔을 스크롤 하거나 내용을 복사하는 등의 기능을 할 수 있다.

# copy mode 진입
ctrl + b, [

# 빠져나오기
(copy mode에서) q or ESC

# 이동
arrow : 커서 이동
pageUp, pageDown : 페이지 이동 (iTerm에서는 fn + up, down, terminal에서는 alt + up, down)

설정 저장하기 tmux.conf

~/.tmux.conf 파일을 생성해 설정을 저장해두면 시작할 때 자동으로 설정을 불러온다. 컬러 설정, 마우스 설정


이것저것 해보다 알게 된건데 iTerm에서 tmux로 만든 세션을 다른 terminal에서 접속하면 동시에 동작한다.

뭐야 무서워…

  • 내 터미널 설정이 이상해서 그런지 설명대로 동작하질 않는다. 
  • 짧지 않았던 3번째 챕터인데 깊은 내용은 후반부에 다룬다는 부분이 많았다. 전반적으로 살펴보는 느낌으로 읽으면 좋을 것 같다.


    Chapter 3 타입1, 값, 변수 Types, Values, and Variables

    이 챕터에서는 다음 세가지에 대해 심층적인 설명을 다룸.

    • 타입 : 문자열, 숫자, 객체 등 값이 어떤 형태의 자료인지를 의미
    • 값 : 3.14, “Hello World” 실제 저장되는 정보
    • 변수 : 값을 나중에 사용하기 위해 이름으로 저장해두는 공간

    3.1 숫자

    64비트 부동 소수점 포맷

    • 정수 문자열 : 10진수(255), 16진수(0xff), 8진수(0377)
    • 부동 소수점 문자열 : [digits][.digits][(E|e)[(+|-)]digits]
    • 계산 : +, -, *, /, % and Math object (p.33)
    • 무한대 : -Infinity, Infinity, negative 0 (but 0 == -0 => true)
    • NaN : Not-a-number value. 0으로 나누기 등 에러가 발생하는 계산에서 나타나는 값 (비교연산자 못씀. isNaN())
    • 다른 프로그래밍 언어처럼 부동 소수점 처리에 문제가 있으므로 정수 영역으로 쓸 것
    • 일자와 시간 : Date object (p.35), new Date().getTime(). 숫자처럼 비교 가능한 객체

    3.2 텍스트

    • 불변(배열같이 0부터 인덱싱), 16비트, 유니코드
    • ” 또는 “”, 개행 또는 이스케이프 시 \ 사용 (p.37, 38)
    • 텍스트 메소드 p.38~
    • 정규표현식 : /hello/g.test("hello world") (챕터 10)

    3.3 불린값 Boolean Values

    • true 또는 false
    • undefined, null, ``, -0, NaN, "" => false

    3.4 nullundefined

    • undefined : 시스템 레벨, 예측할 수 없어서 마치 에러같은 빈 값, TypeError
    • null : 프로그램 레벨, 일반적 또는 예측 가능한 형태로의 빈 값, no object as an object
    • ==로는 같으나(false이므로) ===로는 다름

    3.5 전역객체 The Global Object

    JavaScript 해석기(interpreter)가 실행될 때 선언됨 (새로고침하거나.. 할 때 항상)

    • 전역 프로퍼티 : undefined, Infinity, NaN
    • 전역 함수 : isNaN(), parseInt(), eval()
    • 생성자 함수 : Date(), RegExp(), String(), Object()
    • 전역 객체 : Math, JSON

    웹브라우저에서는 window, 콘솔에서는 global

    3.6 레퍼 객체 Wrapper Objects

    기본형 primitive value인 경우 프로퍼티를 가질 수 없으므로 그런 경우 레퍼 객체를 활용할 수 있음. OO로 개발할 때 도움. (Java의 레퍼 클래스와 비슷한듯)

    var s = "test", d = new String("test");
    s.len = 4, d.len = 4;
    console.log(s.len, d.len); // undefined 4
    
    • String(), Number(), Boolean()

    3.7 변하지 않는 기본형과 변하는 객체 참조 Immutable Primitive Values and Mutable Object

    References

    • 기본형과 객체의 기본적인 차이인 불변성. 객체는 값이 아닌 참조가 들어있기 때문.
    • 객체를 비교하거나 복사할 때는 유의해야 함. (비교 코드 예시 p.45)

    3.8 타입 변환

    JavaScript에서의 타입 변환은 완전 유연

    • true로 변하는 값, false로 변하는 값

    • 타입 변환 표 p. 46

    • 비교할 때 타입 변환을 고려할지 안할지. ==, ===

    • 명시적 변환 : 레퍼 객체 또는 x + "", +x",!!x` 활용

    • 진수 변환, 정수 또는 소수 등 parsing parseInt(), (320.329).toFixed(2)

    • 3.8.3 객체를 기본형으로 변환 : valueOf() => toString() => TypeError

    • 객체-숫자 변환과 객체-텍스트 변환 두가지로 문제 발생할 수 있음 typeof(new Date() + 1) // => “string”

      typeof(new Date() – 1) // => “number”

      typeof(+new Date() + 1) // => “number”

    3.9 변수 선언

    • var로 선언 : 타입이 따로 지정되지 않음.
    • 중복 선언해도 에러 발생 안함. 선언 안하면 에러남.
    • 항상 var 사용하는걸 권장. => 3.10.2

    3.10 변수 스코프 Variable Scope

    • 프로그램 소스코드에서 선언한 변수를 사용할 수 있는 범위. 전역 변수는 전역 스코프를 가짐.

    • 함수 스코프와 호이스팅 Hoisting

      — C에서는 { } 기준의 block scope지만 js에서는 함수 기준의 스코프

      — 함수 중간에 var로 변수선언이 있으면 함수 실행 시 처음에 다 선언처리함 (hoisted)

    • 프로퍼티로서의 변수 : var로 선언하면 삭제 불가능한 프로퍼티로 생성

    • 스코프 체인

      — 변수 확인할 때 스코프 내에 선언되지 않은 경우 상위 스코프로 계속 이동하며 찾음. 끝까지 없으면 ReferenceError

      — 함수 내에 함수를 선언 했을 때

      with 5.7.1, 클로저의 이해 8.6 참고

  • 프로그래밍 서적에서는 흔히 type을 형으로 번역하는데 그냥 영어로 적는다. 

  • 예전부터 게임 개발에 관심이 많았고 만들어보고 싶었었는데 첫 결과물로 Koala hates rain을 릴리즈 하게 되었다.

    게임 소개

    Koala Hates Rain Screenshot

    Koala hates rain은 코알라가 하늘서 떨어지는 비를 피하는 내용으로 짧은 시간에도 즐길 수 있는 미니게임이다.

    2014년 3월 13일에 앱스토어를 통해 출시되었고, 한국 스토어에서 59위까지 진입했었고, 호주 스토어에서는 하위 카테고리에서 13위로 featured 되었다.

    apple에서 제공하는 SpriteKit Framework를 사용했다. 리소스는 일러스트레이터, 음향 효과 및 배경음은 garageband를 통해 제작했다. 총 개발 기간은 20일 정도 걸렸으며 그 중 그래픽/음향 리소스를 만드는데 12일 정도를 사용했다.

    좋았던 점

    SpriteKit을 사용해서 빠르게 개발 할 수 있었다. 애플에서 제공하는 문서가 세세한 부분은 조금 부족했지만 전체적인 흐름을 쉽게 파악할 수 있도록 잘 작성되어 있어 많은 도움이 되었다. ObjectiveC로 개발은 처음이라 어색한게 많았는데 xcode의 강력한 기능도 인상적이었고 특히 트위터를 통해 여러 개발자 분들이 많은 도움을 주셔서 문제를 잘 해결하며 개발할 수 있었다.

    게임 리소스를 직접 만들었다. 개발의 전체적인 프로세스를 배운다는 생각으로 리소스를 만들었는데 일반적으로 출시되는 게임들이 얼마나 많은 공을 들여 제작하고 있는지를 간접적으로나마 느낄 수 있었다. 많은 시간을 할애해서 리소스를 제작했는데 엄청난 수준은 아니지만 적어도 이상해보이진 않도록 만들 수 있었다. 특히 garage band는 몇 번 클릭 만으로 재미있는 소스들이 많이 나와서 즐거웠다.

    트위터를 통해 많은 분들이 테스트에 참여해 주셔서 다양한 피드백을 받을 수 있었다. 혼자 만들며 보지 못했던 부분들을 많이 개선할 수 있었고 다양한 환경에서 테스트 하게 되어 새 버전에서 나타나는 버그를 잡는 등 큰 도움이 되었다. 피드백은 별도의 도구 없이 트위터의 해시태그 #koalaHatesRain를 활용했는데 집계의 불편함은 다소 있었지만 다같이 모이지 않은 상황에서도 한 자리에 모여 피드백을 주고 받는 느낌을 받을 수 있었다.

    개발 과정과 테스트, 피드백의 과정을 뉴스레터를 통해 공유했다. 개인적으로 개발하며 별도의 문서작업을 하지 않았는데 간략한 프로젝트의 소개와 받은 피드백, 문제가 되었던 부분, 해결 과정 등을 담아 공유했고 스스로도 프로젝트를 정리하는데 도움이 되었다.

    다양한 홍보 체널을 활용해볼 수 있었다. 랜딩 페이지, 트위터, 텀블러를 개설했고 페이스북과 페이스북 그룹, 커뮤니티 사이트에 홍보글을 올렸다. 각 인디 게임 리뷰 웹사이트에 리뷰 요청 및 홍보를 위한 자료를 보냈고 호주 지역에 페이스북 타겟 광고를 진행했다. 홍보 특수로 현재 총 다운로드 수의 절반 정도가 유입되었다. 특별하게 대단한 게임은 아니었지만 위 일련의 홍보 과정에서 많은 분들의 생각과 게임 업계 이야기를 생생하게 들어볼 수 있어 더 도움이 되었다. (안드로이드와 iOS 시장의 비교라든가…)

    안좋았던 점

    SpriteKit를 선택한 만큼 장점도 있지만 단점도 많았다. 애플에서 제공하는 framework 답게 안드로이드 등 멀티 플랫폼으로 출시할 수 없었다. 한번 만들면 여러 플랫폼으로 낼 수 있는 cocos2d와 비교해 큰 결점이다. 그리고 아직 충분히 성숙한 상태가 아니라서 다양한 버그와 세세하지 못한 문서, 구글링으로 트러블 슈팅하기엔 너무 적은 개발자층 등의 문제가 있었다.

    일정 관리를 따로 하지 않았다. 그래서 갑작스럽게 릴리즈한 느낌이 강하다. 더불어 중요하지 않은 부분에 신경 쓰느라고 시간을 많이 썼다. 코알라 이미지는 대여섯번 다시 작업했고 (여전히 불만족) 버튼을 누를 때와 땔 때 다른 소리를 넣는 등 이상한 디테일에 집착한 경향이 강했다. 다음에 또 개발하게 된다면 trello, bitbucket의 이슈 트래커나 여러 기능들을 활용해서 더 체계적으로 접근해봐야겠단 생각이 들었다.

    테스트 코드를 작성하지 않았다. 가볍게 프로토타이핑 하는 마음으로 시작했었고 프로토타이핑 한 코드를 실제로 많이 사용했기 때문에 테스트를 작성하기 뭔가 애매하게 되어 버렸다. 로직이 복잡하지 않았기도 했고 발코딩 경향이 강했기에 어물쩡 넘어갔는데 다음에 개발하게 되면 TDD로 진행해보고 싶다.

    앱을 릴리즈 하기 전에 꼼꼼하게 확인하지 못했다. 평가 요청을 띄우는 라이브러리를 사용하지 않는 대신 평가하기 버튼을 넣었는데 iOS 7부터 해당 링크가 변경된 사실을 몰라서 동작하지 않는 상태로 앱스토어에 업로드 되었다. 앱스토어에 등록되지 않아서 뜨지 않는 줄 알았는데 앱스토어 등록 후 받은 피드백에서야 그 원인을 알게 되었다. 그런 이유로 앱 출시 직후에 홍보를 하질 못했는데 오픈 버프(?)를 놓치고 말았다.

    릴리즈 이후 전략이 딱히 없었다. 미리 게임 업데이트의 방향도 잡아두고 미리 구성도 해놔야 했는데, 첫게임이니까 라는 이유로 전혀 생각해보지 않았다. 피드백 중 대부분의 내용도 반영하질 못했는데 차후 버전을 위해 잘 고민해서 방향 잡고 개발해보고 싶다.

    작업노트

    결론

    너무 재미있었다. 역시 현실은 생각만큼 혹독했다. 혹독해서 더 많이 배울 수 있었고 또 다른 시야가 트인 기분이다. 현업에서 종사하시는 분들의 경험을 간접적으로나마 체험하고 나니 새로 느낀 점이 참 많았다. 앱스토어에 매일 출근도장 찍어서 순위도 확인해보고 다른 게임도 더 많이 해보게 되었다. 특히 웹 이외의 분야에서의 개발은 처음이었고 나름 결과물을 공유할 수 있었기에 더 의미있던 시간이었다.

    다음 개발은 cocos2d를 사용할 수 있도록, 그리고 좀 더 기간을 두고 준비할 생각이다. 더 재미있고 즐거운 게임을 만들기 위해 고민할 시간이 기대된다.

    뒷담화(?)

    특히 테스트에 참여해주시고 많은 조언을 해주신 테스터 분들께 너무나도 감사합니다. 다음엔 철저하게 준비해서 더 재미있는 경험을 공유하도록 하겠습니다.

    기초적인 부분이긴 하지만 유니코드 값 비교 부분은 잘 살펴볼 필요가 있다. 꼭 자바스크립트가 아니더라도 각 언어에서 유니코드를 어떻게 처리하고 다루는지 알아두면 유용하다. 발생할 수 있는 수많은 케이스가 있는데 그 중 하나로 음악 스트리밍 서비스인 spotify가 사용자명으로 유니코드를 사용해 보안 문제가 발생했었던 사례를 들 수 있다.


    Chapter 2 어휘 구조 Lexical Structure

    어휘 구조는 프로그래밍 언어의 가장 기초적인 문법.

    2.1 캐릭터 셋

    ASCII와 Latin-1를 포함하고 있는 유니코드

    2.1.1 대소문자 구분 – 구분한다

    html은 구분 안하므로 유의

    2.1.2 공백, 줄바꿈, 양식 문자

    공백은 무시됨, 가독성을 위해 사용 (예외 2.5)

    줄바꿈은 단일 행 실행 종료로도 처리됨 (세미콜론 없어도 된다는 말)

    식별자 빼고 LTR, RTL MARK 등 양식 문자를 사용할 수 있음

    2.1.3 유니코드 탈출 문자열

    유니코드 미지원 환경을 위한 유니코드 사용

    \u + 4자리 8진수 주소

    "résumé" === "r\u00e9sum\u00e9" // => true
    

    2.1.4 표준화 Normalization

    유니코드는 같은 글자를 여러 방법으로 표기할 수 있음

    é는 유니코드 문자 하나로 표기할 수도 있고 e + ́ 로도 표시할 수 있음

    console.log("e\u0301", "\u00e9"); // => é é
    console.log("e\u0301" === "\u00e9"); // => false
    

    자바스크립트는 작성된 코드를 이미 표준화 된 것으로 보고 별도로 표준화 처리 안함

    2.2 주석

    /* 블럭주석 */
    /*
    * 블럭주석
    */
    // 인라인 주석
    

    2.3 문자열 Literals

    문자열은 데이터 값을 의미

    number, string(Chapter 3), boolean, 정규표현식(Chapter 10), null, array, object

    2.4 식별자와 예약어

    문자, _, $, 숫자

    첫글자는 숫자 못씀

    일반적으로 아스키 문자와 숫자

    유니코드 식별자도 가능

    2.4.1 예약어

    예약어는 식별자로 쓸 수 없음 – 기본 함수, 타입 등등

    예약어를 무심코 쓰더라도 예약어 썼다고 에러를 출력하므로 외울 필요는 없어 보임

    (변수명을 undefined로 한다거나 -_ 혼난다)

    2.5 선택적 세미콜론

    다른 언어처럼 각각 명령문 끝에 ; 넣음

    세미콜론 대신 줄바꿈으로 생략도 되는데 말이 안되는 줄바꿈은 알아서 인식함

    작성 의도와 다르게 실행되는 예시 – 코드의 명확성을 위해 세미콜론 꼭 쓰자

    놀부님이 진행하는 자바스크립트 스터디 http://on.fb.me/1iEpW0a 에 참여하게 되었다. 커리큘럼에서 제시된 교재를 선택하고 순서대로 공부해나가면 된다. 상당히 세세하고 실질적이라서 전혀 모르는 사람도 공부하기에 좋은 커리큘럼이다. 교재는 JavaScript: The Definitive Guide으로 선택했다.


    자바스크립트 : 고 수준, 동적, 타입 없는 인터프리터 프로그래밍 언어. 객체 지향, 함수형 언어 스타일

    명칭에는 역사적인 배경이 있음. 상표권 문제로 ECMAScript 로 명명. 3와 5 버전이 있음. (4는 건너 뜀)

    클라이언트측 언어의 태생으로 인해 대다수의 언어와 달리 입출력과 같은 API 지원이 약함.

    공부를 위해 개발자 도구를 설치할 것. (Firebug, 또는 각 브라우저 개발자도구)

    1.1 코어 자바스크립트

    Number, string, boolean

    null과 undefined

    object {} 와 array []

    연산자

    함수 선언

    변수로의 함수

    조건문 if 반복문 while for

    Class와 prototype 상속

    1.2 클라이언트측 자바스크립트

    script 태그

    window 객체

    DOM

    이벤트 핸들링 (onclick, onload etc.)

    jQuery

    이후 웹앱, 스크립티드 http, 미디어 그래픽, 스토리지, html5 api 등 심화 학습.

    1.2.1 계산기 예제

    DOM과 ajax, canvas 이용

    예전에 트위터에서 누군가 소개해줘서 알게 되었는데, 도메인이 도저히 기억나지 않아 한참 검색하다가 다시 찾아서 까먹지 않기 위해 포스트. (허무하게 gitignore.io라니…)

    http://gitignore.io

    git에서는 커밋에 포함하지 않기 위한 규칙을 리포지터리 최상위 .gitignore 파일에 저장하는데 이 템플릿들을 제공하는 서비스다. 사이트 들어가보면 알겠지만 필요한 OS, IDE, 개발언어나 프레임워크 등의 이름을 넣으면 그에 맞는 gitignore 파일을 제공한다.

    gitignore.io

    Command Line 도구를 설치하면 콘솔에서 간편하게 내려받을 수 있다. OSX에서는 다음과 같이 설치해 사용할 수 있다.

    $ echo "function gi() { curl http://www.gitignore.io/api/\$@ ;}" >> ~/.bash_profile && source ~/.bash_profile
    $ gi wordpress,osx >> /path/to/.gitignore
    

    정말 사소한 부분이지만 이런 부분까지 자동화 하는 게으름(?)이 존경스럽다.

    WordPress에서 제공하는 클래스인 WP_Query는 wordpress의 컨텐츠(Post, Page, Custom content etc.)를 쉽게 불러 사용할 수 있도록 도와준다. Widget이나 테마 등에서 컨텐츠 목록을 제공할 필요가 있을 때 편리하게 사용할 수 있다.

    <?php    
    // The Query
    $the_query = new WP_Query( $args );
    
    // The Loop
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        echo '<li>' . get_the_title() . '</li>';
    }
    

    자세한 내용은 WordPress에서 제공하는 WP_Query 문서에서 확인할 수 있다.

    WP_Query에서는 데이터를 가져올 때 array의 형태로 properties를 추가해 활용한다. 한 페이지에서 WP_Query를 여러번 사용할 수도 있는데 이런 경우, 재사용성을 높이기 위해 이전의 설정들이 저장되어 의도하지 않은 데이터가 출력될 때가 있다. 그런 경우를 위해 설정을 초기화 하는 함수인 wp_reset_postdata()가 제공된다.

    <?php    
    // The Query
    $the_query = new WP_Query( $args );
    
    // The Loop
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        echo '<li>' . get_the_title() . '</li>';
    }
    wp_reset_postdata();
    
    $new_query = new WP_Query( $new_args );
    

    wp_reset_postdata()를 사용했는데도 입력한 properties가 무시되는 등 의도한 대로 동작하지 않는 경우가 있다. 이 경우는 WP_Query 클래스에서 포스트를 가져올 때 pre_get_posts hook을 실행하는데 이 포인트에 query 결과를 조작하는 action이 등록되어 있을 가능성이 높다.

    이 hook을 잘못 건들면 대다수의 플러그인과 테마에서 문제가 발생할 수 있기 때문에 만지지 않는걸(should not) 권장한다. Woo Commerce와 같은, 규모가 큰 플러그인은 구현 편의를 위해 이 hook을 사용해 개발하는 경우가 있다. 즉, WP_Query가 제대로 동작하지 않는다면 다른 플러그인이나 테마에서 pre_get_posts를 조작하고 있는지 확인해야 한다.

    <?php
    
    wp_reset_postdata();
    
    global $evil_class;
    remove_action( 'pre_get_posts', array( $evil_class, 'inject_get_posts' ) );
    
    // The Query
    $the_query = new WP_Query( $args );
    
    // The Loop
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        echo '<li>' . get_the_title() . '</li>';
    }
    
    // Recover
    wp_reset_postdata();
    add_action( 'pre_get_posts', array( $evil_class, 'inject_get_posts' ) );
    

    예전부터 cocos2D나 unity를 배워보고 싶었는데 몇 번 글을 보고 따라해봐도 감이 안와서 미뤄왔다. 우연히 SpriteKit 튜토리얼을 보고 따라하다보니 생각보다 쉽게 결과물이 나오길래 게임 만들어보자 마음 먹고 매일 문서 찾아보며 조금씩 만들어가고 있다. 아직 Objective-C도 익숙하지 않지만 CS 193P iPhone Application Development에서 야금야금 들었던 내용 가지고 하나씩 배우고 있다.

    다음 링크는 진행하면서 도움이 된 글들을 간단하게 정리해봤다. 애플 공식 문서도 깔끔하게 정리되어 있는데 좀 예제가 적은 편이라서 기본적인 내용은 공식 문서에서 확인하고서, 실제 사용하는 방법들은 구글링, Stackoverflow에서 찾을 수 있었다.1

    기초

    다음 튜토리얼에서 게임에서 기초적으로 필요한 이미지 불러오기, 터치 이벤트 처리, 간단한 충돌 처리, 노드 animate 방법 등을 배울 수 있다. 리소스도 제공하고 단계별로 잘 설명하고 있어 쉽게 시작하는데 도움이 된다.

    디자인/그래픽 관련

    여러 장의 이미지로 에니메이션을 처리하거나 한 장의 이미지로 여러 node를 만들려고 할 때 다음 글이 도움이 된다. 이미지 하나로 처리하는 방법은 미리 SKTexture textureWithRect:inTexture:로 텍스쳐를 만들어두고 사용하면 된다.

    점수나 안내 문구를 SKLabelNode로 사용하려고 했었기에 임베드 폰트 넣는 방법을 찾아봤다. SKShapeNode로 벡터 처리도 가능하다.

    버튼 관련

    시작, 다시하기, 처음으로 등 버튼을 만들기 위해 찾아본 버튼 관련 내용이다. 꼭 버튼 뿐만 아니라 SKNode에 다 적용되는 내용이라 이해하는데 도움이 되었다.

    데이터 저장하기/불러오기

    High Score를 저장하기 위해 찾아봤는데 여러 저장 방법이 있지만 NSUserDefaults를 사용하기로 했다.

    Footnotes

    1. 아직 나온지 얼마 안되서 그런지 검색이 잘 안되는 경향이 있다.

    근래 아이폰, 아이패드, 맥북 프로 등 통칭 레티나로 일컬어지는, 고밀도 디스플레이 기기가 늘고 있다. 그에 따라서 웹페이지도 레티나 해상도에 대응을 하기 시작했는데, 각 이미지를 2배의 해상도로 저장한 후 css 또는 js를 이용해 치환하는 형태 또는 svg, canvas 등을 이용하는 방식으로 대응하고 있다. 여러 방법 중 svg를 활용하는 방법을 살펴보려고 한다.

    svg는 xml로 작성된 벡터 이미지 포맷으로 대다수의 최신 브라우저에서 지원하고 있어 이와 같은 문제를 해결하는데 도움이 된다. svg를 이용하는 장점은 다음과 같다.

    • 이미지를 2번 이상 생성하지 않아도 된다. 하나의 이미지로 여러 해상도를 지원할 수 있으며 단일 파일로 모두 제어할 수 있으므로 유지보수에 용이하다.
    • svg 엘리먼트를 이용해 인라인으로 사용하면 stylesheet나 js를 이용해 동적으로 활용할 수 있다.

    물론 svg를 사용할 때 단점도 분명 존재한다.

    • 확대/축소에 따라서 의도와 다른 형태로 렌더링 될 수 있다. 예를 들면 비트맵에서는 쉽게 가능한 1px 선을 벡터 방식에선 면으로 표현해야 하기 때문에 그리기 어렵다.
    • IE 8 이하, Android 내장 브라우저 (2.1, 2.2, 2.3)에서는 지원하지 않는다.1

    위에서 살펴본 장단점에 따라 svg를 사용할 수 있는지, 어떤 경우에 적용할 것인지 전략을 세워야 한다. 특히 렌더링에서 차이를 보이는 부분으로 인해 iOS에서 벡터 앱 아이콘을 사용할 수 있는 상황에도 애플앱들은 비트맵으로 작성한 아이콘을 쓰고 있는 예도 있다.2

    svg 사용하기

    svg를 웹에서 사용하는 방법은 img 엘리먼트와 svg 엘리먼트를 이용하거나 css를 통해 활용할 수 있다.

    img를 이용해 일반 이미지처럼 사용할 수 있다.

    <img src="logo.svg" alt="Weird Meetup" />
    

    그리고 svg 엘리먼트를 통해 직접 넣을 수 있다. 이렇게 작성하면 다소 지저분해지는 경향이 있지만 svg 내부의 엘리먼트도 css로 제어할 수 있다는 장점도 있다. 아래는 이상한 모임 로고의 글자 부분이다.

    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="500px"
     height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
        <g id="이상한모임">
            <g>
                <path fill="#000000" d="M180.647,389.499c-2.698,0-5.852-1.786-5.852-6.649v-9.042c0-3.951,2.584-6.991,6.991-6.991h3.381
                    c4.217,0,6.839,3.153,6.839,7.105v9.156c0,3.837-2.545,6.421-5.205,6.421H180.647z M184.447,385.586
                    c1.899,0,2.773-1.824,2.773-3.268v-8.055c0-1.634-1.254-3.078-2.773-3.078h-1.9c-1.52,0-2.925,1.444-2.925,3.078v8.055
                    c0,2.47,0.988,3.268,2.925,3.268H184.447z M200.291,364.309h-5.091v31.953h5.091V364.309z"/>
                <path fill="#000000" d="M216.556,365.639c0.342,4.521,4.597,11.702,7.485,15.273h-5.737c-1.52-1.823-3.153-5.015-4.407-7.94
                    c-1.292,2.583-2.28,5.167-4.445,7.94h-6.421c5.433-4.559,8.207-13.374,8.435-15.273H216.556z M226.283,384.712
                    c2.735,0,4.939,1.71,4.939,4.104v3.039c0,2.09-2.127,4.027-4.787,4.027h-12.918c-3.496,0-5.396-1.178-5.396-4.065v-2.887
                    c0-2.812,2.128-4.218,5.281-4.218H226.283z M214.922,388.663c-1.444,0-1.976,0.38-1.976,1.292v1.102
                    c0,1.103,1.064,1.103,2.052,1.103h9.727c0.912,0,2.052-0.381,2.052-1.103v-1.178c0-0.722-0.76-1.216-2.052-1.216H214.922z
                     M235.135,374.947h-4.255v7.979h-4.863v-18.655h4.863v6.231h4.255V374.947z"/>
                <path fill="#000000" d="M248.742,366.437h6.117v3.495h-2.735c0.874,0.912,1.405,2.166,1.405,3.496v3.951
                    c0,3.191-2.355,5.471-5.053,5.471h-4.711c-2.698,0-5.091-2.279-5.091-5.091v-4.331c0-1.33,0.532-2.584,1.406-3.496h-2.66v-3.495
                    h6.117v-2.166h5.205V366.437z M263.484,395.502h-22.721v-10.524h4.788v6.003h17.934V395.502z M249.122,376.847v-2.432
                    c0-1.216-0.912-2.127-2.166-2.127h-1.596c-1.216,0-2.318,0.911-2.318,2.127v2.432c0,1.254,0.722,2.166,1.938,2.166h2.127
                    C248.362,379.013,249.122,378.101,249.122,376.847z M262.42,372.819h4.483v4.56h-4.483v8.473h-4.901v-21.619h4.901V372.819z"/>
                <path fill="#000000" d="M298.063,392.767h-28.876v-4.445h11.893v-4.293h5.091v4.293h11.893V392.767z M272.493,367.12v15.616
                    h22.455V367.12H272.493z M290.236,378.557h-12.538v-7.295h12.538V378.557z"/>
                <path fill="#000000" d="M315.621,370.806v5.243c0,2.926-2.317,5.243-5.091,5.243h-4.901c-2.773,0-5.281-2.317-5.281-5.243v-5.243
                    c0-2.926,2.508-5.243,5.281-5.243h4.901C313.304,365.562,315.621,367.88,315.621,370.806z M326.031,384.598v11.664h-22.492
                    v-11.664H326.031z M311.176,371.87c0-1.292-0.987-2.242-2.241-2.242h-1.71c-1.254,0-2.355,0.95-2.355,2.242v3.115
                    c0,1.292,1.102,2.279,2.355,2.279h1.71c1.254,0,2.241-0.987,2.241-2.279V371.87z M322.422,388.587h-14.817v3.609h14.817V388.587z
                     M326.031,364.232h-4.407v18.124h4.407V364.232z"/>
            </g>
        </g>
    </svg>
    

    어떻게 지저분한지 보여주기 위해 위 예를 넣었다. 다섯글자일 뿐인데 이렇게 지저분하다.

    modernizr와 css를 이용한 이미지 대체

    위와 같이 직접 적용하면 svg를 지원하지 않는 브라우저에서는 이미지가 나타나지 않기 때문에 modernizr를 통해 svg 지원 여부를 확인하고 그에 따라 css로 이미지를 교체해주는 방법을 활용할 수 있다.

    modernizr를 적용한 모습

    Modernizr를 웹페이지에 적용하면 해당 브라우저에서 어떤 기능을 지원하는지 html의 클래스로 선언해준다. html에 적용된 클래스를 플래그로 이용해 css 배경을 대체/적용하는 방식으로 svg 미지원 브라우저 문제를 해결할 수 있다.

    #logo { background: url("logo.svg"); }
    .no-svg #logo { background: url("logo.png"); }
    

    svg 적용 사례

    • Apple : apple 사이트의 메뉴 등에서 svg를 사용함. 벡터 이미지는 서체 표현에 용이함.
    • Mailchimp : 동보메일 서비스인 mailchimp도 이번 개편에서 svg를 곳곳에서 사용하고 있음. 특히 체크박스나 라디오 버튼을 svg로 대체하고 있는 점이 독특.
    • FontAwesome : 아이콘 폰트를 제공하는 서비스인데 svg로 된 포멧도 지원함.

    이외에도 svg를 활용한 곳을 심심하지 않게 찾아볼 수 있다. svg도 이제 지원하는 브라우저가 많기도 하고 하위 호환을 고려하기도 큰 어려움이 없기 때문에 예전에 비해 많이 사용하는 추세다. 위의 예시에서 눈치챘을 수도 있지만 이상한모임의 로고도 svg를 사용했다.

    읽어볼 만한 글

    다음 두 포스트는 레티나 지원을 위한 다양한 방법에 대해 체계적으로 잘 정리된 글이다.

    간단한 svg 적용 방법, 위에서 언급한 fontawesome를 이용하는 방법은 다음의 링크에서 확인해볼 수 있다.

    Footnotes

    1. svg의 브라우저 지원 여부는 caniuse.com의 svg 페이지에서 확인해볼 수 있다.

    2. iOS7으로 오면서 애플앱도 벡터 방식 아이콘을 쓰는 것 같더라. (잘 모름)

    색상을 바꿔요

    눈에 편한 색상을 골라보세요 :)

    Darkreader 플러그인으로 선택한 색상이 제대로 표시되지 않을 수 있습니다.