Node.js는 이미 이벤트 드리뷴 방식과 비동기 통신적에 이미 많은 인기를 끌고 있는 기술이다.
하지만 현재의 웹페이지는 그냥 빠르다고 하는것으로는 충분함을 채울수가 없다.
만약 우리가 새로운 웹사이트를 만드는것을 node.js를 이용해서 만들려고 계획 중이라면,
지금 부터 소개할 10가지 tips들을 참고하는것이 어떨까 싶다.
1. Run in Parallel
웹 응용 프로그램을 구축하는 동안, 때때로 데이터를 가져오는 여러 내부 API를 호출할 때가 있다.
예를들어 대시보드를 생각해보면, 대시보드가 렌더링 되는 동안 아래과 같은 가상 호출을 실행될수 있다.
The user profile(사용자 프로필) – getUserProfile()
The recent activity(최근 활동내역) – getRecentActivity().
Subscriptions(구독) – getSubscriptions()
Notifications(알림) – getNotifications()
이러한 세부정보를 검색하기 위해 각 기능에 대한 별도의 미들웨어를 만들고 대시보드 경로로 연결한다.
우리는 알아시피 Node.js로 인해 비도기 특성으로 병렬로 여러 기능을 실행하는데 매우 효율적이다.
우리는 이것을 이용할것입니다. 위의 4가지 함수들이 서로 영향을 미치지 않게 병렬적으로 실행되도록 할것이다.
병렬로 실행하는것은 미들웨어의 수를 크게 줄일수 있어 속도를 향상시킬수 있다.!
병렬 실행을 위해 Async.js 모듈을 사용하면 된다.
function runInParallel() {
async.parallel([
getUserProfile,
getRecentActivity,
getSubscriptions,
getNotifications
], function(err, results) {
//This callback runs when all the functions complete
});
}
async.js 모듈에 대해서 자세한 내용은 Github에서 확인하면 되겠다.
2. Go Asynchronous
Node.js는 싱글 스레드 기반으로 만들어져 있다. 이 때문에 사실 비동기가 아닌 동기코드는 잠제적으로 전체 응용 프로그램을 락을 걸수 있다. 예를 들어 파일시스템의 API의 대부분은 동기방식과 비동기 방식이 모두 지원된다. 파일에 관련된 작업을 하는동안 동기 및 비동기 적으로 모두 수행할수 있는데 다음 파일 읽기에 대한 코드의 예를 보자
// Asynchronous
fs.readFile('file.txt', function(err, buffer) {
var content = buffer.toString();
});
// Synchronous
var content = fs.readFileSync('file.txt').toString();
실행 타임이 긴 동기직업을 수행할 경우, 작업이 완료 될때까지 메인스레드는 차단되게 된다. 이렇게 되면 전체 Node.js어플리케이션의 성능이 저하되는 원인이 된다. 그래서 항상 비동기 형식이 지원되는 API라면 반드시 아주 반드시 비동기 코드를 이용해 APi를 호출하긴 바란다.
3. Use Caching
변경되지 않는 데이터를 자주 호출하는 경우 성능 향상을 위해 캐시를 사용할수 있다.
다음 예를 들어보자 최근 게시물을 표시하는 코드이다.
var router = express.Router();
router.route('/latestPosts').get(function(req, res) {
Post.getLatest(function(err, posts) {
if (err) {
throw err;
}
res.render('posts', { posts: posts });
});
});
만약 블로그에 글을 자주 게시 하지 않을 경우, 게시물 배열을 캐시에서 지울수 있다.
다음 예는 Redis라는 모듈을 이용해서 캐싱을 구현하는 방법이다. Redis는 DB의 일종인데 본 블로그내에
Redis에 관한 정보가 있다. 참고하길 바란다.
Redis가 먼저 서버에 설치 되어있어야 한다. 그후 키 / 값 쌍을 저장하기 위한 클리이언트에서는 node_redis를 사용할수 있다.
var redis = require('redis'),
client = redis.createClient(null, null, { detect_buffers: true }),
router = express.Router();
router.route('/latestPosts').get(function(req,res){
client.get('posts', function (err, posts) {
if (posts) {
return res.render('posts', { posts: JSON.parse(posts) });
}
Post.getLatest(function(err, posts) {
if (err) {
throw err;
}
client.set('posts', JSON.stringify(posts));
res.render('posts', { posts: posts });
});
});
});
게시물이 Redis캐시에 존재 한다면, 캐시에서 게시물의 배열을 얻게 되고 그렇지 않다면 DB로 부터 콘텐츠를 검색하고 이를 다시 Redis 로 캐싱한다.
4. Use gzip Compression
gzip압축을 설정하놓으면 Node.js의 웹 어플리케이션에 아주 상당한 성능의 영향을 줄수 있다. GZIP가 호환 되는 브라우저가 특정 응답을 위한 호출을 할때 서버는 응답을 압축해서 브라우저에게 보내주는 모듈이다.
gzip을 사용하지 않는다면 눈에 띄게 브라우저에서 응답을 보여주는 시간의 차이를 볼것이다.
Express 프레임 워크게서 정적 컨텐츠로 내장 제공하기 위해 express.static() 의 미들 웨어에 내장시키면 된다.
설정을 켜는 정도의 수준이므로 굉장히 쉽다.
var compression = require('compression');
app.use(compression()); //use compression
app.use(express.static(path.join(__dirname, 'public')));
5. Use Client Side Rendering When Possible
MVC/ MVVM 프레임워크의 등등과 함께 AngularJS, Ember, Meteor 등등 과 같이 강력한 클라이언트가 많이 생겨났다.
이런 프레임 워크들은 단일 페이지를 만들어 내는것에 대해서 굉장히 쉽게 접근 할수 있도록 해주었다.
기본적으로 서버측에서 랜더링을 하고 API를 노출시켜 JSON을 클라이언트로 응답해주는 구조보다는
클라이언트측에서 UI를 표시하기 위한 정보가 들어있는 JSON만 받아서 UI 랜더링은 클라이언트가 처리 하는 방식이 더욱 효과적이다.
6. Don’t Store Too Much in Sessions
전형적인 Express 웹 어플리케이션에서 세션 데이터는 메모리에 저장하는것을 기본으로 한다. 사용자가 세션에 너무 많은 데이터를 저장할 때, 서버에 상당한 오버헤드를 야기할 수 있다. 따라서 다른 종류의 스토리지를 생성해서 세선에 들어있는 데이터를 관리 해보자 세션에 들어있는 데이터를 최소화 하도록 노력하는것이 중요하다.
예를들어 사용자가 어플리케이션에 로그인을 할떄 세션에 전체 개체를 저장하는 대신에 사용자의 ID를 저장하도록 한다. 그후에 ID를 통해 DB에서 사용자의 정보를 검색하는 방식을 채택하자 , 또한 세션 데이털르 저장하도록 MongoDB 또는 Redis를 추천할수 있다.
7. Optimize Your Queries
만약에 당신이 홈페이지에서 최신 게시물을 표시하는 블로그 운영자라고 가정해 보자.
Mongoose를 이용하면 새로운 데이터를 표시하는것이 편할 것이다.
Post.find().limit(10).exec(function(err, posts) {
//send posts to client
});
그러나 문제는 몽구스에서 Find()함수는 객체의 모든 필드를 가져와 홈페이지에 필요하지 않은 포스트 객체를 가져올수도 있다는것이다. 특정 게시물에 대한 의견의 배열을 가지고 하나의 필도를 코멘트로 지정해보자.
필요한 정보만 찾아올수 있도록 하며 가져오는 동안 다른 쓸데 없는것이 있지 않아 확실한 속도개선의 여지를 보여준다.
다음 처름 쿼리를 최적화 하자
Post.find().limit(10).exclude('comments').exec(function(err, posts) {
//send posts to client
});
8. Use Standard V8 Functions
9. Use nginx in Front of Node
Nginx는 Node.js의 서버의 부하를 줄일 수 있는 작고 가벼운 웹 서버이다. 노드 대센에 정적 파일제공, 정적 콘텐츠를 제공하기 위해 nginx를 사용할 수있다. 또한 전체 응답의 크기가 작기 때문에 Gzip압축 이용하는것을 nginx에서 설정할수가 있다.
어플리케이션의 경우에 따라 속도개선을 위해 nginx를 사용해보자.
10. Minify and Concatenate JavaScript