| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- js
- 내밥줄지켜
- 신입
- #유데미 #udemy #웅진씽크빅 #스나이퍼팩토리 #인사이드아웃 #미래내일일경험 #프로젝트캠프 #부트캠프 #react #next.js #프론트엔드개발자양성과정 #개발자교육과정
- 프로그래밍
- 개발
- 프론트엔드
- 웹개발
- 블레이버스
- 새복많
- AI에게서 살아남기
- javascript
- Web
- pccp
- 밥줄지키기프로젝트
- react
- 자바스크립트
- 백엔드
- 코딩테스트
- 타입스크립트
- 개발자
- 프로그래머스
- 코딩
- 파킨슨병
- 30대까지이루기
- frontend
- Next
- 2026
- 회사
- 밀러컬럼
- Today
- Total
낭 만 당
Nest.js로 가는 길에 Express.js 먼저 맛보기 본문
Nest.js를 배우기 전, 그 기반이 되는 Express.js를 먼저 경험해봤습니다. Node.js 백엔드 생태계의 오랜 강자이자, Nest.js의 근간이 되기 때문에 기본 동작 방식을 알아두는 것이 학습에 도움이 될 거라 판단했습니다.
Express.js vs Nest.js: 자유와 구조
직접 사용해보니 두 프레임워크의 지향점이 명확히 달랐습니다.
Express.js는 자유롭습니다. 정해진 규칙이 거의 없어 빠르게 서버를 만들 수 있습니다. 하지만 이는 개발자마다 코드 스타일이 달라질 수 있음을 의미해, 협업 시 구조 파악에 시간이 걸릴 수 있습니다.
개인적으로 타입스크립트와의 조합이 조금 아쉽게 느껴졌습니다. res 객체나 next() 함수의 유연성이 타입스크립트의 엄격한 타입 검사와는 다소 상충하는 면이 있다는 생각입니다.
반면 Nest.js는 정형화된 프레임워크입니다. 명확한 가이드를 제시해 코드의 일관성을 유지하고 생산성을 높입니다. 초기 학습 곡선은 가파르지만, 한번 익숙해지면 코드 작성이 수월하고 다른 개발자의 코드를 이해하기도 쉽습니다.
| Express.js | Nest.js | |
| 장점 | 자유롭고 유연함 낮은 러닝커브 |
정형화된 구조 높은 코드 재사용성 및 가독성 |
| 단점 | 코드의 비일관성 협업 시, 코드 파악이 어려움 |
높은 초기 러닝커브 (배우기 힘든듯..) 정해진 틀을 벗어나기 복잡함 |

