heron

발단

동아리에서 간단한 프로젝트를 진행하게 되었다. 그리고 그 프로젝트에서 Express.js를 사용하여 웹페이지를 서비스 하기로 정했다.

개인적으로는 PHP를 사용하기를 바랬지만... 아쉽게도 밀어붙일 수가 없었다.

PHP는 구닥다리 기술이라는 인식이 널리 퍼져 있고, Node.js에서 무엇을 해도 전도유망하다 평가받으니 말이다.

그래서 처음으로 서버사이드 언어를 공부하는 후배와 학우에게 PHP를 쓰자고 강하게 주장할 수 없었다.

그들이 PHP 개발자가 되고 싶지는 않을 것 아닌가?

1일차

1일차 작업 내용

  1. 서브도메인 설정.

    첫날(24년 4월 3일)에는 서브도메인을 먼저 설정했다. 원활한 실습을 위해서 필요하다고 판단했다. 궁극적인 목적이 form의 내용을 DB에 전송하는 것 이므로, 결국 서버에서 실습을 해야 한다.

    며칠 전에 작성한 글이 있다.

    서브도메인 설정에 대한 포스팅.

    위의 글은, Node.js의 실습을 위한 서브도메인을 설정하는 과정에서 마주친 문제를 해결한 방법에 대한 것이다.

    그리하여 성공적으로 서브도메인을 설정했다.

  2. Node.js 업데이트

    Node.js를 업데이트 하는 과정에서 우여곡절이 많았지만, 결국 잘 업데이트 했다.

    기존에는 v12.xx.xx가 설치되어 있었다. 업데이트가 정말로 굉장히 어려웠다. 왜 이리도 오류가 많이 발생하고, 설정이 복잡한지...

2일차

개요

2일차에는 별 것 하지 않았다.

Express.js의 공식 문서와, Node.js에 관련된 블로그 포스팅을 여럿 읽어보았다.

이어서 Express.js를 설치하고, 정적 문서 라우팅을 먼저 시도했다.

하단에 기초 문법을 설명해 보겠다.


문법 설명

아래는 Node.js의 공식 페이지의 코드 일부이다. 링크!

1
2
3
4
5
6
7
8
9
10
11
const { createServer } = require('node:http');
const hostname = '127.0.0.1';
const port = 3000;
const server = createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type''text/plain');
  res.end('Hello World');
});
server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
cs

총평

간단하다. 상당히 깔끔한 구조로 보인다. 왜 인기있는지 알겠다.

다만 마음에 들지 않는다. 사용자의 요청을 처리할 내용을 createServer() 내부에 정의하는 부분이 특히 마음에 들지 않는다.

코드가 필연적으로 복잡해지지 않겠는가? 흠... 프로젝트의 규모가 크다면, 코드를 간결하게 작성할 방법을 찾아보아야 할 것이다.

3일차

개요

3일차에는 Express.js로 POST요청을 처리하는 방법을 찾아보았다.


기초 문법 설명

아래는 Express.js의 공식 페이지의 코드 일부이다. 링크!

1
2
3
4
5
6
7
8
9
10
11
const express = require('express')
const app = express()
const port = 3000
 
app.get('/', (req, res) => {
  res.send('Hello World!')
})
 
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
cs

주의할 점

Express.js의 라우팅 함수들은 경로 기반으로 동작한다. 예를 들자면...

app.post('/submit-name', (req, res) => {~~함수의 내용 정의~~});

위와 같은 함수가 존재할 때 해당 함수의 호출은, 루트 경로 아래의 submit-name을 요청할 때 이루어진다는 것이다. 해당 파일의 실존 여부는 중요하지 않다. 해당 파일(경로)의 요청이 있을 때, 해당 요청에 대하여 어떻게 행동할지가 정의되어 있는 경우에만 정상적인 응답이 일어나는 것이다.

그러므로 위에서 제시한 코드의 5행은, 루트 경로('/')로의 get 요청을 처리하는 함수인 것이다.


POST요청 처리 예시

그렇다면 이제 POST 요청을 처리할 수 있다. (mysql과 통신하는 방법도 공식문서에서 친절하게 설명해주었다. 링크!)

아래는 form으로 전송된 이름을 DB에 전송하는 코드이다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const express = require('express');
const app = express();
const port = 3000;
 
//node.js의 모듈 path 를 불러오는 코드.
//이 모듈은 디렉터리 경로 작업에 필요한 함수들 제공.
const path = require('path');
 
//루트 경로로의 접속에 대하여, 해당 html 파일 전송.
app.get('/', (req, res) =>; {
 
    //path.join() : 여러 경로를 합하는 역할 함.
    //__dirname : 현재 코드가 실행되고 있는 디렉터리의 절대경로.
    //sendFile('절대경로') : 경로상의 파일을 전송함.
    res.sendFile(path.join(__dirname, 'index.html'));
    //즉, 현재 작업 경로의 index.html 파일에 접근하여 파일 전송.
})
 
// URL-encoded 데이터를 파싱하는 미들웨어를 추가합니다. - gpt 답변.
//이는 POST 요청을 해석하기 위해 필요.
app.use(express.urlencoded({ extended: true }));
 
//경로 기반으로 node.js가 응답한다.
//즉, "/submit-name"의 경로로 form이 전송하면, 해당 경로로의 post 입력을 아래 코드가 전달받는다.
app.post('/submit-name', (req, res) =>; {
    // req.body에서 데이터를 가져옵니다.
    const name = req.body.name;  //name 속성이 name인 태그의 입력값을 name 변수에 저장.
    //name 변수 = name속성값이 'name'인 태그의 input 값.
 
    res.send(`입력받은 값 : ${name}`);
 
    //여기서 DB와의 통신 수행하면 됨.
    var mysql = require('mysql');  //모듈 로드.
 
    //임시로 유저 이름을 ----- 로 지음.
    //연결시에 사용할 모든 정보를 mysql모듈 내부에 저장.
    var connection = mysql.createConnection({
        host        : 'localhost',
        user        : '#유저이름#',  //보안상의 이유로 가림.
        database    : '#DB 이름',  //보안상의 이유로 가림.
        //테이블 이름은 query문에 작성하도록 함.
        password    : '#유저에 대응되는 PW#'  //보안상의 이유로 가림.
    })
 
    connection.connect();  //연결 시작.
 
    //sql문 쿼리.
    //` 와 ' 는 다름. 전자는 백틱(`), 후자는 작은따옴표('). 
    //js에서는 문자열 템플릿을 작성할 때 사용.
    //백틱으로 작성된 문자열에는 변수가 중간에 삽입될 수 있음.
    connection.query(`INSERT INTO TEST_TB (name) VALUE ('${name}')`, (err, rows, fields) => {
        if(err) throw err;  //에러 발생시 중단.
        console.log('success!');
    })
 
    connection.end();  //연결 중단.
});
 
//응답 대기.
app.listen(port, () =>; {
    console.log(`example... listening on port : '${port}'`);
})
cs

위의 코드는 실제로 서브도메인에서 검증되었다. DB에 정상적으로 쿼리가 전송되는 것을 확인했다.

주석을 상세히 작성했기에, 꼼꼼히 살펴본다면 Express.js로 POST 요청을 처리하는 방법을 이해할 수 있을 것이다.


총평

apache의 정적 라우팅과 PHP의 동적 페이지 작성에 의존해왔던 입장에서 보자면... Node.js의 방식이 굉장히 재미있다.

개인 블로그를 운영하는데 동적 라우팅이 필요하지는 않지만... 좋은 경험이 되었다.