Node.js & Express에서 JWT(JSON Web Token) 사용하기 -2-

전 포스트에서 JWT에 관한 설명을 조금 했는데 이번엔 내가 어떻게 썻는지에 대해서 중점적으로 남겨보려한다.(나중에 까먹을까봐)

이 방법이 Best Practice인지는 잘 모르겠지만…

혹시 이것보다 더 좋은 방법이 있다면 댓글로 알려주세요!

프로젝트 생성

Express 프로젝트를 생성하고 npm install을 해주자.

1
2
$ express --ejs express-jwt
$ cd express-jwt && npm install

일단 껍데기만 있는 Auth API를 만들어 두자.

app.js에 다음과 같이 추가하자.

1
2
3
4
5
// app.js

const auth = require('./routes/auth');

app.use('/auth', auth);

routes/auth.js 파일을 생성하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// routes/auth.js

const express = require('express');
const router = express.Router();

/* Sign Up API
* - parameter email
* - parameter password
* - parameter username
*/
router.post('/signup', (req, res, next) => {
res.send('ok');
});

/* Sign In API
* - parameter email
* - parameter password
*/
router.post('/signin', (req, res, next) => {
res.send('ok');
});

module.exports = router;

JWT 미들 웨어

그리고 jsonwebtoken이라는 모듈을 설치하자

1
$ npm i --save jsonwebtoken

그리고 Express에서 미들웨어처럼 사용하기 위해 utils/tokenHelper.js라는 파일을 만들었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// utils/tokenHelper.js

const jwt = require('jsonwebtoken');

const TOKEN_SECRET = 'secret';

const tokenGenerator = (data, callback) => {
const token = jwt.sign(data, TOKEN_SECRET, {
algorithm: 'HS256',
expiresIn: 60 * 60 * 24 * 7
})
callback(token)
}

const isValid = (token, callback) => {
jwt.verify(token, TOKEN_SECRET, (err, decode) => {
if (err) {
// console.log("=========Token Helper: Can't decode token")
callback({isValid: false})
} else {
const exp = new Date(decode.exp * 1000)
const now = Date.now()
const day = (60 * 60 * 24 * 1000)
if (exp < now) {
// console.log("=========Token Helper: Expired Token")
callback({isValid: false})
} else if (exp < now + (5 * day)) {
// console.log("=========Token Helper: Generate New Token")
const newToken = module.exports.generateToken(decode.user.id)
callback({isValid: true, token: newToken, userInfo:decode})
} else {
// console.log("=========Token Helper: Token is valid")
callback({isValid: true, token: token, userInfo:decode})

}
}
})
}

const tokenHandler = (req, res, next) => {
const { token } = req.query

if(token) {
module.exports.isValid(token, (result) => {
req.userInfo = result;
next()
})
} else {
req.userInfo = {isValid: false}
next()
}
}

export default {
tokenGenerator,
isValid,
tokenHandler
}

Node.js & Express에서 JWT(JSON Web Token) 사용하기 -1-

두달만을 개발할 때 학습한 것들을 정리해서 올리기로 결심했다.

지금 생각나는 후보로는 다음과 같다.

  • JWT
  • Sequelize
  • Socket.io

더 있지만 일단 이 3가지의 기본 셋팅정도는 포스팅으로 올려놓으면 나중에 다시 보기에 좋을듯 싶다.

가장 처음으로 JWT를 다루기로 했다.

프로젝트 초기에는 Redis를 사용한 세션기반의 인증 방식을 사용하고 있었다.

하지만 뭔가 세련된 방법이 없을까 고민다하가 튜터님의 조언으로 JWT라는 것을 사용해 보기로 했다.

JSON Web Token

들어가기 전에 JSON Web Token의 개념을 알아두자.

JWT??

JSON Web Token은 공개된 업계 표준인 RFC 7519 방식으로 양 측의 클레임(Claims)을 안전하게 한다.
JWT.IO를 사용하여 JWT를 디코드, 검증 및 생성할 수 있다.

Claim이라는 용어가 처음에 낯설었지만 서버와 클라이언트가 주고받는 정보나 메세지 정도로 생각하면 된다.

JSON 객체로된 클레임은 디지털로 서명되었기 때문에 검증되고 신뢰할 수 있다고 한다.

