express의 next() 사용해보기

2016-04-28
블로그 UI가 개편중입니다. 참고해주세요.

express 프레임워크로 관리자 화면을 만든다고 생각해보자. 처음에는 간단히 시작할 예정이라 로그인 기능이 없었다. routes에 controler 하나로 어드민 페이지 매핑을 시키고 있었는데 이제 로그인 기능을 추가하려고 한다. http://localhost/admin/ 이하 path에 세션 확인 로직이 필요해졌다.

제일 먼저 고려해 볼만한 것은 controler 안의 모든 function에 체크 로직을 넣는 방식이다. 하지만 이런 방법은 관리가 어렵고 추후 수정할때 분명히 문제가 생긴다. 이런 경우에 express next() 사용을 고려해 볼 수 있다.

애초에 어드민 페이지와 관련하여 아래와 같이 app.js 의 path가 정의되어 있었다고 생각해보자.

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

여기에 모든 세션 체크 로직을 걸고 싶다면 아래와 같이 admin path 진입전에 app.get()next()를 사용하면된다.

app.get('/admin/:path?', function(req, res, next){
	console.log('admin contected.. admin path >> ' + req.params.path);
	next(); 
});
app.use('/admin', admin);

get()에서 url 주소를 획득 및 비교를 하여 /admin/ 이하 경로를 변수 path로 받는다. get()의 두번째 인자로 들어오는 펑션의 로직에 따라 next()를 사용해 다음 평션으로 request를 전달 할 수도 있고 특정 url에 매핑시킬 수도 있게 된다.

위의 소스를 수정했다. express-session를 npm을 이용해 설치하고 아래와 같이 router에 middleware를 구성하였다. 위에 사용됬던 app.get()은 모든 요청을 감지하기 위해 app.route().all() 로 수정되었다.

app.route(/^\/admin(?:\/(.*))?$/).all(function(req, res, next) {
	console.log('admin contected.. admin path >> ' + req.params[0]);
	var path = req.params[0] ? req.params[0].replace(/\//ig,'') : '';

	// 로그인 시도시
	if ( path == 'logintry' || path == 'login') {
		console.log('로그인 정보 없음으로 로그인 시도');
		next();
	} else if ( req.session.user ) { // && 
		console.log('로그인 정보 남아 있음.');
		next(); 
	} else {
		console.log('로그인 정보 없음 리다이렉트');
		req.url = '/admin/login';
		next(); 
	}
});
app.use('/admin', admin);

참고로 url로 넘어오는 path 중에 /admin/login는 로그인 페이지를 띄우는 화면이고, /admin/login/try는 실제로 유저가 입력한 패스워드와 DB의 패스워드를 비교하는 로직을 담고 있다. 로그인 성공시에는 session에 값을 추가하게된다.

2015.09.08 코드 수정본

잠을 자고 일어나 코드를 살펴보니 마음에 들지 않는다. 일단 로그인 경로가 /admin/ 경로 이하에 붙어 있다는것 부터가 세션을 체크하는 부분의 복잡성을 가중시킨다고 판단되어, app.js 에 login 만을 위한 router를 하나 더 추가하였다. admin과 login을 분리 시키니 특정 경로를 분기처리하던 로직을 심을 필요가 없어졌다. 특히나 위의 코드는 /admin/login은 페이지를 여는데 사용되고, /admin/login/try는 실제 로그인 체크로직을 담당하는데, 좀더 restful한 구성을 위해 get method를 통해 /login/ path로 접근하면 페이지를 열어주고, post method를 통해 /login/ path를 접근하면 로그인 체크로직을 태우도록 했다. 결과적으로 훨씬 유연해지고, url이 간결해졌다.

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

app.route(/^\/admin(?:\/(.*))?$/).all(function(req, res, next) {
	var path = req.params[0];
	console.log(path);

	if ( req.session.user ) { 
		console.dir( req.session.user );
		console.log('로그인 정보 남아 있음.');
		next();
	} else {
		var fullUrl = req.protocol + '://' + req.headers.host + req.originalUrl;
		console.log( fullUrl );
		console.log('로그인 정보 없음 리다이렉트');
		return res.redirect('http://' + req.headers.host + '/login/?redirect=' + fullUrl);
	}
});
app.use('/admin', admin);
Prev
Next

익스플로러 브라우저 close event 감지

요즘 socket.io를 이용해서 웹 채팅 화면을 구현중이다. ie 요구사항은 9 버젼부터이다. ie9는 웹소켓을 사용할 수 없어서 폴링방식을 이용하여 통신하는데 아래과 같은 close 상황일 때에 문제가 발생하였다. 탭 창이 닫힌 경우 F5를 눌러서 새로고침 한 경우 ctrl + r을 눌러서 새로고침...

자바스크립트 화살표 함수 (array function)

array func은 아래와 같은 간단한 형태를 보면 매우 간단하나, 복잡한 구문을 보면 매우 어렵게 느껴진다. 쉬운 array func 부터 복잡한 array func까지 절차적으로 밟아보자. array func array func의 특징을 정리해보자면 아래와 같이 간략하게 정리할 수 있다. function에 비해 구문이 짧다....

typescript에서 ie9 window.console bug 수정하기

ie와의 지독한 싸움이 아직도 끝나지 않았다. 예전에 ie9에서 작업할 때 꼭 디버깅 창을 열어야 javascript 소스가 실행되는 현상이 있었다. 알고보니 ie9 버그로써 디버그 창을 열어야 console을 인식하고, 디버그 창을 열지 않으면 console이라는 문자열이 js에 찍히는 순간 javascript가 에러나서 종료되는 현상이였다....

nodejs cluster 프로세스에서 데이터 공유하기

nodejs의 cluster는 기본적으로 child_process의 기능을 바탕으로 만들어졌다. master process와 worker process는 프로세스간 통신할때 일반적으로 사용되는 IPC를 사용하여 서로 통신한다. 또한 cluster 모듈을 사용할 때 공식적으로 프로세스간에 공유하는 메모리는 없다. 따라서 같은 메모리 주소값을 참조해서 데이터를 사용하는 방법 역시 없다. 하지만...