프로그래밍 언어/HTML,CSS,JS

ExpressJS 애플리케이션을 구성하는 방법

Rateye 2021. 11. 8. 16:31
728x90
반응형
질문 : ExpressJS 애플리케이션을 구성하는 방법은 무엇입니까?

NodeJS 용 ExpressJS 웹 프레임 워크를 사용하고 있습니다.

ExpressJS를 사용하는 사람들은 자신의 환경 (개발, 생산, 테스트 ...), 경로 등을 app.js 합니다. 큰 응용 프로그램이 있으면 app.js가 너무 커서 아름다운 방법이 아니라고 생각합니다!

이 디렉토리 구조를 갖고 싶습니다.

| my-application
| -- app.js
| -- config/
     | -- environment.js
     | -- routes.js

내 코드는 다음과 같습니다.

app.js

var express = require('express');
var app = module.exports = express.createServer();

require('./config/environment.js')(app, express);
require('./config/routes.js')(app);

app.listen(3000);

config / environment.js

module.exports = function(app, express){
    app.configure(function() {
    app.use(express.logger());
    });

    app.configure('development', function() {
    app.use(express.errorHandler({
        dumpExceptions: true,
        showStack: true
    }));
    });

    app.configure('production', function() {
    app.use(express.errorHandler());
    });
};

config / routes.js

module.exports = function(app) {
    app.get('/', function(req, res) {
    res.send('Hello world !');
    });
};

내 코드가 잘 작동하고 디렉토리 구조가 아름답다고 생각합니다. 그러나 코드를 수정해야했고 그것이 좋고 / 아름답다는 확신이 들지 않습니다.

내 디렉토리 구조를 사용하고 코드를 수정하거나 단순히 하나의 파일 (app.js)을 사용하는 것이 더 낫습니까?

귀하의 조언에 감사드립니다!

답변

좋아, 오랜만이었고 이것은 인기있는 질문이므로 JavaScript 코드와 중간 크기의 express.js 응용 프로그램을 구성하는 방법에 대한 긴 README로 스캐 폴딩 github 저장소를 만들었습니다.

focusaurus / express_code_structure 는 이에 대한 최신 코드가있는 저장소입니다. Pull 요청을 환영합니다.

stackoverflow가 just-a-link 답변을 좋아하지 않기 때문에 README의 스냅 샷이 있습니다. 계속 업데이트 할 새 프로젝트이므로 몇 가지 업데이트를 할 예정이지만 궁극적으로 github 저장소가이 정보에 대한 최신 위치가 될 것입니다.

이 프로젝트는 중형 express.js 웹 애플리케이션을 구성하는 방법의 예입니다.

2016 년 12 월 v4.14 이상의 최신 버전

빌드 상태

Node.js 표준 스타일

웹 애플리케이션은 모두 동일하지 않으며 모든 express.js 애플리케이션에 적용해야하는 단일 코드 구조도 내 생각에 없습니다.

애플리케이션이 작은 경우 여기에 예시 된 것처럼 깊은 디렉토리 구조가 필요하지 않습니다. 간단하게 유지하고 저장소의 루트에 .js Voilà.

애플리케이션이 거대하다면 어떤 시점에서이를 별개의 npm 패키지로 분리해야합니다. 일반적으로 node.js 접근 방식은 적어도 라이브러리에 대해 많은 작은 패키지를 선호하는 것으로 보이며, 이해하기 시작하고 오버 헤드를 정당화하기 시작하면 여러 npm 패키지를 사용하여 애플리케이션을 빌드해야합니다. 따라서 애플리케이션이 성장하고 코드의 일부가 애플리케이션 외부에서 명확하게 재사용되거나 명확한 하위 시스템이되면 자체 git 저장소로 이동하여 독립형 npm 패키지로 만듭니다.

따라서이 프로젝트의 초점은 중간 규모 애플리케이션에 대해 실행 가능한 구조를 설명하는 것입니다.

다음과 같이 웹 애플리케이션을 구축하는 데는 여러 가지 접근 방식이 있습니다.

  • Ruby on Rails의 서버 측 MVC
  • MongoDB / Express / Angular / Node (MEAN)에 따른 단일 페이지 애플리케이션 스타일
  • 몇 가지 양식이있는 기본 웹 사이트
  • 모델 / 작업 / 뷰 / 이벤트 스타일 a la MVC가 죽었습니다. 이제 움직일 시간입니다.
  • 그리고 현재와 역사 모두 다른 많은