또한 다음과 같은 개념을 가진다.

  • Compact: JWT는 크기가 작기 때문에 URL, POST 파라미터 또는 HTTP Header에 포함될 수 있다. 크기가 작아 전송 속도 또한 빠르다고 할 수 있다.

  • Self-contained: JWT는 Payload에 필요한 데이터를 포함한다. 따라서 토큰을 생성할 때 데이터베이스에서 정보를 가져오면 그 다음부터는 데이터베이스에 질의를 하지 않아도 된다.

언제 JWT를 사용할까?

  • Authentication: JWT를 사용하는 가장 일반적인 시나리오다. 유저가 처음 로그인을 하면, 유저 정보를 포함한 JWT를 생성해 발급해준다. 그 후 유저는 각 요청에 발급받은 토큰을 포함해 보내는데, 서버에서 토큰을 기반으로 유저의 정보, 허용되는 경로 등의 정보를 데이터베이스의 접근없이 알 수 있다. 또한 세션을 유지하지 않아도 되므로 서버의 비용이 줄어들 수 있다.

  • Information Exchange: JWT는 공개 키나 비밀 키로 서명할 수 있기 때문에 안전하게 정보를 교환할 수 있다. 게다가 서명이 헤더와 페이로드를 사용하여 계산되므로 내용이 변경되었는지도 판별할 수 있다.

JWT의 구조

JWT는 점(.)으로 구분되는 세가지 요소를 가진다.

  • Header
  • Payload
  • Signature

그래서 결과적으로 xxxxx.yyyyy.zzzzz 형태를 가지게 된다.

JWT의 첫 번째 부분은 Header 로, 헤더는 2가지 속성 값을 가진다.

  • alg: 해싱 알고리즘. 보통 HMAC SHA256 혹은 RSA가 사용된다.
  • typ: 토큰의 타입 = JWT

다음과 같이 Header를 생성할 수 있다.

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

Payload

두 번째 부분은 처음에 클레임을 포함하는 Payload가 들어가게 된다.

클레임은 3가지로 구분할 수 있는데, 다음과 같다.

  • Reserved claims: 이것은 필수는 아니지만 JWT를 사용함에 있어 권장되는 미리 정의된 클레임 세트이다. iss(발행자), exp(만료 시간), sub(주제), aud(고객) 등을 포함한다.

  • Public claims: 이것은 JWT사용자끼리 충돌을 방지하기 위한 값을 포함한다. 보통 충돌을 방지하기 위한 네임스페이스를 사용한다.

  • Private claims: 정보를 담는 클레임.

다음과 같이 Payload를 생성할 수 있다.

1
2
3
4
5
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

Signature

서명을 만들기 위해서는 인코딩된 헤더, 인코딩된 페이로드, 시크릿 키, 헤더에 지정된 알고리즘을 가진다.

예를 들면 다음과 같이 서명을 만들 수 있다.

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

이렇게 만든 서명으로 메세지가 변경되지 않았음(무결성)을 확인하는데 사용할 수 있다.

확인해보자

JWT Debugger에서 JWT를 디코딩해보거나, 검증하거나 생성해볼 수 있다.

JWT를 어떻게 쓰는…?

클라이언트는 서버에 인증 요청한다.

인증이 성공된다면 서버에서 사용할 클레임을 포함한 JWT를 생성해 클라이언트에게 넘겨준다.
일반적으로 로컬 저장소에 저장되지만 쿠키를 사용할 수도 있다.

그리고 클라이언트에서 인증이 필요한 어떠한 요청을 할 경우 요청 헤더에 다음과 같이 추가해준다.(Bearer는 토큰 타입을 결정하는 자리인데 OAuth2의 토큰 인증 방식이다.)

1
Authorization: Bearer <token>

서버는 요청 헤더에서 토큰 값을 디코딩해 필요한 정보를 가져올 수 있으며 그에 따른 요청 응답을 클라이언트에게 보내준다.

그래서 JWT를 사용하면

서버에서 토큰이 유효하다고 판단하면 클레임들을 디코딩해 정보를 가져올 수 있다.
서버의 메모리와 같이 다른 곳에 따로 관리를 하지 않아도 된다는 뜻이다.

