241204 노드 (웹서버 구축, npm, expess, 라우팅, express 라우팅)

241204 에이콘 아카데미 수업에 기반하여 작성되었음을 알립니다.

 

노드

노드는 모듈만 잘 가져다쓴다면 쉽게 사용가능하다.
얼마나 많은 모듈을 가져다 쓰느냐가 중요하다!
검색과 조립만 잘할줄 안다면 된다. 함수 지향형 언어의 특징이다. 파이썬, 노드 등등

노드 실습 (웹서버 구축)

ex13httpserver.mjs

import http from 'http'; // http 웹 모듈

http.createServer((req, res) => {
    
    res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'}); // statuscode와 mime type을 준다.
    res.write('<h1>환영 노드 여러분</h1>');
    res.write('안녕');
    res.end('<p>잘가</p>');
})
.listen(8080, () => {
    console.log('서버 서비스 중');
});

클라이언트의 요청이 없으면 무한 루프를 돌고 있음!

http서버가 자동으로 Elements를 만들어줌

브라우저 확인 서버가 해당 내용을 넘겨주었다. 단순하게 요청값을 요청하면 반응을 보이는 정도로만 구현하였다.


노드 실습 (npm : figlet 사용)

npm을 사용하면 모듈들을 가져다 쓸 수 있다.

https://www.npmjs.com/ 

npm으로 모듈을 가져다 설치하고 삭제하기

npm install figlet 설치

ex14figlet.mjs

// Ascii art 패키지 : figlet
import figlet from "figlet";

figlet("Node good packaga", function(err, data){
    if(err){
        console.log('wrong');
        return;
    }
    console.log(data);
});

모듈 사용하여 결과 출력

모듈 삭제 (npm uninstall 모듈이름)

다시 실행해보면 모듈이 없어 실행이 안되는 모습


노드 실습 (라우팅)

express

https://expressjs.com/
https://cafe.daum.net/flowlife/RM66/21
https://cafe.daum.net/flowlife/RM66/7
express : 노드를 위한 웹 프레임워크, 노드 사용시 웹 서버를 구축할 때 express를 사용한다.
MVC 패턴을 사용하여 웹서버를 구축할 수 있다.

npm i express 모듈 설치

index.mjs

 

import express from 'express';

//const express = require('express'); 옛날 방법
const app = express();

app.get('/', (req, res) => {
  res.send('hello world');
});

console.log('웹 서버 서비스 시작!');
app.listen(3000);

 

// app.get('/', (req, res) => {
//   res.send('hello world');
// });

요청을 주석처리하고 서버를 껏다 다시 키면 아래와 같다.

서버는 돌고있지만 요청이 없다.

nodemon

코드 변경 시 서버 자동 리로딩 하는 방법, Spring boot devTools와 같은 역할을 하는 nodemon 사용하기
Node.js 개발 시 자바 스크립트 파일들을 수정 할 때마다 매번 ctrl+c를 통해 node를 종료 후 다시 실행해줘야 하는 번거로움 이 있었다. 하지만 파일들을 모니터링하고 있다가 수정될 경우 자동으로 서버를 재실행시켜주는 스크립트 모니터링 유틸리티 nodemon를 이용하면 번거로움이 상당히 줄어든다.

설치 : npm install -g nodemon

환경 설정 : 

package.json

{
  "name": "project02",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon index.mjs" // nodemon 설정
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.21.1"
  }
}

app.get('/', (req, res) => {
  res.send('hello world good');
});

코드 변경

자동으로 서버 리로딩

새로고침 후 변경된 모습 확인

환경변수 설정

// 환경변수 설정 process.env 사용
// PORT외에도 여러개가 있음
// 환경변수 port가 존재하면 해당 port를 쓰고 아니면 3000을 쓴다.
app.set('port', process.env.PORT || 3000);

app.listen(app.get('port'), () => {
    console.log(app.get('port'), '번 포트에서 웹 서버 서비스 시작!');
});

라우팅

// __dirname을 esm 환경에서 사용하는 방법
const __filename = fileURLToPath(import.meta.url); // 현재 실행 중인 파일 경로
const __dirname = path.dirname(__filename); // 현재 실행 중인 디렉토리 경로


// 라우팅, 값을 읽을 때는 app.get() 사용
app.get('/', (req, res) => {
  res.send('hello world good');
});

app.get('/java', (req, res) => {
    res.send('<h2>Hello JAVA</h2>');
});

app.get('/node', (req, res) => {
    res.send('<a href="https://cafe.daum.net/flowlife">카페</a>');
});

app.get('/json', (req, res) => {
    res.json({'겨울':'첫눈이 폭설'});
});

app.get('/abc', (req, res) => {
    res.sendFile(path.join(__dirname, 'abc.html'));
});

abc.html

<body>
    <h1 id="title">abc 문서</h1>
</body>

abc.html (수정)

<body>
    <h1 id="title">abc 문서</h1>
    <script>
        setTimeout(() => {
            console.log("안녕 세상아");
            document.querySelector("#title").textContent = "자바스크립트가 짱이야!";
        },2000)
    </script>
</body>

