본문 바로가기

개인 공부 설명 모음

간단한 node.js Express CRUD 실습

시작. 

1. 폴더 만들고 명령어 npm init -y 

기본 설정으로 package.json 만드는 명령어

 

3. 디렉토리 폴더 views 만들고 views에 index.ejs 생성

간단한 CRUD UI 작성

 

4. app.js 생성 후

백엔드 서버 구축 후 CRUD API 작성

 

5. 최종 디렉토리

│
├── app.js # 메인 서버 파일
├── data.json # 데이터 저장 파일
├── package.json
├── package-lock.json
├── node_modules/
└── views/ # EJS 템플릿 파일
    └── index.ejs

 


views/index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- HTML 문서의 인코딩을 UTF-8로 설정 (한글 등 다양한 문자 지원) -->
  <meta charset="UTF-8">
  <!-- 페이지 제목 설정 -->
  <title>CRUD Example</title>
</head>
<body>
  <!-- 페이지의 메인 제목 -->
  <h1>ejs CRUD 실습 페이지</h1>

  <h2>생성 블록</h2>
  <!-- 게시글 생성 폼 -->
  <!-- 폼 데이터는 POST 요청으로 /create 경로에 전송 -->
  <form action="/create" method="POST">
    <!-- 제목 입력 필드 -->
    <label for="title">Title:</label>
    <input type="text" id="title" name="title" required>
    <!-- 설명 입력 필드 -->
    <label for="description">Description:</label>
    <textarea id="description" name="description" required></textarea>
    <!-- 폼 제출 버튼 -->
    <button type="submit">Create</button>
  </form>

  <!-- 구분선  -->
  <hr>

  <!-- 목록 -->
  <h2>Item List</h2>
  <!-- 게시글 목록을 출력 -->
  <ul>
    <!-- `items` 배열의 각 요소를 순회하며 HTML 리스트로 렌더링 -->
    <% items.forEach(item => { %>
      <li>
        <!-- 각 세기글의 제목과 설명 출력 -->
        <strong><%= item.title %></strong>: <%= item.description %>
        
        <!-- 수정폼 -->
        <!-- 게시글 업데이트 폼 -->
        <!-- 특정 아이템의 id를 URL에 포함하여 POST 요청으로 전송 -->
        <form action="/edit/<%= item.id %>" method="POST" style="display:inline;">
          <!-- 현재 게시글의 제목을 입력 필드로 제공 -->
          <input type="text" name="title" value="<%= item.title %>" required>
          <!-- 현재 게시굴의 설명을 입력 필드로 제공 -->
          <input type="text" name="description" value="<%= item.description %>" required>
          <!-- 업데이트 버튼 -->
          <button type="submit">Update</button>
        </form>

        <!-- 삭제폼 -->
        <!-- 삭제 폼 -->
        <!-- 특정 게시글의 id를 URL에 포함하여 POST 요청으로 전송 -->
        <form action="/delete/<%= item.id %>" method="POST" style="display:inline;">
          <!-- 삭제 버튼 -->
          <button type="submit">Delete</button>
        </form>
      </li>
    <% }); %>
  </ul>
</body>
</html>

 

EJS에서 <%= %>의 역할

  • HTML에 데이터를 출력할 때 사용됩니다.
  • JavaScript 코드를 실행한 결과를 HTML에 삽입합니다.
  • 데이터가 화면에 그대로 렌더링됩니다.

주석 설명 요약

  1. HTML 구조:
    • <!DOCTYPE html>: 문서 타입 선언.
    • <html>: HTML 문서의 루트 요소.
    • <head>: 메타데이터 및 제목 설정.
    • <body>: 실제 콘텐츠가 렌더링되는 부분.
  2. 게시판 생성 폼:
    • /create 경로로 POST 요청을 보냅니다.
    • title과 description을 입력받아 서버에 전송.
  3. 게시판 목록 출력:
    • 서버에서 전달된 items 배열을 순회(forEach)하며 리스트를 출력.
    • <%= ... %>를 사용해 EJS에서 값을 출력.
  4. 게시판 수정 폼:
    • 각 아이템마다 개별 수정 폼이 생성됩니다.
    • id를 URL에 포함하여 어떤 게시글을 수정할지 서버에 전달.
    • 기존 제목과 설명을 입력 필드에 기본값으로 설정.
  5. 게시판 삭제 폼:
    • 각 게시글마다 개별 삭제 폼이 생성됩니다.
    • id를 URL에 포함하여 삭제 요청을 서버에 전달.

 


 

app.js

// Express 모듈을 가져옵니다. Express는 웹 서버를 쉽게 구성할 수 있게 도와주는 프레임워크입니다.
const express = require('express');