따라서 Stateless한 서버를 만들 수 있게 된다.
그러므로 서버의 확장이 용이하고 요청 도메인에 관해 문제가 되지 않아 CORS문제를 생각하지 않아도 된다.

하지만 클레임셋이 증가하면 자연스레 토큰의 길이가 증가하게 되는데 요청 헤더에 토큰을 삽입하는 방식이므로 과한 오버헤드가 발생할 수 있다.

다음 포스팅

원래 프로젝트에서 사용한 예제도 포함하려 했는데

생각보다 JWT에 대한 설명이 길어져 다음 포스팅으로 넘기려한다.

간단한 예제긴 한데 나름 고민해서(?) 만들었고 나중에도 써먹기 위해 기록해둘 생각이다.

Refer

부스트캠프(Boostcamp) 2차 후기

부스트캠프 2차가 끝났다.

약 3주간 프로젝트 기간으로 진행되었는데 진짜 시간이 어마어마하게 빨리 갔다.

어떤 프로젝트를 할지 고민고민 끝에 두달만이라는 자취방 공유 어플리케이션을 만들어보기로 했다.

부스트캠프 2차 == 프로젝트 이기 때문에 이 글은 거의 두달만 개발 후기라고 할 수 있다.

기획

사실 고백하자면 이 두달만이라는 서비스는 작년 가을학기에 학업만 하기에 지루했던 학교생활을 탈피하기 위해(?) 기획한 서비스이다.

같은 랩실의 친구(나에게 부스트캠프를 추천해준 친구)에게 학교생활이 너무 지루하다며 징징댔었는데,
그런 나에게 그럼 우리 뭐 만들어보자라고 이런 아이디어를 생각했다.

안쓰는 자취방의 기간동안 다른사람이 살면서 월세를 줄일 수 있다면 얼마나 좋을까?

물론 에어비앤비가 그것을 잘 해결해 줄 수 있지만 우리나라에서는 불법이란다.

그러면 이 서비스 또한 불법이 아닐까 고민이 많이 되었지만 그때 결론은 일단 만들어보자 였다.

하지만 중간고사가 겹치고 논문에 여러가지 일이 겹치다보니 실 개발은 거의 못하고 방치되어 있었다.

그래서 이번에 부스트캠프에서 다시 한번 해보면 어떨까싶어 이 두달만이라는 서비스를 만들기로 결정했다.

프로젝트 기간은 3주로 산정이 되어있었지만 거의 첫주는 기획과 디자인 그리고 일정을 잡는데에 쓴것 같다.

UI/UX를 많이 신경쓰긴했는데 기존의 부동산 앱(직방, 다방)을 많이 사용해본 상태여서 거의 흡사한 형태의 앱이 디자인 되었다.

앱의 프로토타입을 보려면 이 링크로 가보면 된다.

개발

기획에 1주일을 날리니 개발을 할 수 있는 기간은 2주정도가 남았다.

처음에 이게 가능한 스케줄인가… 내가 너무 일을 벌린것 아닌가 싶었는데 막상 하고나니 되긴 됐다.(건강은 나빠진것 같다.)

대충 개발 스택들을 나열하자면 다음과 같다.

Swift3

이번에 부스트캠프를 통해 처음 접해본 Swift
아직 익숙하지는 않지만, 나름 두달동안 열심히 한 덕분에 프로젝트가 거의 끝나갈 시점에는 생산성이 처음보다 많이 나아져있었다.

  • MapKit
    • 여러 지도 서비스를 사용해보기보다 빠르게 사용할 수 있는 지도를 택했다. API문서화가 잘 되어있고 간편하게 사용할 수 있었다.

그 외에 여러 CocoaPod을 사용했다.

  • Alamofire, AlamofireObjectMapper
    • 서버와 네트워킹을 할때 사용했다.
    • NSURLSession을 사용하는 것보다 코드량도 줄일 수 있고, 더욱 직관적인 코딩을 할 수 있게 해준다.
  • Nuke
    • 이미지 로더로 방 사진을 로딩할 때 사용했다.
  • GooglePlaces
    • 지도상에서 지역을 검색해서 이동하거나, 방을 등록할때 주소를 검색할 수 있게 사용했다.
    • 등록시 주소검색은 다음 주소 검색을 사용하는 것으로 바꿀 예정.
  • FontAwesome.swift
    • 폰트어썸!
  • SwiftRangeSlider
    • 필터에서 가격을 필터링하기 위해 범위 슬라이더로 사용했다.
  • Socket.IO-Client-Swift
    • 채팅을 위해 Socket.IO 클라이언트로 사용했다.

