프로그래밍/Node.js

Node.js를 활용한 네트워킹: HTTP 서버, 요청 및 응답 처리, 웹 소켓 사용하기

shimdh 2025. 2. 19. 00:14
728x90

1. HTTP 서버 생성 및 기본 동작

1.1 HTTP 서버의 기본 개념

HTTP(HyperText Transfer Protocol)는 웹 브라우저와 웹 서버 간의 통신 프로토콜입니다. 웹 페이지 요청 시, 브라우저는 HTTP를 통해 서버에 요청을 보내고, 서버는 요청에 대한 응답을 반환합니다. Node.js는 내장 http 모듈을 통해 이러한 HTTP 서버를 쉽게 만들 수 있습니다.

1.2 기본적인 HTTP 서버 생성 및 실행

아래 예제는 Node.js에서 가장 기본적인 HTTP 서버를 구현하는 방법을 보여줍니다.

const http = require('http');

// 서버가 사용할 포트 번호 설정
const PORT = 3000;

// HTTP 서버 생성
const server = http.createServer((req, res) => {
    // 응답 헤더 설정 (상태 코드 200, 컨텐츠 타입: 일반 텍스트)
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    // 응답 본문 작성 및 전송
    res.end('안녕하세요! Node.js로 만든 HTTP 서버입니다.\n');
});

// 지정된 포트에서 서버 시작 및 리스닝 대기
server.listen(PORT, () => {
    console.log(`서버가 http://localhost:${PORT} 에서 실행 중입니다.`);
});

추가 예제: 동적 포트 설정 및 환경 변수 활용

const http = require('http');

// 환경 변수에 PORT가 설정되어 있으면 사용, 아니면 3000을 기본으로 사용
const PORT = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end(`서버가 포트 ${PORT} 에서 실행 중입니다.\n`);
});

server.listen(PORT, () => {
    console.log(`서버가 http://localhost:${PORT} 에서 실행 중입니다.`);
});

1.3 요청 및 응답 처리: 라우팅 구현

HTTP 요청에는 URL 경로, 쿼리 문자열 등의 정보가 포함됩니다. 이 정보를 이용하여 서버는 클라이언트에게 동적인 응답을 제공할 수 있습니다.

기본 예제: URL 경로에 따른 응답 분기 처리

const http = require('http');

const server = http.createServer((req, res) => {
    const url = req.url;

    if (url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end('<h1>홈페이지</h1>');
    } else if (url === '/about') {
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end('<h1>소개 페이지</h1>');
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 - 페이지를 찾을 수 없습니다.');
    }
});

server.listen(3000, () => {
    console.log('서버가 실행 중...');
});

추가 예제: URL 쿼리 파라미터 처리 및 활용

const http = require('http');
const url = require('url'); // URL 모듈 추가

const server = http.createServer((req, res) => {
    const parsedUrl = url.parse(req.url, true); // 쿼리 파라미터 파싱
    const path = parsedUrl.pathname;
    const query = parsedUrl.query;

    if (path === '/greet') {
        const name = query.name || 'Guest';
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end(`안녕하세요, ${name}님!\n`);
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 - 페이지를 찾을 수 없습니다.\n');
    }
});

server.listen(3000, () => {
  console.log('서버가 실행 중...');
});

1.4 JSON 데이터 응답 처리

JSON은 웹 애플리케이션에서 데이터를 교환하는 데 널리 사용되는 형식입니다. 아래는 Node.js에서 JSON 데이터를 응답으로 보내는 예제입니다.

기본 예제: 정적 JSON 데이터 전송

const http = require('http');

const server = http.createServer((req, res) => {
    const data = { message: "안녕하세요!" };

    // 응답 헤더 설정 (상태 코드 200, 컨텐츠 타입: JSON)
    res.writeHead(200, { 'Content-Type': 'application/json' });
    // JSON 데이터 전송
    res.end(JSON.stringify(data));
});

server.listen(3000, () => {
    console.log('JSON 데이터를 제공하는 서버 실행 중...');
});

추가 예제: 동적으로 생성된 JSON 데이터 전송

const http = require('http');

const server = http.createServer((req, res) => {
    const timestamp = new Date().toISOString();
    const data = { 
        message: "안녕하세요!",
        timestamp: timestamp
    };

    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(data));
});

server.listen(3000, () => {
    console.log('동적 JSON 데이터를 제공하는 서버 실행 중...');
});

2. HTTP 요청 및 응답 심층 처리

2.1 HTTP 요청 및 응답의 이해

  • HTTP 요청: 클라이언트(웹 브라우저 등)가 서버에게 데이터를 요청하는 행위입니다. 주요 요청 메서드로는 GET, POST, PUT, DELETE 등이 있습니다.
  • HTTP 응답: 서버가 클라이언트 요청에 대해 반환하는 데이터입니다. 상태 코드(200, 404 등), 헤더 정보 및 본문 내용을 포함합니다.

