In a classic web app the backend serves the frontend/graphics to the browser, a very common approach in the Node’s world is to use Express static middleware for streamlining static files to the client. BUT – Node is not a typical webapp as it utilizes a single thread that is not optimized to serve many files at once. Instead, consider using a reverse proxy (e.g. nginx, HAProxy), cloud storage or CDN (e.g. AWS S3, Azure Blob Storage, etc) that utilizes many optimizations for this task and gain much better throughput. For example, specialized middleware like nginx embodies direct hooks between the file system and the network card and uses a multi-threaded approach to minimize intervention among multiple requests.
Your optimal solution might wear one of the following forms:
Using a reverse proxy – your static files will be located right next to your Node application, only requests to the static files folder will be served by a proxy that sits in front of your Node app such as nginx. Using this approach, your Node app is responsible deploying the static files but not to serve them. Your frontend’s colleague will love this approach as it prevents cross-origin-requests from the frontend.
Cloud storage – your static files will NOT be part of your Node app content, they will be uploaded to services like AWS S3, Azure BlobStorage, or other similar services that were born for this mission. Using this approach, your Node app is not responsible deploying the static files neither to serve them, hence a complete decoupling is drawn between Node and the Frontend which is anyway handled by different teams.
# configure gzip compression
gzip on;
keepalive 64;
# defining web server
server {
listen 80;
listen 443 ssl;
# handle static content
location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /usr/local/silly_face_society/node/public;
access_log off;
expires max;
}
From the blog StrongLoop:
…In development, you can use res.sendFile() to serve static files. But don’t do this in production, because this function has to read from the file system for every file request, so it will encounter significant latency and affect the overall performance of the app. Note that res.sendFile() is not implemented with the sendfile system call, which would make it far more efficient. Instead, use serve-static middleware (or something equivalent), that is optimized for serving files for Express apps. An even better option is to use a reverse proxy to serve static files; see Use a reverse proxy for more information…
클래식 웹에서는 백엔드가 브라우저에 프론트엔드/그래픽을 제공했다. 노드에서 일반적인 방식은 정적 파일을 클라이언트에게 전달하기 위해 Express 정적 미들웨어를 사용하는 것이다.
그러나 단일 스레드를 사용하는 노드는 일반적인 웹 앱이 아니기에 한번에 많은 파일을 제공하기에 최적화되지 않았다.
대신 작업에 대해 많은 최적화와, 훨씬 많은 처리량을 제공하는 리버스 프록시(예를 들어 nginx, HAProxy), 클라우드 저장소, CDN(예를 들어, AWS S3, Azure Blob Storage 등)의 사용을 고려해야 한다.
예를 들어 nginx와 같은 특수 미들웨어는 파일 시스템과 네트웨크 카드 간의 직접 연결을 구현하고 다중 스레드 접근 방식을 사용하여, 다수의 요청 간의 개입을 최소화 한다.
최적의 솔루션은 다음 형식중 하나를 사용할 수 있다:
리버스 프록시 사용 - 정적 파일은 Node 애들리케이션의 바로 옆에 위치하며, 정적 파일 폴더에 대한 요청만 nginx와 같은 노드 애플리케이션 앞에 있는 프록시에서 제공한다.
이 방식을 사용하면, 노드는 정적 파일을 배포하는 책임은 있으나 직접 제공하지는 않는다. 이 방법은 프론트엔드에서 교차적으로 요청을 하지 않아도 되기에 이러한 방식을 선호 할 것이다.
그러면 요청은 express에 하고 제공은 nginx에서 하기 때문에 node의 메모리에는 영향을 미치지 않는 것인가..?
하지만, nginx를 거쳐서 express로 요청이 들어로는데, 정적 파일의 요청의 경우에 nginx(파일 요청 전달)->express(어떤 파일을 요청하는지 확인, nginx에 파일 전달 요청)->nginx(파일 전송)->front 이러한 방식으로 구현?
위의 방식이 맞다면 스트리밍 또는 파일 전체 전송 이러한 전송에 대한 기술적인 부분은 Nginx에서 결정하는 것인가..?
[CORS - 교차 출처 리소스 공유](CORS는 왜 이렇게 우리를 힘들게 하는걸까? | Evans Library)
왜 프론트엔드가 좋아할까?? -> nginx에 프론트 올려놓으면 백엔드에서 요청에 대한 응답을 할 때 cors의 Acccess-Control-Allow-Origin*를 지정하여 응답하기 때문에 편해진다
클라우드 저장소 - 정적 파일은 Node 애플리케이션의 컨텐츠가 아니고, AWS S3, Azure BlobStorage와 비슷한 저장소에 저장이 될 것이다.
이 방식을 사용하면, Node는 정적 파일을 배포 하거나 제공할 책임이 없다. 따라서 노드와 프론트엔드 간에 완전한 분리가 이루어지며, 이는 다른 팀에서 처리한다.
# nginx.conf
# gzip 압축 구성
gzip on;
keepalive 64;
# 웹서버 정의
server {
listen 80;
listen 443 ssl;
# 정적 컨텐츠 관리
location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /usr/local/silly_face_society/node/public;
access_log off;
expires max;
}
StrongLoop의 블로그:
/>…개발중 당신은 정적 파일을 제공하기 위해 /res.sendFile()/를 사용할 수 있다./
그러나 이 함수는 모든 파일 요청에 대해 파일 시스템에서 읽어야 하기 때문에 상당한 대기 시간이 발생하고 애플리케이션 전체 성능에 영향을 미치기 때문에 상용되는 서버에는 사용하면 안된다.
res.sendFile()은 파일 전송 시스템으로 구현되어 있지 않기 때문에 효율과는 거리가 멀어진다.
대신, Express 애플리케이션에서 파일 제공에 최적화 되어있는 serve-static 미들웨어(또는, 비슷한 환경)를 사용해라.
더 나은 방법은 정적 파일 제공을 위해 리버스 프록시를 사용하는 것이다. 자세한 내용은 리버스 프록시 사용에 대한 정보를 참조해라…