Node.js + Express + Socket.IO

사용해본 경험이 있는 언어와 프레임워크로 백엔드의 부담을 최소화했다.
안그래도 시간이 부족한데 백엔드에서 시간을 빼았기기 싫었기 때문이다.

Auth를 위해 JWT를 사용했고 처음 로그인이나 회원가입이후에 모든 요청에는 토큰을 포함해 인증을 했다.

Node.js에서 ORM을 사용하기 위해 Sequelizer를 사용했는데 생각보다 학습하는데 시간이 필요했다.
어찌어찌 구현은 했는데 나중에 리팩터링을 해야겠다.

Azure

별다른 이유없이 크레딧이 남아서 썻다.

MariaDB

처음에는 클라이언트에도 Realm을 써보고 백엔드에도 Realm을 발라보자! 했지만 Geo 거리 계산같은 쿼리는 지원하지 않는듯 해서 RDBMS를 사용하게 되었다.

Nginx

사진처럼 정적인 파일은 어플리케이션 서버에서 처리하기보단 그 앞에 웹 서버를 둬서 처리하면 어플리케이션 서버의 효율을 높일 수 있다.

데모데이

그렇게 순식간에 개발기간이 끝났다.

데모데이는 토요일에 있었는데 그 전날엔 거의 밤을 새서 앱을 마무리하고 소개페이지와 데모영상을 만들수밖에 없었다.(평소에 좀 더 할껄…)

데모영상을 나름 신경써서 만들긴했는데 데모데이날 다른사람들의 영상을 보니 내 영상은 정말 초라했다.

다른사람들이 한 프로젝트를 그날 처음봤는데 다들 재미있는 프로젝트들을 하고 있었고 완성도도 어마어마했다.(부스트캠프 iOS반 짱짱)
역시 세상은 넓고 고수는 많다

네트워킹데이

드디어 부스트캠프의 마지막행사 네트워킹데이가 다가왔다.


드디어 끝이 보인다

두달동안 다들 고생해서 그런가 피곤해보이는 사람들이 많았다.(물론 나포함)

행사는 다음과 같이 진행되었다.

1부

  • 오프닝 및 기업소개
  • Android 발표와 부스 세션
  • Break
  • iOS 발표와 부스 세션
  • 마무리

2부

  • 안내 및 다과
  • 수료식

이름만 들어도 알만한 기업들과 조금은 생소하지만 재밌는 것을 하고 있는 기업들도 많이 참여해서 부스트캠프에서 인재를 발굴해가고 싶다고 했다.(부디)

그리고 Android 발표와 부스 세션시간이 지나고 iOS 발표와 부스 세션시간이 되었다.

저번 데모데이때 좋은 평가를 받은 6개의 프로젝트의 발표가 이루어졌다.(내 플젝은 안타깝지만 ㅠㅠ)

그리고 각 프로젝트별로 부스를 설치해 자기 앱을 발표하는 시간이었는데, 내 부스에는 아무도 오지 않으면 어떡하나 싶었지만 매우 감사하게도 몇몇분이 방문해 앱 설명을 듣고 응원도 해주시고 궁금한 것들을 물어보셨다.
또 다녀가신 분들 중 한분께서 창업엔 관심이 없냐며 자기 회사의 서비스와 어떻게 협력하면 좋을 것 같다고 까지 말씀해주셔서 되게 감사하고 기억에 남았다.

사실 데모데이가 끝나고 앱을 더 수정할 것이 남아있었지만 조금 의욕이 한풀 꺾여있었는데, 다시금 동기부여를 해주신것 같다.(런칭까지 빠샤!)

그렇게 iOS 발표까지 끝나고 1부가 끝났다.

2부가 시작하기 전에 저녁으로 피자를 줬다.(🍺까지 있었다면 참 좋았을텐데)

저녁을 해결하고 원티드의 황리건 님의 특강이 있었다.
개발자 커리어의 시작점에서 라는 주제로 여러가지 좋은 말씀을 해주셨는데 그 중 시장가치가 중요하다는 말이 제일 기억에 남는다.