이들 각각은 다른 디렉토리 구조에 잘 맞습니다. 이 예제에서는 스캐 폴딩 일 뿐이며 완전히 작동하는 앱은 아니지만 다음과 같은 주요 아키텍처 포인트를 가정합니다.

  • 사이트에 기존의 정적 페이지 / 템플릿이 있습니다.
  • 사이트의 "응용 프로그램"부분은 단일 페이지 응용 프로그램 스타일로 개발되었습니다.
  • 애플리케이션은 REST / JSON 스타일 API를 브라우저에 노출합니다.
  • 이 앱은 단순한 비즈니스 도메인을 모델링합니다.이 경우에는 자동차 대리점 애플리케이션입니다.

이 프로젝트 전반에 걸쳐 Ruby on Rails에 구현 된 많은 아이디어와 이들이 채택한 "구성에 대한 규약"결정이 널리 받아 들여지고 사용되었지만 실제로는 그다지 도움이되지 않으며 때때로이 저장소와 반대되는 주제가 될 것입니다. 권장합니다.

여기서 내 요점은 코드 구성에 대한 기본 원칙이 있으며, 이러한 원칙을 기반으로 Ruby on Rails 규칙이 Ruby on Rails 커뮤니티에 (대부분) 의미가 있다는 것입니다. 그러나 생각없이 이러한 관습을 준수하는 것은 요점을 놓친다. 기본 원칙을 익히면 쉘 스크립트, 게임, 모바일 앱, 엔터프라이즈 프로젝트, 홈 디렉토리까지 모든 프로젝트가 잘 구성되고 명확 해집니다.