Express.js, 직접 부딪혀보기!
백문이 불여일견이죠. 모든 배움의 시작은 "공식 문서"라는 말을 되새기며, 바로 실습에 돌입했습니다.
1. 프로젝트 설정
먼저 터미널을 열고 프로젝트를 시작할 폴더를 만들었습니다.
# 바탕화면에 myapp 폴더 생성
mkdir myapp
# myapp 폴더로 이동
cd myapp
# package.json 파일 생성 (-y 옵션으로 질문 생략)
npm init -y
# express 설치
npm install express
# vscode 실행
code .
여기서 npm은 Node Package Manager의 약자로, 다른 개발자들이 만들어둔 유용한 코드 뭉치(패키지)들을 쉽게 설치하고 관리하게 해주는 도구입니다. npm init 명령어를 실행하면 package.json 파일이 생기는데, 이 파일에 우리 프로젝트의 정보와 어떤 패키지들을 사용하는지에 대한 기록이 남게 됩니다.
2. Hello World! 서버 띄우기
공식 문서의 "Hello World" 예제를 따라 app.js 파일을 만들고 코드를 작성했습니다.
// app.js
const express = require("express"); // express 패키지를 가져옴
const app = express(); // express 서버 실행
const port = 3000; // 서버를 열 포트 번호
// '/' 경로로 GET 요청이 오면 "Hello World!"를 응답
app.get("/", (req, res) => {
res.send("Hello World!");
});
// 3000번 포트에서 요청을 기다림
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
코드를 간단히 해석해보자면, express를 가져와 app이라는 서버 인스턴스를 만들고, 3000번 포트를 사용하도록 설정했습니다. app.get('/', ...) 부분은 "누군가 우리 서버의 기본 주소(/)로 GET 요청을 보내면, 'Hello World!'라는 텍스트를 응답해줘"라는 뜻입니다.
이제 터미널에서 서버를 실행...
node app.js
브라우저 주소창에 http://localhost:3000을 입력하니...
"Hello World!"가 화면에 뜨는 걸 보니 정말 신기하고 뿌듯했습니다! 🥳. (모든 프로그래밍의 아버지... hello world )
길을 만드는 기술, 라우터 (Router)
기능이 많아지면 app.js 파일 하나에 모든 코드를 넣기 힘들어집니다. 이때 라우터를 사용하면 기능별로 코드를 분리해서 깔끔하게 관리할 수 있어요. Router는 말 그대로 '길(URL 경로)을 연결해주는 장치'입니다.
저는 routers 폴더를 만들고 그 안에 user.router.js 파일을 만들어 사용자 관련 API를 분리해봤습니다.
// routers/user.router.js
const router = require("express").Router();
router.get("/", (req, res) => {
res.send("User Router GET /user");
});
module.exports = router; // 다른 파일에서 쓸 수 있게 내보내기
그리고 app.js에서 이 라우터를 가져와 /user라는 길에 연결해줬습니다.
// app.js (추가된 부분)
const userRouter = require("./routers/user.router");
// '/user' 경로로 들어오는 요청은 userRouter가 처리
app.use("/user", userRouter);
이제 http://localhost:3000/user로 접속하면 user.router.js에 정의한 응답이 잘 나오는 것을 확인할 수 있었습니다. 이렇게 관심사를 분리하니 코드가 훨씬 체계적으로 변하는 걸 느낄 수 있었습니다.
클라이언트와 데이터 주고받기: Query, Param, Body
클라이언트로부터 데이터를 받는 방법은 크게 세 가지가 있습니다. 직접 코드를 짜면서 익혀봤습니다.
- Query: URL 뒤에 ?key=value 형태로 데이터를 전달합니다. (예: /user?nickname=suloth)
- Param: URL 경로의 일부로 데이터를 전달합니다. (예: /user/suloth)
- Body: 요청의 본문에 데이터를 담아 전달하며, 주로 POST, PUT, PATCH 메소드에서 사용됩니다.
user.router.js 파일을 수정해서 세 가지 방식을 모두 테스트해봤습니다.
// routers/user.router.js
const router = require("express").Router();
// 1. Query로 받기
router.get("/", (req, res) => {
const { nickname } = req.query; // const nickname = req.query.nickname; 과 동일
res.json({ userInfoForQuery: { nickname } });
});
// 2. Param으로 받기
router.get("/:nickname", (req, res) => {
const { nickname } = req.params;
res.json({ userInfoForParam: { nickname } });
});
// 3. Body로 받기
router.post("/", (req, res) => {
const body = req.body;
res.json(body);
});
module.exports = router;
Body를 사용하려면 app.js에 express.json()이라는 미들웨어를 추가해서 서버가 JSON 형식의 요청 본문을 읽을 수 있도록 설정해줘야 합니다.
// app.js
app.use(express.json()); // body-parser
Postman이라는 API 테스트 도구를 사용해 Body 데이터를 보내보니, 보낸 데이터가 그대로 응답으로 돌아오는 것을 확인할 수 있었습니다.
요청과 응답 사이의 마법, 미들웨어 (Middleware)
미들웨어는 Express의 핵심 개념 중 하나입니다. 간단히 말해 요청(req)이 들어와서 응답(res)이 나가기까지 거치는 중간 함수들을 의미합니다.
미들웨어를 이용하면 요청 객체를 조작하거나, 다음 로직으로 넘어가기 전에 특정 작업을 수행하게 할 수 있습니다. next() 함수를 호출하면 다음 미들웨어로 제어가 넘어갑니다.
아래 코드는 /middleware 경로로 요청이 오면, 첫 번째 미들웨어에서 쿼리에 nickname을 강제로 설정하고 next()를 호출해서 다음 미들웨어로 넘기는 예제입니다.
// routers/user.router.js
router.get(
"/middleware",
(req, res, next) => {
// 첫 번째 미들웨어: 요청 객체 조작
req.query["nickname"] = "suloth_from_middleware";
next(); // 다음 미들웨어로 이동
},
(req, res) => {
// 두 번째 미들웨어: 최종 응답
res.json({
nickname: req.query.nickname,
});
}
);
이 코드를 작성하고 http://localhost:3000/user/middleware로 접속하니, URL에 쿼리를 넣지 않았는데도 suloth_from_middleware라는 닉네임이 응답으로 오는 것을 볼 수 있었습니다. 미들웨어의 힘을 제대로 체감하는 순간이었죠.
주의! 라우터는 위에서부터 순서대로 코드를 읽기 때문에, router.get("/middleware")를 router.get("/:nickname")보다 위에 작성해야 합니다. 그렇지 않으면 Express가 'middleware'라는 문자열을 :nickname 파라미터로 인식해버리는 불상사가 생깁니다.
느낀 점
Express.js를 직접 다뤄보니 왜 많은 개발자가 Node.js에 입문할 때 Express를 선택하는지 알 수 있었습니다. 자유롭고 직관적이라 빠르게 결과물을 볼 수 있다는 점이 정말 매력적이었습니다. 동시에 왜 Nest.js 같은 구조화된 프레임워크가 등장했는지도 자연스럽게 이해하게 되었습니다.
참고 블로그 출처 https://suloth.tistory.com/197

'Programming Record' 카테고리의 다른 글
| 프로그래머스 Lv 2 - 기능개발 (JavaScript) (4) | 2025.08.15 |
|---|---|
| [파킨슨밸런스] 서울대병원 파킨슨병 환자를 위한 운동 추적 어플 개발 (5) | 2025.08.09 |
| 프로그래머스 Lv1 수박수박수~ 문제 풀기와 코드의 변화 (1) | 2025.07.16 |
| 프로그래머스 Lv 1 - 하샤드 수 (JavaScript) (1) | 2025.07.07 |
| 웹 성능 최적화 기법: chapter3 웹 사이트 성능을 개선하는 기본적인 방법 (1) | 2024.11.30 |