지금은 핫한 기술일지라도 언제 사라질지 모른다며 플래쉬를 예로 들어 아주 기억에 남게 설명해주셨다.

그리고 드디어 마지막 수료식이 남았다.

수료증을 받고 사진을 찍으니 이제 진짜 끝이구나 싶었다.

수료식 중간에 갑자기 베스트 부스터였나? 열심히 한 사람 시상식이 있었는데 영문을 알수없게도 나도 수상하게 되었다.(감사합니다)

그렇게 수료식도 끝나고 팀별로 사진도 찍고나니 행사가 끝났다.


라떼 팀 수고하셨슴다~

진짜 후기

진짜 두달이란 시간동안 말그대로 부스트했던 것 같다.

앱 개발은 1도 모르던 나였지만 제법 그럴듯해보이는 앱을 하나 제작했다.

같이 공부하고 매일매일 회의하면서 서로 피드백도 주면서 도와줬던 팀원들, 엄청 질문을 많이 해도 하나하나 다 알려주셨던 이재훈 튜터님, 주말마다 특강을 준비해주셨던 다른 튜터님들 그리고 잘 진행되도록 프로그램을 짜준 부스트캠프 운영진들 덕분인 것 같다.

이제 시작인 2017년 시작이 좋은 것 같다.

두달만은 일단 앱스토어 등록 시도는 해봐야겠다.

JavaScript에서 string을 replaceAll 하고싶을 때

javascript에서 스트링을 replace할때 당황스러웠던 적이 있었다.

1
2
> "javascript".replace("a","b")
'jbvascript'

저렇게 앞의 한글자만 replace를 해주기때문이다.
어떻게하면 깔끔하게 할 수 있을지 구글링하다보니 역시 답이 나왔다.

정규식을 이용해서 replace를 하면되는데

1
2
> "javascrip".replace(/a/gi,"b")
'jbvbscript'

저 뒤에 있는 gi는 정규표현식 옵션이다.

  • g : global
  • i : ignore case
  • m : multiline

좀 찾아보니 정규표현식을 쓰지않고 다른방법으로 쓰는 경우도 있었다.

1
2
3
4
5
6
function replaceAll(str, searchStr, replaceStr) {
return str.split(searchStr).join(replaceStr);
}

> replaceAll("javascript", "a", "b")
'jbvbscript'

이렇게 또 하나 알아갑니다.

Refer

라즈베리파이와 페이스북 메신저를 사용한 온습도 모니터링 봇 개발

집이 1층인데 햇빛도 잘 안들어오고 환기도 잘 안되서 거의 항상 습하고 곰팡이도…
어느 주말에 그날도 역시 습한 집에 누워있다가 갑자기 집이 도대체 얼마나 습한건지 궁금해졌다.
어떻게 할까 고민하던 중 작년에 IoT관련 세미나에서 받은 라즈베리파이와 키트를 살펴보니 온습도 센서를 발견했다.(이거다!)
그래서 무작정 개발해보기로 했다.

개발 구상

  • 라즈베리파이와 온습도 센서를 통해 데이터 가져오기
  • 온습도 데이터를 저장하고 웹에서 간단히 보여줄 수 있는 웹 서버 개발
  • (후에 추가된) 온습도 모니터링해서 알려주는 봇 개발

이렇게만 하면 되겠지..?

라즈베리파이

일단 라즈베리파이에 Thing+가 셋팅되어 있었는데, 그 API를 활용해서 데이터를 불러오려고 시도했다. 하지만 뭔가 잘못된것인지 라즈베리파이와 연동이 안되서 실패했다.
그래서 그냥 빵판에 연결해서 데이터를 뽑아보는 방법으로 바꿨는데 하다보니 좋은 오픈소스도 있어서 쉽게 할 수 있었다.

회로도

[출처] Adafruit

위 그림처럼 회로를 연결하고 테스트를 해봤다. 필요한 소스는 Adafruit_Python_DHT 여기에서 구할 수 있었다.

1
2
$ python AdafruitDHT.py 11 4
Temp=31.0* Humidity=42.0%

그리고 저 라이브러리를 사용해서 얻은 온습도 데이터를 10초마다 보낼 수 있게 crontab을 사용했다.