Rails 커뮤니티의 경우 단일 Rails 개발자가 앱에서 앱으로 전환하고 매번 익숙하고 익숙해지기를 원합니다. 이는 37 개의 신호 또는 Pivotal Labs 인 경우 매우 의미가 있으며 이점이 있습니다. 서버 측 자바 스크립트 세계에서 전체적인 정신은 더 와일드 웨스트이며 우리는 그것에 대해 실제로 문제가 없습니다. 그것이 우리가 구르는 방법입니다. 우리는 그것에 익숙합니다. express.js 내에서도 Rails가 아닌 Sinatra와 가까운 친척이며 Rails에서 규칙을 취하는 것은 일반적으로 아무것도 도움이되지 않습니다. 나는 심지어 구성보다 관습에 대한 원칙 이라고 말하고 싶다.

  • 정신적으로 관리 가능
    • 뇌는 한 번에 적은 수의 관련 사항 만 처리하고 생각할 수 있습니다. 이것이 우리가 디렉토리를 사용하는 이유입니다. 작은 부분에 집중하여 복잡성을 처리하는 데 도움이됩니다.
  • 크기에 적합해야합니다.
    • 파일이 1 개 뿐인 디렉토리 3 개만있는 "Mansion Directories"를 만들지 마십시오. 3 개의 파일이있는 1 개의 디렉토리가 훨씬 더 적절할 때 10 개 이상의 파일을 보관할 10 개 이상의 디렉토리를 생성하도록 소규모 프로젝트를 부끄럽게 만드는 Ansible Best Practices 에서 이런 일이 발생하는 것을 볼 수 있습니다. 당신은 버스를 운전하지 않습니다 (당신이 버스 운전사가 아니라면 버스 운전은 작동하지 않습니다). 그러므로 내부의 실제 파일에 의해 정당화되지 않는 파일 시스템 구조를 만들지 마십시오 .
  • 모듈 식이지만 실용적이어야합니다.
    • 노드 커뮤니티는 전반적으로 작은 모듈을 선호합니다. 앱에서 완전히 분리 할 수있는 모든 것은 내부 사용을 위해 모듈로 추출하거나 npm에 공개적으로 게시해야합니다. 그러나 여기서 범위가되는 중간 규모 응용 프로그램의 경우이 오버 헤드로 인해 적절한 가치없이 워크 플로가 지루해질 수 있습니다. 따라서 완전히 분리 된 npm 모듈을 정당화하기에 충분하지 않은 일부 코드가있는 경우에는 일부 크기 임계 값을 초과 할 때 추출 될 것이라는 예상과 함께 "프로토 모듈"로 간주하십시오.
    • @ hij1nx 와 같은 일부 사람들은 app/node_modules 디렉토리를 포함하고 proto-module package.json 파일을 가지고있어 전환을 용이하게하고 알림 역할을합니다.
  • 코드를 쉽게 찾을 수 있습니다.
    • 빌드 할 기능이나 수정해야 할 버그가 주어지면 개발자가 관련된 소스 파일을 찾는 데 어려움을 겪지 않는 것이 목표입니다.
    • 의미 있고 정확한 이름
    • crufty 코드가 완전히 제거되어 고아 파일에 남아 있지 않거나 주석 처리되지 않았습니다.
  • 검색 친화적이어야합니다.
    • 모든 자사 소스 코드는 app 디렉토리에 있으므로 find / grep / xargs / ag / ack / etc를 실행하고 타사 일치에 의해 산만 해지지 않도록 cd 할 수 있습니다.
  • 간단하고 명확한 이름 지정
    • npm은 이제 모두 소문자 패키지 이름을 요구하는 것 같습니다. 나는 이것이 대부분 끔찍하다고 생각하지만 무리를 따라야하므로 JavaScript에서 변수 이름이 camelCase kebab-case - 는 JavaScript의 마이너스 기호이기 때문입니다.
    • 변수 이름은 모듈 경로의 기본 이름과 일치하지만 kebab-case camelCase 변환됩니다.
  • 기능이 아닌 커플 링으로 그룹화
    • app/views , app/controllers , app/models 등의 Ruby on Rails 규칙에서 크게 벗어났습니다.
    • 기능이 전체 스택에 추가되므로 내 기능과 관련된 전체 파일 스택에 집중하고 싶습니다. 사용자 모델에 전화 번호 필드를 추가 할 때 사용자 컨트롤러 이외의 컨트롤러는 신경 쓰지 않으며 사용자 모델 이외의 모델은 신경 쓰지 않습니다.
    • 따라서 각각 고유 한 디렉토리에있는 6 개의 파일을 편집하고 해당 디렉토리에있는 수많은 다른 파일을 무시하는 대신이 저장소는 기능을 구축하는 데 필요한 모든 파일이 같은 위치에 배치되도록 구성됩니다.
    • MVC의 특성상 사용자보기는 사용자 모델에 연결된 사용자 컨트롤러에 연결됩니다. 따라서 사용자 모델을 변경하면이 3 개의 파일이 함께 변경되는 경우가 많지만 거래 컨트롤러 또는 고객 컨트롤러는 분리되어 관여하지 않습니다. 일반적으로 MVC가 아닌 디자인에도 동일하게 적용됩니다.
    • MVC 또는 MOVE 스타일의 분리는 어떤 모듈에 어떤 코드가 들어가는가를 권장하지만 MVC 파일을 형제 디렉토리로 확산시키는 것은 성가신 일입니다.
    • 따라서 각 경로 파일에는 소유하는 경로의 일부가 있습니다. 레일 스타일의 routes.rb 파일은 앱의 모든 경로에 대한 개요를 원할 때 유용하지만 실제로 기능을 구축하고 버그를 수정할 때는 변경하려는 부분과 관련된 경로에만 관심이 있습니다.
  • 코드 옆에 테스트 저장
    • 이것은 "그룹 별 커플 링"의 예일 뿐이지 만 구체적으로 부르고 싶었습니다. 저는 테스트가 "tests"라는 병렬 파일 시스템 아래에있는 많은 프로젝트를 작성했으며 이제 테스트를 해당 코드와 동일한 디렉토리에 배치하기 시작 했으므로 다시는 돌아 가지 않을 것입니다. 이것은 더 모듈화되고 텍스트 편집기에서 작업하기가 훨씬 쉬우 며 많은 "../../ .."경로 넌센스를 완화합니다. 확실하지 않은 경우 몇 가지 프로젝트에서 시도해보고 스스로 결정하십시오. 나는 그것이 더 낫다는 것을 당신에게 확신시키기 위해 이것 이상으로 아무것도하지 않을 것입니다.
  • 이벤트로 교차 결합 감소
    • "OK, 새 거래가 생성 될 때마다 모든 영업 담당자에게 이메일을 보내고 싶습니다."라고 생각한 다음 거래를 생성하는 경로에 해당 이메일을 보내는 코드를 입력하기 만하면됩니다.
    • 그러나 이러한 결합은 결국 앱을 거대한 진흙 덩어리로 만들 것입니다.
    • 대신 DealModel은 "만들기"이벤트를 발생시키고 시스템이 이에 대응하여 수행 할 수있는 다른 작업을 완전히 인식하지 않아야합니다.
    • 이런 식으로 코딩하면 사용자 코드 기반의 순도를 오염시키는 결합 된 비즈니스 로직의 쥐 둥지가 곳곳에 존재하지 않기 때문에 app/users 에 넣는 것이 훨씬 더 가능해집니다.
  • 코드 흐름을 따를 수 있습니다.
    • 마법 같은 일을하지 마십시오. 파일 시스템의 매직 디렉토리에서 파일을 자동로드하지 마십시오. Rails가 아닙니다. app/server.js:1 에서 시작되며 코드를 따라로드하고 실행하는 모든 것을 볼 수 있습니다.
    • 경로에 대한 DSL을 만들지 마십시오. 요구되지 않을 때 어리석은 메타 프로그래밍을하지 마십시오.
    • 앱이 너무 커서 magicRESTRouter.route(somecontroller, {except: 'POST'}) 를 수행하는 것이 3 가지 기본 app.get , app.put , app.del , 호출을 통해 큰 승리를 거두는 경우 아마도 빌드 중일 것입니다. 너무 커서 효과적으로 작업 할 수없는 모 놀리 식 앱입니다. 3 개의 간단한 선을 1 개의 복잡한 선으로 변환하는 것이 아니라 큰 승리를 위해 멋지게 꾸며보세요.
  • 케밥 소문자 파일 이름 사용
    • 이 형식은 플랫폼 간의 파일 시스템 대소 문자 구분 문제를 방지합니다.
    • npm은 새 패키지 이름에 대문자를 사용하지 않습니다.express.js 사양
  • app.configure 사용하지 마십시오. 거의 전적으로 쓸모가 없으며 필요하지 않습니다. 무의미한 카피 파스타로 인해 많은 상용구에 있습니다.
  • 미들웨어의 순서와 명시적인 문제의 경로 !!!
    • 내가 stackoverflow에서 보는 거의 모든 라우팅 문제는 비 순차적 익스프레스 미들웨어입니다.
    • 일반적으로 경로를 분리하고 순서에 많이 의존하지 않기를 원합니다.
    • 2 개의 경로에 대해 미들웨어 만 필요한 경우 전체 애플리케이션에 app.use 를 사용하지 마십시오 body-parser ).
    • 모든 것이 말하고 완료되면 정확히 다음 순서를 따르십시오.
      1. 매우 중요한 애플리케이션 전체 미들웨어
      2. 모든 경로 및 여러 경로 미들웨어
      3. THEN 오류 핸들러
  • 슬프게도, sinatra에서 영감을 얻은 express.js는 대부분 모든 경로가 server.js 있다고 가정하고 순서가 명확해질 것입니다. 중간 규모 애플리케이션의 경우 별도의 경로 모듈로 분리하는 것이 좋지만 비 순차적 미들웨어의 위험을 초래합니다.
  •  