2초후에 변경!,

같은 자바스크립트 언어라도 파싱(해석) 주체가 다르다! abc.html은 브라우저에서 파싱, index.mjs는 노드에서 파싱한다.

// 파라미터 받기
app.get('/user/:bun/:irum', (req, res) => {
    const {bun, irum} = req.params;
    res.json({bun, irum});
});

app.get('/user/:season', (req, res) => {
    const {season} = req.params;
    if(season === 'summer') {
        res.json({'season':'덥다 더워'});
    } else if(season === 'winter') {
        res.json({'season':'춥다 추워'});
    } else {
        res.json({'season':'너무 좋아'});
    }
});

app.get('/test', (req, res) => {
    res.sendFile(path.join(__dirname, 'test.html'));
});

test.html

<body>
    계절 : <input type="text" id="name" />
    <button onclick="getSeason()">확인</button>
    <script>
        function getSeason() {
            const name = document.querySelector("#name").value;
            fetch(`http://localhost:3000/user/${name}`)
            .then((response) =>  response.json())
            .then((data) => {
                console.log(data);
            })
        }
    </script>
</body>

다른 도메인으로도 접근해보기

파일 독립적으로 실행 file:///C:/work/nodesou/project02/test.html, 아파치 톰캣 서버

cors 정책으로 요청 안됨! 노드에서 다른 도메인에서의 접근을 허용해줘야함

cors

// cors 문제 해결
// npm install cors
import cors from 'cors';

const app = express();
app.use(cors()); // cors 문제 해결
// 미들웨어를 활성화

// 특정 도메인만 허용하는 방법
const corsOption = {
    origin:'http://234.233.7.98:80', // 특정 도메인 IP로 가정
    methods:['GET', 'POST', 'PUT'],
} 
app.use(cors(corsOption)); // 특정 도메인만 허용

아파치 톰캣 서버

파일 독립적으로 실행

같은 도메인


노드 실습 (express Router)

노드 프로젝트 생성 시 기본 설정 방법

mkdir 프로젝트명
npm init -y
npm i express
npm i cors
npm i nodemon

package.json

{
  "name": "project03",
  "version": "1.0.0",
  "main": "app.mjs",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon app.mjs"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.21.1",
    "nodemon": "^3.1.7"
  }
}

app.mjs (기본 설정)

기본 설정 이후 작업 시작하자

import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';

const app = express();
app.use(cors()); // cors 문제 해결

app.set('port', process.env.PORT || 3000); // 환경변수 port가 존재하면 해당 port를 쓰고 아니면 3000을 쓴다.

// __dirname을 esm 환경에서 사용하는 방법
const __filename = fileURLToPath(import.meta.url); // 현재 실행 중인 파일 경로
const __dirname = path.dirname(__filename); // 현재 실행 중인 디렉토리 경로

app.listen(app.get('port'), () => {
    console.log(app.get('port'), '번 포트에서 웹 서버 서비스 시작!');
});

jikwon.mjs

import { Router } from "express";

const router = Router();

router.get('/', (req, res) => { // http://localhost:3000/jikwon
    res.send('안녕 직원들아');
});

router.get('/nice', (req, res) => { // http://localhost:3000/jikwon/nice
    res.send('잘한다 직원들아');
});

// /jikwon/ 다음 요청은 여기서 결정한다.
router.get('/nice/:irum', (req, res) => { // http://localhost:3000/jikwon/nice
    const {irum} = req.params;
    res.send({우수직원 : irum});
});

export default router;

gogek.mjs

import { Router } from "express";

const router = Router();

router.get('/', (req, res) => {
    res.send('안녕 고객들아');
});

export default router;

app.mjs

import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';

import gogekRouter from './routes/gogek.mjs';
import jikwonRouter from './routes/jikwon.mjs';

const app = express();
app.use(cors()); // cors 문제 해결

app.set('port', process.env.PORT || 3000); // 환경변수 port가 존재하면 해당 port를 쓰고 아니면 3000을 쓴다.

// __dirname을 esm 환경에서 사용하는 방법
const __filename = fileURLToPath(import.meta.url); // 현재 실행 중인 파일 경로
const __dirname = path.dirname(__filename); // 현재 실행 중인 디렉토리 경로

// (req, res) 순서 중요
app.get('/', (req, res) => { 
    res.send('good');
});

app.use('/jikwon', jikwonRouter);
app.use('/gogek', gogekRouter);

app.listen(app.get('port'), () => {
    console.log(app.get('port'), '번 포트에서 웹 서버 서비스 시작!');
});

💡(req, res) 순서 중요
app.get('/', (res, req) => {
   res.send('good');
});

req, res 순서가 바뀌면 에러 떨어짐

'Study > Acorn' 카테고리의 다른 글

241206 노드 (세션)  (0) 2024.12.06
241205 노드 (get/post, 쿠키)  (0) 2024.12.05
241203 노드 (이벤트 처리, DB 연결)  (0) 2024.12.03
241202 노드 (개요, CommonJs, ESM, 동기/비동기)  (3) 2024.12.02
241129 뷰(RESTful)  (1) 2024.11.29