2.2 Node.js에서 HTTP 서버 생성 및 요청 처리

Node.js http 모듈을 이용하여, 요청 메서드 및 URL에 따라 다양한 응답을 생성할 수 있습니다.

기본 예제: URL 경로에 따른 다른 응답 처리

const http = require('http');

const server = http.createServer((req, res) => {
    // 요청 URL에 따라 다른 응답 제공
    if (req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('안녕하세요! 홈 페이지입니다.');
    } else if (req.url === '/about') {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('안녕하세요! About 페이지입니다.');
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('페이지를 찾을 수 없습니다.');
    }
});

server.listen(3000, () => {
    console.log('서버가 http://localhost:3000 에서 실행되고 있습니다.');
});

추가 예제: POST 요청 처리 및 데이터 수신

const http = require('http');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/submit') {
        let body = '';

        req.on('data', chunk => {
            body += chunk.toString(); // 데이터 수집
        });

        req.on('end', () => {
            res.writeHead(200, { 'Content-Type': 'text/plain' });
            res.end(`받은 데이터: ${body}`);
        });
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 - 페이지를 찾을 수 없습니다.');
    }
});

server.listen(3000, () => {
  console.log('서버가 실행 중...');
});

2.3 Node.js 비동기 처리 모델의 활용

Node.js의 비동기 프로그래밍 모델은 여러 클라이언트의 동시 요청을 효율적으로 처리하는 데 핵심적인 역할을 합니다.

기본 예제: 비동기 파일 읽기 및 응답

const fs = require('fs');
const http = require('http');

const server = http.createServer((req, res) => {
    fs.readFile('./data.txt', (err, data) => {
        if (err) {
            res.writeHead(500);
            return res.end('파일 읽기 실패');
        }

        res.writeHead(200);
        res.end(data);
    });
});

server.listen(3000, () => {
  console.log('서버가 실행 중...');
});

추가 예제: 비동기 파일 업로드 처리

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/upload') {
        const fileStream = fs.createWriteStream('./uploaded_file.txt');
        req.pipe(fileStream); // 요청 데이터를 파일로 스트리밍

        req.on('end', () => {
            res.writeHead(200, { 'Content-Type': 'text/plain' });
            res.end('파일 업로드 완료!');
        });
    } else {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('404 - 페이지를 찾을 수 없습니다.');
    }
});

server.listen(3000, () => {
  console.log('서버가 실행 중...');
});

3. 웹 소켓(WebSocket)을 이용한 실시간 통신

3.1 웹 소켓의 기본 원리

웹 소켓은 클라이언트와 서버 간 양방향 통신을 가능하게 하는 프로토콜입니다. HTTP와 달리, 지속적인 연결을 통해 실시간 데이터 전송이 가능합니다.

3.2 Node.js에서 웹 소켓 구현

Node.js에서는 ws 패키지를 사용하여 간편하게 웹 소켓 기능을 구현할 수 있습니다.

기본 예제: 웹 소켓 서버 생성 및 메시지 송수신

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('클라이언트가 연결되었습니다.');

    ws.on('message', (message) => {
        console.log(`서버 received message => ${message}`);

        wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(`서버로부터 받은 메시지 : ${message}`);
            }
        });
    });

    ws.send('환영합니다! 당신은 이제 채팅방에 들어왔습니다.');
});

추가 예제: 클라이언트 연결 상태 관리 및 메시지 처리

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('클라이언트가 연결되었습니다.');

    ws.on('close', () => {
        console.log('클라이언트가 연결을 종료했습니다.');
    });

    ws.on('message', (message) => {
        console.log(`서버 received message => ${message}`);

        wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(`서버로부터 받은 메시지 : ${message}`);
            }
        });
    });

    ws.send('환영합니다! 당신은 이제 채팅방에 들어왔습니다.');
});

4. 결론

본 포스트에서는 Node.js를 이용하여 HTTP 서버를 구축하고, 클라이언트의 요청과 서버의 응답을 처리하는 방법, 그리고 웹 소켓을 활용하여 실시간 양방향 통신을 구현하는 방법을 자세히 살펴보았습니다. 각 섹션별로 추가된 예제들을 통해 Node.js의 네트워킹 기능을 더욱 깊이 있게 이해하는 데 도움이 되었기를 바랍니다. 이러한 기술들은 현대 웹 애플리케이션 개발에서 매우 중요한 역할을 담당하며, 사용자 경험 향상에 큰 기여를 할 수 있습니다. 이 기술들을 효과적으로 활용하여 더욱 강력하고 효율적인 웹 애플리케이션을 개발하시기 바랍니다.

728x90