Node.js에 대한 훌륭한 요점 Better local require () 경로 에서 커뮤니티에 의해 자세히 설명되고 논의되는 많은 접근 방식이 있습니다. 나는 곧 "../../../ .. 많은 양의 ../../../ .. 처리"를 선호하거나 requireFrom 모듈을 사용하기로 결정할 것입니다. 그러나 지금은 아래에 설명 된 심볼릭 링크 트릭을 사용하고 있습니다.

require("../../../config") 와 같은 성가신 상대 경로를 사용하여 프로젝트 내에서 요구하는 것을 피하는 한 가지 방법은 다음 트릭을 사용하는 것입니다.

  • 앱의 node_modules 아래에 심볼릭 링크를 만듭니다.
      cd node_modules && ln -nsf ../app
  • cd node_modules && ln -nsf ../app
  • 전체 node_modules 폴더가 아닌 node_modules / app symlink 자체 만 git에 추가하십시오.
        git add -f node_modules / app 예,
    .gitignore
      파일에 "node_modules"가 있어야합니다. 아니요, "node_modules"를 git 저장소에 넣지 않아야합니다. 어떤 사람들은 이것을 추천 할 것입니다. 정확하지 않습니다.
  • git add -f node_modules / app
  • .gitignore 파일에 "node_modules"가 있어야합니다.
  • 아니요, "node_modules"를 git 저장소에 넣어서는 안됩니다. 어떤 사람들은 이것을 추천 할 것입니다. 정확하지 않습니다.
  • 이제이 접두사를 사용하여 프로젝트 내 모듈을 요구할 수 있습니다.var config = require("app/config");var DealModel = require("app/deals/deal-model")
      ;
  • var config = require("app/config");
  • var DealModel = require("app/deals/deal-model") ;
  • 기본적으로 프로젝트 내에서 외부 npm 모듈에 필요한 작업과 매우 유사한 작업이 필요합니다.
  • 죄송합니다. Windows 사용자는 상위 디렉터리 상대 경로를 사용해야합니다.
  • cd node_modules && ln -nsf ../app
  • cd node_modules && ln -nsf ../app
  • git add -f node_modules / app
  • .gitignore 파일에 "node_modules"가 있어야합니다.
  • 아니요, "node_modules"를 git 저장소에 넣어서는 안됩니다. 어떤 사람들은 이것을 추천 할 것입니다. 정확하지 않습니다.
  • git add -f node_modules / app
  • .gitignore 파일에 "node_modules"가 있어야합니다.
  • 아니요, "node_modules"를 git 저장소에 넣어서는 안됩니다. 어떤 사람들은 이것을 추천 할 것입니다. 정확하지 않습니다.
  • var config = require("app/config");
  • var DealModel = require("app/deals/deal-model") ;
  • var config = require("app/config");
  • var DealModel = require("app/deals/deal-model") ;