// body-parser 모듈을 가져옵니다. 요청에서 전송된 데이터를 읽고 처리하는 데 사용됩니다.
const bodyParser = require('body-parser');

// fs 모듈을 가져옵니다. 파일 시스템과 상호작용(파일 읽기/쓰기)하는 데 사용됩니다.
const fs = require('fs');

// Express 애플리케이션을 초기화합니다.
const app = express();

// 서버가 실행될 포트를 설정합니다.
const PORT = 3000;

// -------------------- 미들웨어 --------------------

// body-parser를 사용해 요청 본문 데이터를 URL-encoded 형식으로 처리할 수 있게 설정합니다.
app.use(bodyParser.urlencoded({ extended: true }));

// EJS를 템플릿 엔진으로 설정합니다. EJS 파일을 렌더링하여 동적으로 HTML을 생성합니다.
app.set('view engine', 'ejs');

// -------------------- 데이터 로드 --------------------

// 서버 실행 시 데이터를 로드합니다.
// 'data.json' 파일의 내용을 읽고 JSON 형식으로 파싱하여 `data` 변수에 저장합니다.
let data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'));

// -------------------- 루트 API --------------------

// 메인 페이지 - 게시글 목록을 읽어서 클라이언트에 전달합니다.
app.get('/', (req, res) => {
  // 'index.ejs' 템플릿을 렌더링하며, 현재 `data`를 `items` 변수로 전달합니다.
  res.render('index', { items: data });
});

// 새로운 게시글 생성 (POST 요청 처리)
app.post('/create', (req, res) => {
  // 클라이언트로부터 전달받은 제목과 설명으로 새 newItem 객체를 만듭니다.
  const newItem = {
    id: Date.now(), // 현재 시간을 고유 ID로 사용합니다.
    title: req.body.title, // 요청 본문에서 제목을 가져옵니다.
    description: req.body.description, // 요청 본문에서 설명을 가져옵니다.
  };

  // 새 게시글을 `data` 배열에 추가합니다.
  data.push(newItem);

  // 업데이트된 데이터를 'data.json' 파일에 저장합니다.
  fs.writeFileSync('./data.json', JSON.stringify(data, null, 2));

  // 작업 완료 후 메인 페이지로 리다이렉트합니다.
  res.redirect('/');
});

// 게시글 수정 (POST 요청 처리)
app.post('/edit/:id', (req, res) => {
  // URL에서 전달된 ID로 수정할 게시글을 찾습니다.
  const index = data.findIndex(d => d.id == req.params.id);

  // 게시글이 존재하면 데이터를 업데이트합니다.
  if (index !== -1) {
    data[index].title = req.body.title; // 요청 본문에서 새로운 제목을 가져와 업데이트합니다.
    data[index].description = req.body.description; // 새로운 설명으로 업데이트합니다.

    // 업데이트된 데이터를 'data.json' 파일에 저장합니다.
    fs.writeFileSync('./data.json', JSON.stringify(data, null, 2));
  }

  // 작업 완료 후 메인 페이지로 리다이렉트합니다.
  res.redirect('/');
});

// 게시글 삭제 (POST 요청 처리)
app.post('/delete/:id', (req, res) => {
  // URL에서 전달된 ID를 제외한 게시글만 남깁니다.
  data = data.filter(d => d.id != req.params.id);

  // 업데이트된 데이터를 'data.json' 파일에 저장합니다.
  fs.writeFileSync('./data.json', JSON.stringify(data, null, 2));

  // 작업 완료 후 메인 페이지로 리다이렉트합니다.
  res.redirect('/');
});

// -------------------- 서버 시작 --------------------

// 서버를 지정된 포트에서 실행합니다.
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

 

주석 설명 요약

  • 모듈: 각종 모듈의 역할과 사용 방법을 설명.
  • Middleware: 데이터를 처리하고, 템플릿 엔진을 설정하는 중간 처리 과정 설명.
  • Load Data: 파일에서 데이터를 읽어오는 과정 설명.
  • Routes: 각 경로(GET, POST 등)의 목적과 주요 로직 설명.
  • Start Server: 서버를 시작하고 사용자가 접근 가능한 URL 출력.

'개인 공부 설명 모음' 카테고리의 다른 글

윈도우/리눅스 curl 명령어  (0) 2026.06.03
정보의 표현 - 1  (0) 2025.03.06
컴퓨터 입문  (2) 2025.03.06
Python 리스트, 튜플, 딕셔너리, 집합 등 기본 자료구조 실습  (0) 2024.11.17
변수 Python  (1) 2024.11.17