Node.js를 설치하기 위한 가장 쉬운 방법은 공식사이트인 http://www.nodejs.org 에서 설치 파일을 받는 것이겠지만, 이 방법은 두 가지 큰 단점을 가지고 있습니다.
첫째, 기본적으로 /usr/local에 설치가 되므로 관리자 권한이 없이는 제대로 실행되지 않습니다. 특히 -g 옵션을 줘서 global로 모듈을 설치할 때 마다 sudo를 해줘야 하는 불편함이 따릅니다. 물론 /usr/local 자체의 퍼미션을 변경하는 방법도 있지만, 보안상 권장하진 않습니다.
둘째, 노드의 여러 버전을 관리할 수가 없습니다. 프로젝트 별로 다른 버전을 써야 할 경우나, 여 러 노드 버전에 맞춰 테스트를 해야 할 때 매우 불편합니다.
Homebrew를 사용하여 설치하는 방법도 있지만, El Capitan에서 새로 추가된 SIP(System Integrity Protection) 때문에 권한 문제가 발생할 때가 종종 있어서, 이 글에서는 제외시켰습 니다.
기존에 이미 노드를 설치하셨다면,
노드는 깔끔하게 삭제하기가 매우 어렵습니다. 아래의 방법으로 삭제하시기 바랍니다. (참고 자 료: http://benznext.com/completely-uninstall-node-js-from-mac-os-x/)
1. /usr/local/lib 에 있는 node와 node_modules를 삭제
2. /usr/local/include 에 있는 node와 node_modules를 삭제
3. Homebrew로 설치하셨다면, brew uninstall node를 실행
4. ~/local 또는 ~/lib 또는 ~/include 디렉토리 밑에 존재하는 node와 node_modules 삭 제
5. /usr/local/bin 에 있는 node 관련 실행파일들 삭제
추가로, 필요에 따라 아래 명령어들을 실행하시면 됩니다. (다른 파일까지 삭제하지 않도록 주 의!)
1. sudo rm /usr/local/bin/npm
2. sudo rm /usr/local/share/man/man1/node.1
3. sudo rm /usr/local/lib/dtrace/node.d
4. sudo rm -rf ~/.npm
5. sudo rm -rf ~/.node-gyp
6. sudo rm /opt/local/bin/node
7. sudo rm /opt/local/include/node
8. sudo rm -rf /opt/local/lib/node_modules
nvm 설치하기
그럼, nvm(Node Version Manager)을 사용하여 노드를 설치하는 방법을 알아보겠습니다. 먼저 터미널에서 아래의 명령어를 입력해 nvm을 설치합니다.
$ curl https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash 그 다음, 쉘을 재시작하거나, 아래의 명령어를 실행합니다.
$ source ~/.bash_profile 제대로 설치되었는지 확인해 볼 수 있습니다.
$ nvm --version
Node.js 설치하기
가장 최신의 stable 버전을 설치하려면, 다음과 같이 실행하면 됩니다. $ nvm install stable 혹은, 원하는 특정 버전을 설치하려면, $ nvm install v5.5.0 이런 식으로 실행하시면 됩니다.
설치할 수 있는 버전 목록을 보려면 다음과 같이 실행합니다.
$ nvm ls-remote 여러 버전의 노드를 설치하셨다면, 아래의 명령어로 원하는 버전으로 전환할 수 있습니다. $ nvm use v4.2.6
테스트
시험삼아 grunt-cli를 설치해보면 sudo 필요없이 설치가 되는 것을 볼 수 있습니다.
Remote Virtual Interface Tool starts and stops a remote packet capture instance for any set of attached mobile devices. It can also provide feedback on any attached devices that are currently relaying packets back to this host.
- Production(api.push.apple.com:443) / Development(api.sandbox.push.apple.com:443) HTTP/1.1 통신을 지원하지 않는다.
APNS 기능
기본적으로 Push Notification 은 단방향 서비스이다.
개발 서버에서 APNS 에 푸쉬 알림을 요청하면 APNS가 알아서 디바이스에 전송한다.
개발 서버는 APNS에 요청하면 할 일은 끝이다.
개발 서버는 APNS 에 푸쉬 알림을 요청할 때, 데이터 format 등에 대한 정상 여부는 리턴 받지 만 실제 도착여부에 대해서는 리턴을 받지 못한다.
사용자가 설정에서 알림을 끄더라도 알림이 출력되지 않지만 알림 수신은 된다.
사용자가 알림을 중지했는지 여부는 알 수 없다. (즉 앱에서만 알 수 있음)
APNS 유실되는 사례
디바이스 전원이 꺼져있는 경우 APNS의 QoS (Quality of Service) 컴포넌트는 디바이스 전원이 꺼져있는 경우, Notification을 잠시 저장했다가 다시 사용 가능해질 때 Notification이 전달되도록 하지만, 다 음의 경우 저장된 Notification이 폐기된다.
- 잠시 꺼져 있는 경우(얼마나 잠시인지 명시되지 않았음) , APNS는 Notification을 저장을
하는데 저장 가능한 Notificaiton은 하나다. 디바이스가 꺼졌있는 동안 하나의 앱에서 여러
개의 푸쉬 알림을 보낸다면, 제일 나중에 보내진 Notification만 저장되어 전달된다. 이전
에 저장된 Notification 은 폐기된다.
- 장시간 꺼져 있는 경우 (장시간이 얼마나인지는 명시되지 않았음), 저장된 Notification은 폐기된다.
APNS 서버 응답 코드
- 200 성공
- 400 잘못된 요청
- 403 인증서 또는 공급자 인증 토큰에 오류가 발생했습니다.
- 405 요청에 bad : 메서드 값이 사용되었습니다. POST 요청 만 을 지원합니다.
- 410 장치 토큰이 해당 항목에 대해 더 이상 활성화되지 않습니다.
- 413 알림 페이로드가 너무 큽니다.
- 429 서버가 동일한 장치 토큰에 대해 너무 많은 요청을 수신했습니다.
- 500 내부 서버 오류 503 서버가 종료되어 사용할 수 없습니다.
- 503 서버가 종료되어 사용할 수 없습니다.
Feedback Service
Feedback 서비스는 Notification 전달 실패 정보를 개발 서버에 알려주기 위한 서비스다. 푸쉬 알림이 앱이 삭제된 이유로 전달되지 못했다면 , APNS 는 이를 Feedback 서비스에 알리 고 Feedback 서비스는 실패한 디바이스의 토큰을 리스트에 저장한다.
APNS 에서 푸쉬 알림을 디바이스로 전송하기 전에 실패한 – data format error 등 – 경우에 는 Feedback 서비스의 리스트에 등록되지 않는다.(즉, 전송자체가 성공한경우 Feedback 서 비스 사용이 가능함) 개발 서버는 APNS 연결과는 별개로 Feedback 서비스에 접속해서 디바이스 토큰 리스트를 요 청해야 한다. Feedback 서비스는 리스트가 요청될 때마다 리스트를 전달한 후 리스트를 초기화 (clear) 한다.
Feedback 서비스로부터 받은 리스트의 데이터에는 timestamp 정보가 포함되어 있다. 이를 이용하여 리스트에 있는 디바이스 토큰이 Push Service에 재등록되어 있는지를 확인할 수 있 다. (푸쉬 알림을 보낸 시각과 디바이스 토큰의 timestamp 를 비교하면 디바이스 토큰의 재등록 여부를 확인할 수 있다.)
Feedback 서비스로의 요청을 위한 url, port 및 format 등의 내용은 아래 링크 참조.
You can easily use html inside attributedText property of the UILabel to easily do various text formatting.
let htmlString = "<font color=\"red\">This is </font> <font color=\"blue\"> some text!</font>"
let encodedData = htmlString.data(using: String.Encoding.utf8)!
let attributedOptions = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
do {
let attributedString = try NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
label.attributedText = attributedString
} catch _ {
print("Cannot create attributed String")
}
Type 5
In my case, I needed to be able to set different colors/fonts within labels frequently so I made a UILabel extension using Krunal's NSMutableAttributedString extension.