Express.js는 HTTP 응답을 클라이언트에게 전송하는 방법을 제어할 수 있는 강력한 응답 객체를 제공합니다. 자주 사용되는 두 가지 메서드인 res.redirect
와 res.render
에 대해 알아보겠습니다. 이 글에서는 이러한 메서드들의 작동 방식을 설명하고, 주요 사용 사례를 강조하며, 따라야 할 중요한 보안 조치들을 논의합니다.
res.redirect
res.redirect
메서드는 브라우저에게 다른 URL로 이동하도록 지시합니다. 이 리다이렉션은 애플리케이션 내의 상대 경로나 완전히 다른 사이트의 절대 URL로 이동할 수 있습니다. HTTP 상태 코드를 지정하지 않으면 기본적으로 Express는 302("Found") 응답을 보냅니다.
리다이렉트 트리거:
res.redirect(url)
을 호출하면 Express는 응답에 Location
헤더를 설정합니다. 그러면 클라이언트의 브라우저가 해당 URL로 새로운 요청을 보냅니다.
상대 URL vs. 절대 URL:
Express는 완전한 URL(예: http://example.com
)과 상대 URL(예: /admin
) 모두를 지원합니다. 상대 URL을 사용할 때는 브라우저가 현재 URL을 기준으로 해석하므로, 후행 슬래시가 최종 경로 해석에 영향을 미칠 수 있습니다. 예기치 않은 탐색 동작을 방지하기 위해 이 점을 유의하세요.
// 같은 애플리케이션 내의 상대 URL로 리다이렉트
res.redirect('/admin');
// 외부 사이트로 리다이렉트
res.redirect('http://example.com');
// 특정 HTTP 상태와 함께 리다이렉트 (예: 301 영구 이동)
res.redirect(301, 'http://example.com');
// 현재 URL을 기준으로 한 상대 경로로 리다이렉트
res.redirect('post/new');
// 요청의 이전 페이지로 리다이렉트 (이전 페이지가 없으면 "/"로 이동)
res.redirect('back');
오픈 리다이렉트 방지:
리다이렉트 URL이 사용자가 제공한 데이터로 구성되는 경우, 항상 입력값을 검증하고 정제하세요. 검증되지 않은 리다이렉트는 공격자가 사용자를 악성 웹사이트로 보내도록 조작될 수 있습니다.
상대 URL 해석 이해:
브라우저가 현재 요청 URL을 기준으로 상대 URL을 처리하므로, URL을 동적으로 구성할 때 사용자가 예기치 않은 목적지에 노출되지 않도록 주의하세요.
res.render
res.render
메서드는 서버 측 뷰 렌더링에 사용됩니다. 뷰 템플릿과 제공된 데이터를 결합하여 Express는 클라이언트에게 전송될 HTML을 생성합니다. 이 메서드는 Pug, EJS, Handlebars와 같은 템플릿 엔진을 활용합니다.
템플릿 엔진 통합:
res.render
의 첫 번째 인수는 뷰 이름(구성된 views
디렉터리를 기준으로 한 파일 경로)입니다. 파일 확장자를 지정하지 않으면 Express는 뷰 엔진 설정을 사용하여 템플릿 파일 유형을 결정합니다.
로컬 변수:
템플릿에 변수를 제공하기 위해 두 번째 인수로 객체를 전달할 수 있습니다. 예를 들어, { name: 'Tobi' }
는 템플릿 내에서 name
변수를 사용할 수 있게 합니다.
콜백 사용:
선택적으로 콜백 함수를 제공할 수 있습니다. 이 모드에서는 res.render
가 렌더링된 HTML 문자열과 오류를 반환하지만 자동으로 응답을 보내지는 않습니다. 개발자가 응답을 처리해야 합니다(일반적으로 res.send(html)
를 호출).
// 뷰를 렌더링하고 자동으로 HTML 응답 전송
res.render('index');
// 로컬 변수와 함께 뷰 렌더링
res.render('user', { name: 'Tobi' });
// 콜백을 사용하여 뷰를 렌더링하고 결과를 수동으로 전송
res.render('index', (err, html) => {
if (err) {
return next(err); // 오류를 적절히 처리
}
res.send(html);
});
뷰 경로에 사용자 입력을 절대 신뢰하지 마세요:
뷰 파일 경로는 절대로 신뢰할 수 없는 사용자 입력으로 구성해서는 안 됩니다. 사용자 입력이 경로를 지정하도록 허용하면 디렉터리 순회 공격이나 무단 파일 접근이 발생할 수 있습니다.
로컬 변수의 데이터 검증:
클라이언트 측에서 렌더링되는 데이터는 크로스 사이트 스크립팅(XSS) 취약점을 방지하기 위해 적절히 이스케이프되거나 검증되어야 합니다. locals
객체에 전달되는 모든 변수가 안전한지 확인하세요.
민감한 데이터 노출:
뷰에 전송되는 데이터에 민감한 정보(비밀번호, API 키, 개인 데이터 등)를 포함하지 않도록 주의하세요.
뷰 캐싱:
프로덕션 환경에서는 성능 향상을 위해 기본적으로 뷰 캐싱이 활성화됩니다. app.set('view cache', true)
(또는 개발 중에는 false
)를 사용하여 이 동작을 제어할 수 있습니다.
모든 사용자 입력 검증:
리다이렉트에 사용되거나 뷰 렌더링에 전달되는 사용자 입력값은 항상 유효성 검사를 수행하고, 데이터를 정제한 후, 필요한 경우 인코딩해야 합니다.
콘텐츠 보안 정책(CSP) 구현:
엄격한 콘텐츠 보안 정책을 사용하여 보안을 강화하세요. 이는 콘텐츠를 로드할 수 있는 소스를 제어하여 XSS 위험을 완화하는 데 도움이 됩니다. Helmet과 같은 라이브러리를 사용하면 CSP 구성이 간단해집니다.
Express 설정 검토 및 구성:
공식 Express 문서에서 제공하는 추가 보안 지침을 숙지하세요.
res.redirect
:
클라이언트의 위치를 변경해야 할 때 이 메서드를 사용하세요. 리다이렉트에 사용되는 URL이 오픈 리다이렉트 취약점으로 이어질 수 있는 조작으로부터 안전한지 항상 확인하세요.
res.render
:
서버 측 HTML 생성에 사용하세요. XSS와 파일 시스템 접근 위험을 방지하기 위해 뷰 경로나 템플릿 변수에 검증되지 않은 사용자 입력값을 절대 노출하지 마세요.
이러한 모범 사례와 보안 고려사항을 따르면 더 견고하고 안전한 Express.js 애플리케이션을 구축할 수 있습니다.