일반적으로 코드 모듈과 클래스는 전달 된 options app/server.js app/config.js 모듈을로드해야합니다. 거기에서 작은 options 개체를 합성하여 필요에 따라 하위 시스템을 구성 할 수 있지만 모든 하위 시스템을 추가 정보로 가득 찬 큰 글로벌 구성 모듈에 연결하는 것은 잘못된 연결입니다.

DB 연결 생성을 중앙 집중화하고 연결 매개 변수를 전달하고 서브 시스템이 자체적으로 나가는 연결을 만드는 것과는 반대로이를 서브 시스템으로 전달하십시오.

이것은 Rails에서 전달 된 또 다른 매력적이지만 끔찍한 아이디어입니다. NODE_ENV 환경 변수를 살펴 보는 app/config.js 라는 앱에 정확히 1 개의 위치가 있어야합니다. 다른 모든 것은 클래스 생성자 인수 또는 모듈 구성 매개 변수로 명시적인 옵션을 가져야합니다.

이메일 모듈에 이메일 전달 방법 (SMTP, stdout에 로그, 대기열에 넣기 등)에 대한 옵션이있는 경우 {deliver: 'stdout'} 과 같은 옵션을 선택해야하지만 NODE_ENV 절대 확인해서는 안됩니다.

이제 테스트 파일을 해당 코드와 동일한 디렉토리에 보관하고 파일 이름 확장자 명명 규칙을 사용하여 테스트를 프로덕션 코드와 구분합니다.

  • foo.js 에는 모듈 "foo"의 코드가 있습니다.
  • foo.tape.js 에는 foo에 대한 노드 기반 테스트가 있으며 동일한 디렉토리에 있습니다.
  • foo.btape.js 는 브라우저 환경에서 실행해야하는 테스트에 사용할 수 있습니다.

나는 파일 시스템 glob과 find . -name '*.tape.js' 명령을 사용하여 필요에 따라 모든 테스트에 액세스합니다.

이 프로젝트의 범위는 주로 파일과 디렉토리가 어디로 가는지에 관한 것이며 다른 범위를 추가하고 싶지는 않지만 코드를 3 개의 개별 섹션으로 구성한다고 언급하겠습니다.

출처 : https://stackoverflow.com/questions/5778245/expressjs-how-to-structure-an-application

 

728x90
반응형