1
2
3
4
5
6
7
8
9
10
11
12
import Adafruit_DHT
import requests
import datetime

humidity, temperature = Adafruit_DHT.read_retry(11, 4)

data = {'humidity': humidity, 'temperature': temperature, 'ticktime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

url = 'SERVER_URL'

res = requests.post(url, data=data)
res.content

웹 개발

라즈베리파이로 자체 웹서버를 올려서 사용할까도 생각했었는데 공유기로 연결을 해둬서 그런가 IP포워딩등 여러가지 설정할것이 있어서 그냥 Microsoft의 Azure를 사용하기로 했다.
기본적으로 Node.js + Express 로 웹서버를 구축하고 라즈베리파이에서 전송한 데이터를 몽고디비에 저장하는 API하나를 만들고, 웹 페이지에서 마지막 업데이트 시간과 온도, 습도를 보여주는 페이지를 개발했다.
시간대별로 온습도가 어떻게 변하는지 보고싶어서 plotly.js 라이브러리를 사용해서 그래프를 쉽게 만들었다.
다만 모바일 화면에서 너무 찌그러져보이는 단점이 있는데 커스터마이징을 할 수 있는 d3.js로 나중에 바꿀 생각이다.

생각보다 빠르고 쉽게 구축을 했는데, 막상 웹 페이지에서 보는것만 있으니 조금 별로였다. 쾌적한 온습도 범위를 벗어나면 내가 알 수 있는 어떤 장치가 필요하다고 생각했다.

OMSH WEB

메신저 개발

사실 처음에는 (이미 해봤던)슬랙 API를 활용해서 만들려고했다.
하지만 좀 새로운 것이 없을까 하다가 슬랙과 유사한 서비스인 잔디에도 비슷한 기능이 있을 것 같아서 찾아보니 역시 있었다.
그래서 내가 원하는 습도가 넘어가면 알림을 Jandi Webhook 을 통해 알림을 줄 수 있게 해놨다.

Jandi Webhook Noti

오예!

그런데 이렇게 막상 만들고나니 습도가 높아졌을 때 알림이 오는건 좋은데 내가 원할 때마다 웹 페이지에 접속하고 보는게 생각보다 불편했다.
그래서 뭔가 대안이 없을까 생각을 하다가 요즘 핫하다는 Facebook Messenger 로 온습도를 알려주는 Bot을 만들기로 했다.

막상 한다곤 했지만 아는게 없어서 일단 이 링크를 따라했다.
생각보다 훨씬 빠르고 간단하게 개발이 완료되었는데, 여기에 뭐 쓰기도 애매한 수준이라 생략하겠다.(저 링크에 더 자세히 나온다.)

OMSH Bot

Refer

npm으로 Nodejs stable 버젼 설치하기

nodejs를 설치해야 하는데 apt-get install nodejs를 하면 계속 구버젼이 깔린 적이 있었다.

1
2
$ nodejs --version
v0.10.25

( ??? 매우 당황)

이걸 어찌해야하나… 내가 쪼렙 개발자라고 구버젼만 써라 이건가…

하지만 개발력이 딸리면 구글링만 잘해도 중간은 간다고 생각한다.

그렇게 열심히 구글링을 한 결과 내가 원하는 것을 얻어냈고 나는 승리했다.

해결 방법

1. 캐시를 초기화

1
2
$ sudo npm cache clean -f
npm WARN using --force I sure hope you know what you are doing.

2. npm module n 설치 - Interactively Manage All Your Node Versions

1
2
3
$ sudo npm install -g n
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
n@2.1.3 /usr/local/lib/node_modules/n

3. Nodejs 설치!

1
2
3
4
5
6
7
$ sudo n stable

install : node-v6.2.2
mkdir : /usr/local/n/versions/node/6.2.2
fetch : https://nodejs.org/dist/v6.2.2/node-v6.2.2-linux-x64.tar.gz
######################################################################## 100.0%
installed : v6.2.2

4. Binary 링크 설정

1
$ sudo ln -sf /usr/local/n/versions/node/6.2.2/bin/node /usr/bin/node

5. 확인

1
2
$ node --version
v6.2.2

6. 추가로 stable버젼이 아닌 내가 원하는 버젼의 Nodejs도 설치할 수 있다.

1
$ sudo n {version}

Refer

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×