학습
JavaScript Node.js 기초
JavaScript Node.js 기초 — 고급
Node.js 기초
1. 도입 (왜 배워야 하는가)
Node.js는 JavaScript를 서버 측에서 실행할 수 있게 해주는 런타임 환경입니다. 현대 웹 애플리케이션의 대부분은 클라이언트와 서버 간의 비동기 통신을 요구하며, Node.js는 이러한 요구를 충족시키기 위해 설계되었습니다.
실무에서 Node.js를 사용할 경우, 다음과 같은 이점이 있습니다:
- 비동기 처리: Node.js는 이벤트 기반이며, 비동기 I/O를 통해 높은 성능을 발휘합니다.
- JavaScript 통일성: 프론트엔드와 백엔드 모두 JavaScript로 작성할 수 있어 개발자가 하나의 언어로 전체 애플리케이션을 관리할 수 있습니다.
- 거대한 생태계: NPM(노드 패키지 매니저)을 통해 다양한 패키지를 쉽게 설치하고 사용할 수 있습니다.
- 정의: 이벤트 루프는 Node.js가 비동기 작업을 처리하는 방식입니다. 싱글 스레드로 작동하며, 비동기 작업이 완료되면 콜백을 호출합니다.
- 비유: 주방에서 요리를 할 때, 요리사가 하나의 요리를 하면서 동시에 다른 재료를 준비하는 것과 같다고 생각할 수 있습니다.
- 정의: 비동기 I/O는 작업을 요청한 후, 해당 작업이 완료될 때까지 기다리지 않고 다음 작업을 수행할 수 있게 해주는 방식입니다.
- 비유: 친구에게 대화를 걸고, 답변이 오기 전에 다른 친구와 대화하는 것과 비슷합니다.
Node.js를 모르면 고성능 서버를 구축하기 어렵고, 최신 웹 개발 트렌드에 뒤처질 수 있습니다. 또한, 다른 언어로 작성된 서버와의 통합이 복잡해질 수 있습니다.
2. 핵심 개념 설명
이벤트 루프 (Event Loop)
비동기 I/O (Asynchronous I/O)
관련 용어 정리
| 용어 | 설명 |
|---|---|
| 콜백 (Callback) | 비동기 작업이 완료된 후 실행되는 함수 |
| 프라미스 (Promise) | 비동기 작업의 결과를 나타내는 객체 |
| async/await | 비동기 코드를 더 읽기 쉽게 만들어주는 구문 |
3. 기본 코드 예제
Node.js의 기본적인 HTTP 서버를 만들어 보겠습니다.
const http = require('http'); // http 모듈을 가져옵니다.
const server = http.createServer((req, res) => { // 서버를 생성합니다.
res.statusCode = 200; // 응답 상태 코드를 200으로 설정합니다.
res.setHeader('Content-Type', 'text/plain'); // 응답 헤더에 Content-Type을 설정합니다.
res.end('Hello, World!\n'); // 응답 본문을 설정하고 응답을 종료합니다.
});
const PORT = 3000; // 포트 번호를 설정합니다.
server.listen(PORT, () => { // 서버를 해당 포트에서 대기하게 합니다.
console.log(서버가 http://localhost:${PORT}에서 실행 중입니다.); // 서버 실행 메시지를 출력합니다.
});
실행 결과:
서버가 http://localhost:3000에서 실행 중입니다.
http 모듈을 가져옵니다. 이 모듈은 HTTP 서버를 만들 때 필요합니다.createServer 메서드를 사용해 서버를 생성합니다. 이 메서드는 요청이 들어올 때마다 호출되는 콜백 함수를 받습니다.listen 메서드를 호출하여 서버를 시작하고, 시작 메시지를 콘솔에 출력합니다.4. 실전 활용 예제
예제 1: 쇼핑몰에서 장바구니 기능 구현
장바구니에 상품을 추가하는 API를 만들어 보겠습니다.
const express = require('express'); // express 모듈을 가져옵니다.
const app = express(); // express 애플리케이션을 생성합니다.
app.use(express.json()); // JSON 형식의 요청 본문을 처리할 수 있게 합니다.
let cart = []; // 장바구니를 저장할 배열입니다.
app.post('/cart', (req, res) => { // POST 요청을 처리하는 엔드포인트를 생성합니다.
const item = req.body; // 요청 본문에서 아이템을 가져옵니다.
cart.push(item); // 장바구니에 아이템을 추가합니다.
res.status(201).send('아이템이 장바구니에 추가되었습니다.'); // 성공 응답을 보냅니다.
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(서버가 http://localhost:${PORT}에서 실행 중입니다.);
});
이 코드는 장바구니에 상품을 추가하는 기능을 제공합니다. 클라이언트에서 POST 요청을 보내면, 해당 상품이 장바구니 배열에 추가됩니다.
예제 2: 사용자 인증 기능 구현
사용자 로그인 기능을 추가해 보겠습니다.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
let users = { 'user1': 'password1' }; // 사용자 정보를 저장한 객체입니다.
app.post('/login', (req, res) => {
const { username, password } = req.body; // 요청 본문에서 사용자명과 비밀번호를 가져옵니다.
if (users[username] && users[username] === password) { // 사용자 인증 확인
res.status(200).send('로그인 성공!'); // 성공 응답
} else {
res.status(401).send('로그인 실패!'); // 실패 응답
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(서버가 http://localhost:${PORT}에서 실행 중입니다.);
});
이 코드는 사용자가 입력한 사용자명과 비밀번호를 확인하여 로그인 여부를 판단합니다.
5. 흔한 실수와 주의사항
실수 1: 비동기 코드를 동기처럼 처리하기
const fs = require('fs');
const data = fs.readFileSync('file.txt'); // 동기적으로 파일을 읽으려고 합니다.
console.log(data); // 데이터가 없거나 에러가 발생할 수 있습니다.
올바른 코드:
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => { // 비동기적으로 파일을 읽습니다.
if (err) {
console.error(err);
return;
}
console.log(data); // 정상적으로 파일 내용을 출력합니다.
});
실수 2: 콜백 지옥
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('결과:', finalResult);
});
});
});
올바른 코드 (Promise 사용):
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log('결과:', finalResult))
.catch(err => console.error(err)); // 에러 처리
6. 정리
다음에 학습하면 좋은 주제: