./index
import "dotenv/config";
import { app } from "./src/app";
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`정상적으로 서버를 시작하였습니다. http://localhost:${PORT}`);
});
./node_modules/dotenv/config>
(function () {
require('./lib/main').config(
Object.assign(
{},
require('./lib/env-options'),
require('./lib/cli-options')(process.argv)
)
)
})()
pacakage.json 파일에 "main"이 "index.js" 파일로 설정되어 있다. 이 진입로를 확인하면 dotenv/config를 import 함을 확인할 수 있다.
Object.assign은 출처 객체들을 대상 객체에 붙여넣는 '몰아주기' 기능으로 이해된다. process.argv는 Node.js가 실행될 때 관련 정보들을 command-line 인자들로 이루어진 배열로 반환한다고 한다.
import cors from "cors";
...
const app = express();
app.use(cors());
CORS(Cross Origin Resource Sharing)은 한 출처에서 실행 중인 웹 어플리케이션이 다른 출처에 resource를 요청할 때, 요청과 응답을 주고 받는 방법이다. 여기서 출처란 protocol, port, domain을 포함한다.
실제적인 요청에 앞서 prefligh를 보내게 되는데 simple requests라는 일부 조건에서는 preflight가 생략된다.
import express from "express";
...
const app = express();
app.use(express.urlencoded({ extended: false }));
express.json과 마찬가지로 express.urlencoded 역시 NextHandlerFunction 타입을 따른다. 이 타입은 IncomingMessage를 받아서 http.ServerResponse를 뱉어주는 점이 주목할만하다.
url encoding된 payloads를 parsing할 때 content-type hearder도 함께 확인 된다고 한다. parsing된 데이터를 포함하는 객체는 흔히 아는 req.body에 populated 되는데, 만약 parsing할 body가 없거나 content-type matching이 실패할 시 빈 객체가 populated 된다.
./src/db/index
import mongoose from "mongoose";
const DB_URL =
process.env.MONGODB_URL ||
"MongoDB 서버 주소가 설정되지 않았습니다. \n .env 파일을 확인주세요.";
mongoose.connect(DB_URL);
const db = mongoose.connection;
db.on("connected", () => {
console.log("정상적으로 MongoDB 서버에 연결됐습니다. ");
});
db.on("error", (error) => {
console.error("MongoDB 연결에 실패했습니다.");
});
events.d.ts
namespace NodeJS {
interface EventEmitter {
/**
* Alias for `emitter.on(eventName, listener)`.
* @since v0.1.26
*/
...
on(eventName: string | symbol, listener: (...args: any[]) => void): this;
mongoose.connection.on은 EventEmitter interface 타입을 따르는데, 이는 eventName이라는 조건에 따라 여러가지 listener들을 등록할 수 있다. listener는 '이벤트를 기다리는 요소' 정도로 이해하고 넘어가보자.