학습 목표
Node.js와 Express로 기본적인 서버 만들기
들어가기 전
해당 글은 작성자가 프로젝트를 끝내고 정리하는 식의 글이기 때문에 작성한지 오래된 코드나 글의 경우 좀 내용이나 설명이 빌 수도 있으므로 유의해서 보길 추천한다.
1. app.js 파일 생성
아래 코드가 express를 사용하여 서버를 만든 코드이고 서버를 열기만 하였으며 다른 기능은 만들지 않은 상태이다.
사실 http 모듈과 express 모듈 모두 웹서버를 만드는데 사용되는 기본 모듈이다. http 모듈이 더 기본적인 모듈이고 express가 http를 기반으로 기능을 더 간소화하여 사용자로 하여금 사용하기 더 간편하게 만들어주는 모듈이다. 이런 얘기를 들으면 http를 사용하지않고 express만 사용하면 될 것 같은데 왜 2개를 같이 사용하는지 궁금할 수도 있을텐데 그 이유는 이 프로젝트의 목적때문에 그런것 이고 자세한건 나중에 가서 알아보자
require("dotenv").config();
const express = require("express");
const http = require("http");
const dotenv = require("dotenv");
dotenv.config();
const app = express();
const server = http.createServer(app);
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log("서버가 " + port + "번 포트에서 실행중입니다.");
});
각설하고 위에 코드를 차례대로 보면 먼저 express와 http모듈을 선언하고 app에 express객체를 선언하여 담는다. 그리고 이 express객체를 가지고 http서버를 만들었다.
port를 보면 process.env.PORT || 3000이라고 되어있는데 이 뜻은 process.env라는 객체에 PORT라는 변수가 있으면 해당 번호를 사용하고 아니면 3000번을 사용하겠다는 것이다.
dotenv 모듈은 기본적인 보안과 관련된 모듈이다. 자세한건 나중에 다른 글을 통해서 소개할 예정이다.
그런 다음 listen 메서드를 이용해서 서버가 요청을 받을 수 있도록 열어 놓는다. 여기서 listen 메서드를 살펴보면 메서드의 매개변수로 port와 콜백함수를 넣은 상태이다. 이 말은 port에 해당하는 포트번호로 서버를 열고 서버가 열리고 나면 뒤에 오는 함수를 실행하겠다는 뜻이다.
이렇게 만들면 기본적인 서버는 열려있는 상태가 된다. 하지만 http 통신을 하지는 못한다. 왜그런가 하면 말 그대로 서버에게 열려 있으라고만 하고 그 다음 행동을 지정하지 않은 상태이기 때문이다. 즉 열린 다음 http 통신이 들어오면 어떻게 처리할지 서버에게 알려줘야 하는 것이다. 다음으로는 어떻게 해당 과정을 처리하는지 알아보자.
2. app.js에서 서버 설정 및 데이터베이스 연결
require("dotenv").config();
const express = require("express");
const cookiParser = require("cookie-parser");
const connectDB = require("./database/database");
const cors = require("cors");
const dotenv = require("dotenv");
const userRoutes = require("./routes/userRoutes");
const signupRoutes = require("./routes/signupRoutes");
const likeRoutes = require("./routes/likeRoutes");
const communityRoutes = require("./routes/communityRoutes");
const companionRoutes = require("./routes/companionRoutes");
const mypageRoutes = require("./routes/mypageRoutes");
const chatRoutes = require("./routes/chatRoutes");
const http = require("http");
dotenv.config();
const app = express();
const server = http.createServer(app);
connectDB();
app.use(express.json());#요청에서 json형태의 body를 파싱하는 역할
app.use(cookiParser());#요청에 있는 쿠키를 파싱하는 역할
app.use(
cors({
origin: true,
credentials: true,
})
);
app.use(
session({
secret: process.env.sessionKey,
resave: false,
saveUninitialized: false,
})
);
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log("서버가 " + port + "번 포트에서 실행중입니다.");
});
이전 코드에 비해서 코드가 좀 길어졌다. 1번째 코드는 정말 서버를 열기만 한 코드였다면 이 코드는 실제로 사용이 가능한 코드라고 할 수 있다. 역시 위에서 부터 천천히 살펴보자.
먼저 connectDB라는 객체가 만들어졌다. 이건 말 그대로 DB와 서버를 연결하는 객체인데 이건 외부 모듈이 아니라 프로젝트 내부에 만들어 놓은 모듈이므로 일단 이런 과정이 있다고 생각하고 넘어가면 될 것 같다.
다음으로 이제 서버에 여러가지 설정을 한다.
app.use(
cors({
origin: true,
credentials: true,
})
);
app.use(
session({
secret: process.env.sessionKey,
resave: false,
saveUninitialized: false,
})
);
먼저 설명하기 전 app 즉 express에는 여러가지 메서드가 있다. 그 중 하나가 use 메서드인데 이 메서드는 미들웨어를 위한 메서드이다.
미들웨어란 해당 요청을 최종적으로 처리하기전 실행시키기는 함수라는 것 정도만 알아두고 미들웨어에 대한 설명은 나중으로 미루겠다.
위 코드를 보면 use메서드를 이용해서 cors, session 모듈을 실행하고 있다. 먼저 cors 모듈은 이름 그대로 cors 설정을 위한 모듈이다.
CORS(Cross-Origin Resource Sharing)란?
기본적으로 서버는 같은 도메인에서의 요청만 허용하도록 되어있다. 이 말은 서버에서 서버로의 요청은 아무런 설정 없이 처리가 가능하지만 브라우저에서 서버로의 요청 즉 프론트 서버 -> 백엔드 서버로의 요청은 허용되지 않는다는 것이다. 그런데 대부분의 서비스나 프로젝트는 프론트와 백엔드를 나눠서 구현하기 때문에 이를 가능하도록 하는 것이 cors이다
cors 설정은 여러가지가 있지만 여기서는 origin, credentials 설정을 했다. orgin은 도메인들 중 원하는 도메인만 받아들이도록 설정하는 것인데 true로 설정을 하면 모든 도메인에서 오는 요청을 받아들인다. 물론 보안적인 관점에서는 절대하면 안되는 것이지만 간단한 프로젝트에서는 true로 하는 것이 편하다. 그리고 credentials는 쿠키 허용 옵션인데 다른 도메인에서 보내는 쿠키를 받아들이도록 하는 것이다. 이 옵션은 나중에 구현할 로그인 및 다른 api 요청에서 jwt 토큰을 사용하기 때문에 넣은 옵션이다.
그리고 2번째로 설정하는 옵션이 session인데 session이란 일종의 쿠키이다. 대신 키-벨류로 이루어진 쿠키말고 키만 전달을 하고 벨류에 해당하는 값을 서버에서 관리하는 것이다. 이 역시 여러가지 설정 값들이 있다.
- secret - 키 값을 암호화 할때 사용하는 서명 값이다. 보통 process.env 파일에 저장하여 사용
- resave - 세션이 수정되지 않을 때도 저장을 할 것인지 지정하는 프로퍼티. 공식 문서에서는 false를 추천한다.
- saveUninitialized - 세션에 저장할 값이 없더라도 저장을 할지 지정하는 프로퍼티. 기본 값은 true이다.
일단 이정도만 사용하므로 해당되는 프로퍼티들만 설명을 하였다. 이외 다른 프로퍼티도 많으므로 궁금하거나 필요하다면 아래의 공식문서에서 확인하는 걸 추천한다.
https://www.npmjs.com/package/cors
cors
Node.js CORS middleware. Latest version: 2.8.5, last published: 5 years ago. Start using cors in your project by running `npm i cors`. There are 13736 other projects in the npm registry using cors.
www.npmjs.com
https://www.npmjs.com/package/express-session
express-session
Simple session middleware for Express. Latest version: 1.17.3, last published: 2 years ago. Start using express-session in your project by running `npm i express-session`. There are 4807 other projects in the npm registry using express-session.
www.npmjs.com
3. app.js 에서 라우팅하기
라우팅?
- 서버로 들어오는 요청들을 보고 해당하는 파일 혹은 메서드로 보내는 미들웨어의 일종
- 이 프로젝트에서는 mvc 아키텍처로 구현을 하였으므로 1차적으로 url마다 해당하는 라우터 파일로 라우팅한다.
app.use("/uploads", express.static("uploads"));
app.use("/community", communityRoutes);
app.use("/companion", companionRoutes);
app.use("/users", userRoutes);
app.use("/signup", signupRoutes);
app.use("/like", likeRoutes);
app.use("/mypage", mypageRoutes);
app.use("/chat", chatRoutes);
위 코드를 설명하자면 "/community"로 시작하는 요청은 communityRoutes파일로 요청을 넘겨서 처리하겠다는 것이다. 이렇게 라우팅을 하면 각 기능 혹은 파트마다 요청을 처리하는 메서드를 나눠서 관리 및 개발을 할 수 있어 나중에 유지보수에 있어서 이득을 주기 때문에 이런 형태로 관리하는 것을 추천한다. 이제 위에 있던 코드들을 전부 합치면 아래의 코드가 나온다.
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const session = require("express-session");
const cookiParser = require("cookie-parser");
const dotenv = require("dotenv");
const connectDB = require("./database/database");
const userRoutes = require("./routes/userRoutes");
const signupRoutes = require("./routes/signupRoutes");
const likeRoutes = require("./routes/likeRoutes");
const communityRoutes = require("./routes/communityRoutes");
const companionRoutes = require("./routes/companionRoutes");
const mypageRoutes = require("./routes/mypageRoutes");
const chatRoutes = require("./routes/chatRoutes");
const http = require("http");
const fs = require("fs");
dotenv.config();
const app = express();
const server = http.createServer(app);
connectDB();
app.use(
cors({
origin: true,
credentials: true,
})
);
app.use(express.json());
app.use(cookiParser());
app.use(
session({
secret: process.env.sessionKey,
resave: false,
saveUninitialized: false,
})
);
app.use("/uploads", express.static("uploads"));
app.use("/community", communityRoutes);
app.use("/companion", companionRoutes);
app.use("/users", userRoutes);
app.use("/signup", signupRoutes);
app.use("/like", likeRoutes);
app.use("/mypage", mypageRoutes);
app.use("/chat", chatRoutes);
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log("서버가 " + port + "번 포트에서 실행중입니다.");
});
해당 코드의 전체적인 플로우는 express 모듈과 http모듈을 이용해서 서버 객체를 만들고 여러가지 설정을 거친 뒤 서버를 특정 포트에 열는 것이다. 여기서 여러가지 설정에 대한 설명은 자세하게 하지 않았으므로 다음에 다른 글을 통해서 설명할까 생각 중이다.
'Node.js(Express)' 카테고리의 다른 글
| [Node.js] JWT 사용하기 - access token, refresh token (0) | 2024.01.20 |
|---|---|
| [Node.js] JWT에 대해 알아보기 (0) | 2024.01.18 |
| [Node.js] SNS 만들기 - Controller 만들기 (0) | 2024.01.18 |
| [Node.js] SNS 만들기 - Model 만들기 (0) | 2024.01.18 |
| [Node.js] SNS 만들기 - 라우터 만들기 (1) | 2024.01.13 |