Javascript/Node.js

1. 프로젝트 구조 설계

Frankie 2021. 9. 10. 17:08

1.1 컴포넌트 기반으로 설계

- 코드를 컴포넌트로 나누고, 각각의 컴포넌트가 자신의 폴더 혹은 할당된 코드베이스를 안에서 작고 간단한 단위로 유지되도록 해라.

-> 그렇게 하지 않을 경우 새로운 기능을 작성하는 개발자가 변경사항이 어떤 영향을 미치는지 알기가 힘들면 의존하고 있는 다른 컴포넌트를 망칠까 두려워 하게 되고, 이는 배포를 더 느리고 더 불안전하게 만든다.

 

좋은예: 자족적인 컴포넌트 기반으로 설계

나쁜예: 파일을 기술적인 역할별로 모아두기

1.2 컴포넌트를 계층화하고, Express를 그 경계 안에 둬라

- 각각의 컴포넌트는 웹, 로직, 데이터 접근 코드를 위한 객체인 '계층'을 포함해야 한다. 이것은 우려할 만한 요소들을 깨끗하게 분리할 뿐만 아니라 모의 객체를 만들어 테스트하기 굉장히 쉽게 만든다.

- 이것이 굉장히 일반적인 패턴임에도. API 개발자들은 웹 계층의 객체를 비지니스 로직과 데이터 계층으로 보내서 계층을 뒤섞어버리는 경향이 있다. 그렇게 하는 것은 어플리케이션에 의존성을 만들고 Express에서만 접근 가능하도록 만든다.

-> 그렇게 하지 않을 경우: 웹 객체와 다른 계층을 뒤섞은 앱의 테스트 코드, CRON 작업이나 Express가 아닌 다른 곳에서의 접근을 불가능하게 한다.

 

컴포넌트 코드를 웹, 서비스, 데이터 접근 언어 계층으로 나누어라

1.3 공유 유틸리티들은 npm 패키지로 감싸라

 

- 커다란 앱에서는 로깅, 암호화 같은 횡단 관심사가 있는 유틸의 경우 당신이 쓴 코드로 감싸진 private NPM package의 형태로 노출이 되어야 한다. 이것은 여러 코드 기반과 프로젝트들에게 그것들을 공유할 수 있도록 해준다. 

- 프로젝트가 커지면서 비슷한 유틸리티들을 소비하는 다른 서버의 다른 컴포넌트들이 생겨나면 의존성을 관리하기 시작해야 한다

-> npm이라는 도구로 제삼자 유틸리티 패키지를 자신만의 코드로 감싸 미래에 대체하기 쉽게 하고 그 코드를 private npm 패키지로 publish하면 된다. private 모듈이나 private 레지스트리, 혹은 로컬 npm 패키지를 사용하면 npm 패키지를 공개적으로 공유하지 않고도 자용으로 쓸 수 있게 publish 할 수 있다.

 

1.4 Express의 appr과 server를 분리하라

 

- Express 앱을 통째로 하나의 큰 파일에 정의하는 나쁜 습관은 피해라.

- 'Express'정의를 최소한 둘로(API선언과 네트워크 부분)으로 나누자. 더 좋은 구조는 API 선언을 컴포넌트 안에 놓는 것이다.

-> 그렇게 하지 않을 경우: HTTP 요청으로만 API 테스트가 가능하게 된다 (커버리지 보고서를 생성하기가 더 느려지고 훨씬 힘들어진다). 

 

// API 선언 - app.js

var app = express();
app.use(bodyParser.json());
app.use("/api/events", events.API);
app.use("/api/forms", forms);

// Server network 선언 - /bin/www

var app = require('../app');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

// 예: supertest를 이용해서 API를 테스트 해보기

const app = express();

app.get('/user', function(req, res) {
  res.status(200).json({ name: 'tobi' });
});

request(app)
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });

1.5 환경을 인식하는, 보안적인, 계층적인 설정을 사용하라

- 완벽하고 결점이 없는 구성 설정은 (a) 파일과 환경변수 모두에서 키 값을 읽을 수 있어야하고 (b) 보안 값들은 커밋된 코드 밖에서 관리되어야하며 (c) 설정은 좀 더 쉽게 찾을 수 있도록 계층적으로 관리해야 한다.

-> 그렇게 하지 않을 경우: 위의 구성 요구사항 중 하나라도 만족시키지 못한다면 개발팀이나 데브옵스팀을 늪으로 몰아갈 수 있다.

 

예) 계층적인 config는 항목을 찾거나 대용량 config 파일들을 유지하는데 도움이 된다.

{
  // Customer module configs 
  "Customer": {
    "dbConfig": {
      "host": "localhost",
      "port": 5984,
      "dbName": "customers"
    },
    "credit": {
      "initialLimit": 100,
      // Set low for development 
      "initialDays": 1
    }
  }
}

 

 

'Javascript > Node.js' 카테고리의 다른 글

[Node.js] 3. 코드 스타일  (0) 2021.09.13
[Node.js] 2. 에러 처리 방법  (0) 2021.09.10
[Objection.js] Eager Loading Method  (0) 2021.09.09
옵셔널 체이닝 - '?.'  (0) 2021.09.02
[Node.js] 개념  (0) 2021.07.20