본 포스트는 Express 기반의 Node.js 애플리케이션 서버를 구성할 때 mysql2 라이브러리를 이용하여 MySQL 연계 환경을 구성하는 방법을 설명합니다.

 

Node.js Express mysql2 환경 설정

 

express 서버의 기본적인 환경 설정은 이전 포스트인 아래 링크를 참고하여 설정합니다. 아래 포스트에서 설정한 내용에 이어서 MySQL 환경 구성을 진행해보겠습니다.

 

Node.js Express 환경 설정 :: 즐거운인생 (tistory.com)

 

Node.js Express 환경 설정

본 포스트는 Express 기반의 Node.js 애플리케이션 서버를 구성하고 static 경로를 설정하는 방법을 설명합니다. 서론 Node.js 서버 애플리케이션을 개발할 때 주로 사용하는 Framework는 Express와 Nest 정도

redballs.tistory.com

 

MySQL 설치

먼저 사용할 데이터베이스를 로컬에 설치 해보겠습니다. MySQL은 아래 링크에서 자신의 환경에 맞는 설치 파일을 다운로드하여 설치합니다.

https://dev.mysql.com/downloads/mysql/

 

MySQL :: Download MySQL Community Server

Select Operating System: Select Operating System… Microsoft Windows Ubuntu Linux Debian Linux SUSE Linux Enterprise Server Red Hat Enterprise Linux / Oracle Linux Fedora Linux - Generic Oracle Solaris macOS Source Code Select OS Version: All Windows (x86

dev.mysql.com

 

설치 과정은 별로 특별할 것이 없으므로 별도로 설명하지 않습니다. 설치 과정 중 MySQL root 계정을 설정하는 부분이 있는데 본인이 사용할 root 계정을 정확하게 입력하고 기억합니다.

 

접속정보 설정

설치가 완료되었다면 MySQL Workbench를 켜고 일단 root 계정으로 접속합니다.

MySQL Workbench

 

위 스크린 샷의 MySQL Connections 부분에 [+] 버튼을 클릭하여 새로운 Connection을 하나 생성하는데, 계정의 비밀번호를 Keychain에 저장하고 싶으면 [Store in Keychain ...] 버튼을 클릭하여 비밀번호를 기억시켜 둡니다. 여기서는 굳이 비밀번호는 저장하지 않겠습니다.

새 Connection 생성

식별할 수 있는 Connection Name과 접속 정보를 확인한 후 [OK] 버튼을 선택하면 아래와 같이 Connection이 하나 생성됩니다.

Connection 생성 확인

 

선택하고 비밀번호를 입력하여 root 계정으로 로그인 합니다.

데이터베이스 접속

 

데이터베이스 생성

이제 사용할 데이터베이스 및 사용자를 하나씩 생성해 보겠습니다. 먼저 아래 스크립트로 데이터베이스를 먼저 생성합니다.

CREATE DATABASE testDB DEFAULT CHARACTER SET utf8 collate utf8_general_ci;

 

testDB 라는 이름의 데이터베이스를 하나 생성하고 해당 데이터베이스의 기본 Charater-set을 UTF-8로 설정합니다. 이어서 사용자 계정도 하나 생성합니다. testid 라는 계정을 생성하고 비밀번호는 test01!로 생성하겠습니다.

CREATE USER 'testid'@'%' IDENTIFIED BY 'test01!';

 

이제 생성한 계정에 testDB의 개체들을 사용할 수 있는 권한을 부여합니다. 

GRANT ALL PRIVILEGES ON testDB.* to 'testid'@'%';

 

다시 로그인해서 정상적으로 로그인이 되는지 확인합니다. 위에서 하신대로 [New Connection]을 하나 열고 로그인하시면 됩니다.

생성한 계정으로 로그인

테스트에 사용할 테이블을 하나 생성합니다.

CREATE TABLE TB_TEST (
    TEST_ID int,
    TEST_TXT varchar(100),
    PRIMARY KEY(TEST_ID)
)

 

생성한 테이블에 데이터를 한 건 입력하고 SELECT 해서 테이블이 정상적으로 생성되었는지 확인합니다.

INSERT INTO TB_TEST VALUES (1, 'TEST');

SELECT  *
  FROM  TB_TEST

 

Node.js 프로젝트 설정

위와 같이 데이터베이스에 대한 설정을 마쳤으면 이제 Node.js 에서 해당 데이터베이스를 사용하도록 설정합니다. 위의 포스트를 따라해서 "Hello World"까지 출력해 본 상태라면 현재 package.json은 express 모듈만 설치하여 아래와 같은 상태입니다.

{
  "name": "express",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "express": "^4.18.1"
  },
  "scripts": {
    "start": "node ./src/app.js"
  }
}

 

MySQL 데이터베이스를 연동하기 위해 mysql2 모듈을 설치합니다.

D:\workspace\expressServer>yarn add mysql2

 

MySQL 연동을 위한 소스코드를 app.js 파일에 추가합니다. mysql2 모듈을 추가하고 Connection Pool을 생성합니다. 위에서 생성한 데이터베이스 및 계정 정보를 입력하여 생성합니다.

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
    host: 'localhost',
    port: '3306',
    user: 'testid',
    password: 'test01!',
    database: 'testDB'
});

const getConn = async() => {
    return await pool.getConnection(async (conn) => conn);
};

 

testSelect라는 Route를 추가하고 간단하게 TB_TEST 테이블의 정보를 조회하는 쿼리를 실행하도록 작성합니다.

app.get('/testSelect', async (req, res) => {
    const conn = await getConn();
    const query = 'SELECT TEST_ID, TEST_TXT FROM TB_TEST';
    let [rows, fields] = await conn.query(query, []);
    conn.release();

    res.send(rows);
});

 

위 내용들을 추가한 app.js의 전체 소스코드는 아래와 같습니다.

const express = require('express');
const path = require('path');
const app = express();
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
    host: 'localhost',
    port: '3306',
    user: 'testid',
    password: 'test01!',
    database: 'testDB'
});

const getConn = async() => {
    return await pool.getConnection(async (conn) => conn);
};

app.use(express.static(path.join(__dirname, '../public')));
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../public/index.html'));
});

app.get('/testSelect', async (req, res) => {
    const conn = await getConn();
    const query = 'SELECT TEST_ID, TEST_TXT FROM TB_TEST';
    let [rows, fields] = await conn.query(query, []);
    conn.release();

    res.send(rows);
});

app.listen('8001', () => {
    console.log('Server started');
});

 

실행 결과 확인

브라우저에 http://localhost:8001/testSelect 를 입력하여 접근하면 아래와 같은 결과를 확인할 수 있습니다.

[{"TEST_ID":1,"TEST_TXT":"TEST"}]

 

300x250

'Node.js > express 환경구성' 카테고리의 다른 글

Node.js Express 환경 설정  (0) 2022.07.15

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

 

React + Express + TypeScript 프로젝트 구성하기

 

이전 포스트에서는 express 서버에서 개발한 API에서 사용하는 데이터와 동일한 형태로 uiModule에도 /src/interface/apidata.interface.ts 파일에 데이터를 선언했습니다. 이번 포스트에서는 해당 데이터 타입을 사용하는 API 인터페이스 부분을 작성해 보겠습니다.

 

/src/component/listview.component.tsx 파일을 생성하고 API 데이터를 저장할 state를 하나 선언합니다. articles 상태에는 API 본문을 저장할 예정이므로 IRespData 형태로 선언합니다.

const ListView = () => {
    const [articles, setArticles] = useState<IRespData | null>(null);
}

export default ListView;

 

목록에 필요한 데이터는 로컬 서버에 Query 해야 하므로 fetch API를 사용해서 서버 API를 Query 하는 apiGet 함수를 하나 정의합니다.

const apiGet = async(type: string, param: string) => {
    const apiUrl: string = '/search/' + type + '/' + param;
    await fetch(apiUrl, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    })
    .then((resp: Response) => resp.json())
    .then((resp: IHttpResp) => {
        if (resp.code === '00') {
            setArticles(resp.data as IRespData);
            console.log(resp.data);
        } else {
            //handle error
        }
    });
};

 

Naver API는 서버 API에서 호출하므로 UI에서는 /search/{type}/{param} 형식으로 서버 API를 호출합니다.  도서 검색을 React 라는 파라미터로 검색을 하려면 /search/book/React 로 검색할 수 있습니다. apiGet 함수는 useEffect에서 호출하여 화면이 Loading 될 때 조회하도록 합니다.

useEffect(() => {
    apiGet('book', 'React');
}, []);

 

apiGet 함수를 호출할 때 React 관련 도서를 검색할 수 있도록 위와 같이 useEffect Hook을 작성합니다. 이번 포스트에서는 console.log로 resp.data가 올바르게 조회되는지 까지만 확인해 보겠습니다. 그러므로 UI는 별도로 작성하지 않고 <></> 만 return 하도록 합니다. 여기까지 작성한 listview.component.tsx 프로그램의 전체 소스코드는 아래와 같습니다.

import { useEffect, useState } from "react";
import { IHttpResp, IRespData } from "../interface/apidata.interface";

const ListView = () => {
    const [articles, setArticles] = useState<IRespData | null>(null);

    const apiGet = async(type: string, param: string) => {
        const apiUrl: string = '/search/' + type + '/' + param;
        await fetch(apiUrl, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then((resp: Response) => resp.json())
        .then((resp: IHttpResp) => {
            if (resp.code === '00') {
                setArticles(resp.data as IRespData);
                console.log(resp.data);
            } else {
                throw new Error('error');
            }
        });
    };

    useEffect(() => {
        apiGet('book', 'React');
    }, []);

    return (
        <></>
    );
};

export default ListView;

 

다음은 /src/app.tsx 프로그램을 아래와 같이 하나 작성하여 ListView 컴포넌트를 추가합니다.

import ListView from "./component/listview.component";

const App = () => {
    return (
        <ListView />
    )
};

export default App;

 

/src/main.tsx 소스코드에서는 <App /> 컴포넌트를 렌더링 하도록 아래와 같이 변경합니다.

import ReactDOM from 'react-dom';
import App from './app';

ReactDOM.render(<App />, document.getElementById('app'));

 

이제 서버와 인터페이스하여 수신한 데이터를 Logging 하는 부분까지는 준비를 마쳤습니다. 이제 타입스크립트를 컴파일하고 생성한 js 파일을 번들링하여 build.js를 생성합니다.

D:\workspace\expressServer\uiModule> tsc
D:\workspace\expressServer\uiModule> npm run build

 

/public/build.js 가 재생성 되었음을 확인하고 express 서버를 구동합니다.

D:\workspace\expressServer> yarn start

 

이제 브라우저로 http://localhost:8001 에 접속하면 아래와 같은 콘솔 로그를 확인할 수 있습니다.

인터페이스 결과 로그

 

아직 UI는 하나도 만들지 않았지만 이번 시리즈의 목적은 달성했습니다. 이번 시리즈의 목적은 아래 그림과 같았습니다.

서버 to 서버 인터페이스

 

NAVER API를 브라우저에서 직접 호출하지 않고 로컬에 express 서버를 하나 띄운 다음, express 서버에서 Naver API를 호출하여 중계하도록 Front-end, Back-end 프로그램을 작성해 보았습니다.

 

이후 UI를 만들어 보는 과정은 [React 기초 (List - TypeScript)] 시리즈의 "06 - ListView UI 구성" 포스트와 거의 동일한 내용이 될 것 같아서 작성하지 않겠습니다. 계속 진행해 보실 분들은 아래 링크를 참고하시면 됩니다.

React 기초 (목록 - TypeScript) 06 - ListView UI 구성 :: 즐거운인생 (tistory.com)

 

React 기초 (목록 - TypeScript) 06 - ListView UI 구성

본 포스트에서는 리액트와 타입스크립트를 이용하여 네이버 API로 데이터를 검색해서 목록 화면을 구성해 보겠습니다. 저번 포스트에서는 Naver API를 호출하여 응답 데이터를 확인해 보고, 응답

redballs.tistory.com

 

300x250

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

 

React + Express + TypeScript 프로젝트 구성하기

 

이전 포스트에서는 expressServer 프로젝트 아래 uiModule 이라는 경로를 생성하고 해당 경로를 React 프로젝트로 구성한 후 소스코드를 컴파일 및 번들링해서 Node.js 서버에서 실행해보는 부분까지 진행해 보았습니다. 이번 포스트에서는 이전 포스트들에서 만든 서버 API에서 응답하는 데이터를 확인해 보고, Front-end에서 사용할 데이터 타입을 선언해 보겠습니다.

 

먼저 서버 API의 데이터 구조를 정의한 포스트는 아래 주소를 참고합니다.

React + Express + Typescript - 02. 데이터 타입 선언 :: 즐거운인생 (tistory.com)

 

React + Express + Typescript - 02. 데이터 타입 선언

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API

redballs.tistory.com

 

먼저 로컬 서버를 구동하고 http://localhost:8001/search/news/React 로 접근해서 데이터를 확인해 보겠습니다.

 

HTTP 응답

HTTP 응답은 아래와 같은 형태로 응답코드, 응답메시지, 응답데이터가 return 됩니다.

HTTP 응답

 

DATA 영역

HTTP 응답 중 데이터 영역은 아래와 같이 출력 건수(display), 시작건수(start), 전체건수(total), 검색유형(type), 검색 결과 데이터(items) 가 return 됩니다.

데이터부 응답

 

검색 결과 데이터 영역

검색 결과 데이터 영역은 두 가지 형태로 return 됩니다. type이 news일 경우에는 뉴스 데이터의 배열 형태로 return 되고, type이 book일 경우에는 도서 데이터의 배열 형태로 return 됩니다.

 

[type이 new일 경우]

뉴스 유형의 검색 결과

[type이 book일 경우]

도서 유형의 검색 결과

 

데이터 타입 선언

위 데이터를 분석해서 데이터 타입을 정의하면 되는데, 기본적으로는 서버 애플리케이션에서 정의한 데이터와 동일하게 정의하면 됩니다. 서버 애플리케이션의 정의를 참조하여 아래 경로에 프로그램을 작성합니다.

- ./uiModule/src/interface/apidata.interface.ts

 

먼저 HTTP 응답은 아래와 같이 작성합니다.

interface IHttpResp {
    code: string;
    message: string;
    data: IRespData | null
}

 

서버 요청에 대한 응답은 기본적으로 응답코드와 메시지, 조회한 데이터를 응답하도록 하고 조회한 데이터는 IRespData 형태로 아래와 같이 정의합니다. 오류일 경우 데이터가 없을 수도 있으니 null도 허용해줍니다.

interface IRespData {
    lastBuildDate: string;
    total: number;
    start: number;
    display: number;
    type: string;
    items: INewsData[] | IBookData[];
}

 

Naver API에서 주는 응답의 형태에 현재 데이터의 유형을 구분할 수 있는 type 속성을 추가합니다. 실제 조회한 데이터는 뉴스 데이터일 경우 INewsData의 배열 형태, 도서 데이터일 경우 IBookData의 배열 형태로 구성합니다. INewsData와 IBookData의 정의는 아래와 같습니다.

interface INewsData {
    title: string;
    originallink: string;
    link: string;
    description: string;
    pubDate: string;
}

interface IBookData {
    title: string;
    link: string;
    image: string;
    author: string;
    price: string;
    discount: string;
    publisher: string;
    pubdate: string;
    isbn: string;
    description: string;
}

 

다른 모듈에서 사용할 수 있도록 export를 추가합니다.

export {
    IHttpResp,
    IRespData,
    INewsData,
    IBookData
}

 

JSON 형태로 보면 아래와 같은 형태입니다.

{
    "code": "",
    "message": "",
    "data": {
        "start": 0,
        "total": 0,
        "display": 0,
        "lastBuildDate": "",
        "type": "",
        "items": [{
            "title": "",
            "description": "",
            "link": "",
            "originallink": "",
            "pubDate": ""
        }]
    }
}

 

데이터 타입 선언 부분은 서버와 클라이언트가 동일한 형태로 데이터를 참조해야 하므로 서버 개발자와 클라이언트 개발자가 별개로 있다면 협의해서 인터페이스 하는데 문제 없이 맞추어 가야합니다.

 

다음 포스트에서는 서버에서 제공한 API와 인터페이스하여 선언한 데이터 타입으로 바인드해서 확인해 보겠습니다.

300x250

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

 

React + Express + TypeScript 프로젝트 구성하기

 

저번 포스트까지 Node.js 서버를 express 기반으로 구성한 후 간단하게나마 서버 프로그램을 작성해서 Naver API를 호출하는 API를 작성하고 테스트 해보았습니다. 이번 포스트에서는 해당 API를 사용하여 UI를 구성할 React 프로젝트의 환경을 구성해 보겠습니다.

 

서버와 클라이언트 프로젝트는 별도의 Repository로 구성해도 되고, 하나의 통합 Repository로 구성해도 됩니다. 여기서는 별도의 프로젝트로 구성하지 않고 express 프로젝트 안에 uiModule이라는 경로를 생성하여 React 프로젝트를 구성해 보도록 하겠습니다.

 

먼저 expressServer 프로젝트의 루트 경로에 uiModule이라는 경로를 생성합니다.

D:\workspace\expressServer> mkdir uiModule
D:\workspace\expressServer> cd uiModule
D:\workspace\expressServer\uiModule>

 

yarn init 명령으로 package.json 파일을 생성합니다.

D:\workspace\expressServer\uiModule> yarn init -y

 

다음은 React 프로젝트에서 사용할 모듈을 설치합니다.  프로젝트에 사용할 모듈에 대한 설명은 아래 포스트를 참고합니다.

React 기초 (목록 - TypeScript) 02 - 프로젝트 생성 :: 즐거운인생 (tistory.com)

 

React 기초 (목록 - TypeScript) 02 - 프로젝트 생성

본 포스트에서는 리액트와 타입스크립트를 이용하여 네이버 API로 데이터를 검색해서 목록 화면을 구성해 보겠습니다. 이전 포스트에서 개발할 내용을 확인해 보았으니, 이제 개발에 필요한 환

redballs.tistory.com

 

설치할 모듈은 아래와 같습니다.

D:\workspace\expressServer\uiModule> yarn add react@17.0.2
D:\workspace\expressServer\uiModule> yarn add react-dom@17.0.2
D:\workspace\expressServer\uiModule> yarn add --dev babel-core@6.26.3
D:\workspace\expressServer\uiModule> yarn add --dev babel-loader@8.2.3
D:\workspace\expressServer\uiModule> yarn add --dev babel-preset-react-app@10.0.1
D:\workspace\expressServer\uiModule> yarn add --dev webpack@5.66.0
D:\workspace\expressServer\uiModule> yarn add --dev webpack-cli@4.10.0
D:\workspace\expressServer\uiModule> yarn add --dev typescript
D:\workspace\expressServer\uiModule> yarn add --dev @types/react @types/react-dom
D:\workspace\expressServer\uiModule> yarn add moment@2.29.1

 

위 포스트에서 사용했던 webpack-dev-server는 이미 express로 구성한 서버가 있으므로 설치하지 않습니다.

 

/uiModule/src 경로를 생성하고, 아래와 같이 main.tsx 파일을 작성합니다

import ReactDOM from 'react-dom';

ReactDOM.render(<div>Hello World</div>, document.getElementById('app'));

 

타입스크립트를 사용하도록 tsx 파일로 생성했으므로 uiProject 하위에 tsconfig.json 파일을 아래와 같이 생성합니다.

{ 
    "compilerOptions": {
        "jsx": "react-jsx",
        "target": "es6",
        "module": "commonjs",
        "outDir": "./dist",
        "rootDir": "./src",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
    }
}

 

rootDir 이 ./src 이므로 uiModule/src 하위 파일들에 대해 컴파일을 수행하고 outDir 이 ./dist 이므로 uiModule/dist 하위에 컴파일 결과 파일을 생성합니다.

 

 

uiModule 의 package.json 파일에 build 스크립트를 아래와 같이 추가합니다.

{
  "name": "uiModule",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "moment": "2.29.1",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "^18.0.15",
    "@types/react-dom": "^18.0.6",
    "babel-core": "6.26.3",
    "babel-loader": "8.2.3",
    "babel-preset-react-app": "10.0.1",
    "typescript": "^4.7.4",
    "webpack": "5.66.0",
    "webpack-cli": "4.10.0",
    "webpack-dev-server": "4.7.3"
  },
  "scripts": {
    "build": "webpack"
  }
}

 

여기까지 작업을 하면 uiModule 하위의 프로젝트 구조는 아래와 같습니다.

uiModule 프로젝트 구조

 

이제 tsc 명령으로 컴파일을 하면 아래 그림과 같이 dist 폴더가 생성되고 그 하위에 컴파일 결과가 생성됩니다.

D:\workspace\expressServer\uiModule> tsc

컴파일 결과 생성 확인

 

여기까지 잘 되었다면 이제 Node.js 서버에서 uiModule을 사용하기 위해 expressServer 프로젝트의 /public/js 하위로 컴파일 결과 파일들을 번들링하기 위해 아래와 같이 uiModule/webpack.config.js 파일을 생성합니다.

'use strict'
const path = require('path');

module.exports = {
    entry: {
        main: ['./dist/main.js']
    },
    output: {
        path: path.resolve(__dirname, '../public/js'),
        filename: 'build.js'
    },
    module: {
        rules: [{
            test: /\.jsx?$/,
            use: {
                loader: 'babel-loader'
            }
        }]
    }
};

 

애플리케이션의 시작점은 ./dist/main.js 로 컴파일 되므로 entry는 main.js 로 설정합니다. 번들링한 결과는 uiProject 외부에 있는 프로젝트 루트의 ./public/js로 전송해야 하므로 output은 위와 같이 설정하고 번들링한 결과는 build.js로 생성합니다.

D:\workspace\expressServer\uiProject> npm run build

 

npm run build 명령으로 번들링하면 아래 그림과 같이 결과가 생성됩니다.

번들링 결과 확인

 

번들링한 결과를 사용할 수 있도록 아래와 같이 index.html 파일을 수정합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Express Sample</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    </head>
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="js/build.js"></script>
    </body>
</html>

 

이제 프로젝트 루트로 이동해서 yarn start 명령으로 서버를 실행시키고 화면에 Hello World가 표시되는지 확인합니다.

D:\workspace\expressServer> yarn start

 

 

실행 결과 확인

300x250

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

 

React + Express + TypeScript 프로젝트 구성하기

 

이전 포스트에서는 서버와 Naver API 서버 간, 클라이언트와 서버 간 인터페이스에 사용할 데이터 타입을 선언해 보았습니다. 이번 포스트에서는 Controller와 Service를 만들어서 실제로 인터페이스를 수행해 보겠습니다.

 

먼저 서버에서 Naver API와 통신을 위해서 request 모듈을 설치하겠습니다. 이전 포스트에서 React로 개발할 때는 Fetch API를 사용했지만 Node.js에는 Fetch API가 구현되어 있지 않아, node-fetch 모듈을 설치하면 유사하게 사용할 수 있지만 좀 더 많이 사용하는 request 모듈을 설치해서 사용해 보겠습니다.

D:\workspace\expressServer> yarn add request

 

request 모듈의 기본적인 사용법은 아래와 같습니다. 우리가 사용할 Naver API는 Get 방식으로 호출할 것이므로 request.get 메소드로 알아 보겠습니다.

const request = require('request');

request.get({
    headers: {},
    url: '',
    qs: {},
    json: true
}, function(error, response, body) {
});

 

request.get에 전달하는 파라미터 중 headers에는 HTTP Header 정보를 설정합니다. Content-Type과 Naver의 인증을 위한 인증 정보를 전달합니다. 아래 코드를 참고하여 각자가 발급 받은 인증 키를 입력합니다.

headers: {
    'Content-Type': 'application/json',
    'X-Naver-Client-Id': CLIENT_ID,
    'X-Naver-Client-Secret': CLIENT_SECRET
}

 

url은 파라미터를 제외한 부분을 입력합니다. 일단 뉴스 API로 간주하고 작성합니다.

uri: 'https://openapi.naver.com/v1/search/news

 

qs에는 해당 API를 Get 방식으로 호출할 때 전달할 QueryString 파라미터를 세팅합니다. 일단 검색에 정도만 세팅합니다.

qs: {
    query: "코로나"
}

 

우리는 API 요청에 대한 응답을 json으로 parsing하여 전달 받으면 되므로 json: true 옵션도 추가합니다.

 

Callback은 3개의 파라미터를 전달 받습니다. error, response, body를 전달 받는데 일단 우리는 오류 처리에 대한 부분은 body가 있는지 없는지를 보고 판단하겠습니다. body가 있을 경우에는 body에서 데이터를 추출하여 응답할 것이고, 없으면 오류 코드를 세팅하여 응답하도록 합니다.

const httpResp: HttpResp = new HttpResp();
const respData: RespData = new RespData(type);

if (body) {
    respData.setStart(body.start);
    respData.setDisplay(body.display);
    respData.setTotal(body.total);
    respData.setItems(body.items);
        
    httpResp.setCode('00');
    httpResp.setMessage('Success');
    httpResp.setData(respData);
} else {
    httpResp.setCode('99');
    httpResp.setMessage('Failed');
    httpResp.setData(null);
}

 

해당 조회하는 메소드는 비동기 처리를 위해 async 처리하여 Promise를 응답하도록 구성합니다. Service 프로그램은 ./src/naverapi/naverapi.service.ts 로 생성하고 아래와 같이 작성합니다.

import { HttpResp, RespData } from "../entity/httpresp.entity";
import { INaverApiResp } from "../interface/apidata.interface";

const NaverApiService = () => {
    const request = require('request');

    const search = async (type: string, param: string): Promise<HttpResp> => {

        return new Promise<HttpResp>((resolve, reject) => {
            const CLIENT_ID: string = '';
            const CLIENT_SECRET: string = '';
    
            const apiUrl: string = 'https://openapi.naver.com/v1/search/' + type;
            
            request.get({
                headers: {
                    'Content-Type': 'application/json',
                    'X-Naver-Client-Id': CLIENT_ID,
                    'X-Naver-Client-Secret': CLIENT_SECRET
                },
                uri: apiUrl,
                qs: {
                    query: param
                },
                json: true
            }, (error: object, response: object, body: INaverApiResp) => {
                const httpResp: HttpResp = new HttpResp();
                const respData: RespData = new RespData(type);

                if (body) {
                    respData.setStart(body.start);
                    respData.setDisplay(body.display);
                    respData.setTotal(body.total);
                    respData.setItems(body.items);
        
                    httpResp.setCode('00');
                    httpResp.setMessage('Success');
                    httpResp.setData(respData);
                } else {
                    httpResp.setCode('99');
                    httpResp.setMessage('Failed');
                    httpResp.setData(null);
                }

                resolve(httpResp);
            });
        });
    }

    return {
        search
    }
};

export default NaverApiService;

 

위에서 설명한 내용들로 구성되어 있습니다. apiUrl을 구성할 때는 뉴스와 도서를 하나의 메소드로 사용하기 위해 /search/ 하위에 타입을 추가하는 구조로 작성합니다. 다음은 Controller를 작성해 보겠습니다.

 

 

Controller 프로그램은 ./src/naverapi/naverapi.controller.ts 로 생성하고 아래와 같이 작성합니다.

import express, { Request, Response } from "express";
import { HttpResp } from "../entity/httpresp.entity";
import NaverApiService from "./naverapi.service";

const service = NaverApiService();
const NaverApiController = express.Router();

NaverApiController.get('/:type/:keyword', async (req: Request, res: Response) => {
    const httpResp: HttpResp = await service.search(req.params.type, req.params.keyword);
    res.send(httpResp);
});

export default NaverApiController;

 

express.Router()로 Router를 선언한 후 get 리스너를 추가합니다. URL은 아래와 같이 구성합니다.

http://localhost:8001/search/news/코로나

라는 URL로 접근할 경우 해당 요청에서 "news"와 "코로나"를 사용해서 Naver API에는 아래와 같이 요청하게 됩니다.

https://openapi.naver.com/v1/search/news?query=코로나

 

도서 API를 사용할 경우에도 위와 같은 규칙으로 동일하게 변환합니다.

http://localhost:8001/search/book/코로나

라는 URL로 접근할 경우 해당 요청에서 "book"과 "코로나"를 사용해서 Naver API에는 아래와 같이 요청합니다.

https://openapi.naver.com/v1/search/book?query=코로나

 

그리고 아까 생성한 Service class의 search 메소드를 호출한 결과를 응답합니다. search 메소드는 응답을 Promise<HttpResp> 타입으로 응답하므로 await 키워드를 사용하여 HttpResp 형태로 응답 받습니다.

 

이제 app.ts 프로그램에 app.use 를 사용해서 해당 Router를 앱에 추가합니다. 해당 Router는 /search 경로 하위에 매핑하겠습니다.

app.use('/search', NaverApiController);

 

해당 라인을 추가한 app.ts 의 전체 소스코드는 아래와 같습니다.

import express, { Request, Response } from "express";
import path from "path";
import NaverApiController from "./naverapi/naverapi.controller";

const app = express();

app.use(express.static(path.join(__dirname, '../public')));
app.get('/', (req: Request, res: Response) => {
    res.sendFile(path.join(__dirname, '../public/index.html'));
});
app.use('/search', NaverApiController);

app.listen('8001', () => {
    console.log('Server started');
});

  

이제 컴파일한 후 애플리케이션을 재시작 합니다.

D:\workspace\expressServer> tsc
D:\workspace\expressServer> yarn start

 

시작한 후 설정한 경로로 검색해서 결과를 한 번 확인해 보겠습니다.

먼저 news API를 "코로나"라는 키워드로 검색해서 결과를 확인해 보겠습니다.

 

[http://localhost:8001/search/new/코로나]

뉴스 API 확인

 

그 다음은 book API를 "코로나"라는 키워드로 검색해서 결과를 확인해 보겠습니다.

 

[http://localhost:8001/search/book/코로나]

도서 API 확인

 

클라이언트 프로그램에서 직접 Naver API를 호출할 때와 달리  CORS 오류가 발생하지 않고 잘 조회됨을 확인할 수 있습니다.

300x250

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

 

React + Express + TypeScript 프로젝트 구성하기

 

이전 포스트에서는 TypeScript 컴파일 환경 및 프로젝트 실행 환경을 구성하고 컴파일한 ./dist/app.js 프로그램으로 Node.js 서버를 구동하는 부분까지 작업해 보았습니다. 이번 포스트에서는 Controller와 Serivce를 생성해서 브라우저에서 받은 요청을 Naver API로 전달하여 응답을 받은 후, 사용자의 브라우저로 전달하는 부분을 작성해 보겠습니다.

 

데이터 타입 선언

먼저 각 데이터의 타입을 선언해 보겠습니다. 데이터의 타입은 interface로 선언하며 ./src/interface/ 하위에 apidata.interface.ts 파일을 생성하여 작성합니다. 이전 포스트에서 사용했던 Naver API의 데이터 종류는 아래와 같습니다.

 

인터페이스 응답

Naver API의 전체적인 응답 Layout은 아래와 같습니다.

{
    lastBuildDate: '',
    total: 0,
    start: 0,
    display: 0,
    items: []
}

 

뉴스 API 데이터

뉴스 API 요청에 대한 응답 Layout은 아래와 같습니다.

{
    title: '',
    originallink: '',
    link: '',
    description: '',
    pubDate: ''
}

 

도서 API 데이터

도서 API 요청에 대한 응답 Layout은 아래와 같습니다.

{
    title: '',
    link: '',
    image: '',
    author: '',
    price: '',
    discount: '',
    publisher: '',
    pubdate: '',
    isbn: '',
    description: ''
}

 

위에서 확인한 데이터를 interface로 ./src/interface/apidata.interface.ts 프로그램에 아래와 같이 선언합니다.

interface INaverApiResp {
    lastBuildDate: string;
    total: number;
    start: number;
    display: number;
    type: string;
    items: INewsData[] | IBookData[];
}

interface INewsData {
    title: string;
    originallink: string;
    link: string;
    description: string;
    pubDate: string;
}

interface IBookData {
    title: string;
    link: string;
    image: string;
    author: string;
    price: string;
    discount: string;
    publisher: string;
    pubdate: string;
    isbn: string;
    description: string;
}

export {
    INaverApiResp,
    INewsData,
    IBookData
}

 

해당 Layout은 Service class에서 참조해야 하므로 export하여 다른 class에서 참조할 수 있도록 합니다. Naver API 데이터에 대한 부분은 아래 포스트에서 예제를 확인할 수 있습니다.

React 기초 (목록 만들기) 05 - ListView UI 구성 :: 즐거운인생 (tistory.com)

 

React 기초 (목록 만들기) 05 - ListView UI 구성

본 포스트에서는 리액트를 이용하여 네이버 API로 데이터를 검색해서 목록 화면을 구성해 보겠습니다. 저번 포스트에서 Naver News API를 호출해서 아래 형태로 결과를 받아보는 부분까지 진행해 보

redballs.tistory.com

 

Class 선언

추가로 두 가지 유형을 더 선언해 보겠습니다.  현재 작성하는 것은 서버 프로그램이므로 클라이언트의 HTTP 요청에 응답할 표준 Layout이 필요합니다. 간단하게 응답코드, 메시지, 데이터 본문으로만 구성해서 Class를 생성해 보겠습니다. 실제 사용 시에는 new 키워드로 인스턴스를 생성하여 사용하겠습니다.

 

interface와의 차이점은 interface는 Naver API에서 받아온 데이터의 응답에 대한 유형을 선언하고 타입 확인만 필요한 형태에 사용하지만 직접 데이터를 생성하는 부분은 class를 선언하고 인스턴스를 생성해서 사용합니다.

 

./src/entity/httpresp.entity.ts 파일을 생성하고 먼저 HTTP 요청에 대한 응답 Layout으로 사용할 HttpResp class를 아래와 같이 생성합니다.

class HttpResp {
    private code: string;
    private message: string;
    private data: RespData | null = null;

    constructor (code: string = '00', message: string = 'Success') {
        this.code = code;
        this.message = message;
    }

    public setCode = (code: string): void => {
        this.code = code;
    }

    public setMessage = (message: string): void => {
        this.message = message;
    }

    public setData = (data: RespData | null): void => {
        this.data = data;
    }
}

 

속성은 3개를 정의했습니다. 응답코드(code), 응답메시지(message), 응답데이터(data) 크게 3가지 정보를 사용하여 응답합니다. constructor는 new 키워드로 인스턴스를 생성할 때 사용하는 생성자입니다. code와 message를 파라미터로 받으며  입력하지 않을 경우 '00', 'Success'로 각각 세팅합니다.

 

응답데이터인 data는 RespData라는 타입으로 선언합니다. RespData라는 타입은 아직 생성하지 않았으니 아직은 오류가 발생합니다. 그리고 응답데이터는 초기에는 값이 없으므로 null도 허용해 주고, 초기값은 null로 세팅합니다. 아래와 같이 | (pipeline)으로 연결하면 여러 유형을 허용할 수 있습니다.

const data: RespData | null = null;

 

그리고 class에서 사용하는 속성들에 대해서는 setter만 선언 했습니다. 나중에 getter가 필요하게 되면 추가적으로 선언해도 되고, 서버에서 데이터를 수신 받아 응답만 할 목적이므로 아직까지는 getter는 필요가 없어 보입니다.

 

그럼 다음으로 응답데이터에 사용하는 RespData class를 아래와 같이 작성합니다. 별도의 파일로 생성하지 않고 동일한 파일에 작성합니다.

class RespData {
    private total: number = 0;
    private start: number = 0;
    private display: number = 0;
    private type: string = '';
    private items: INewsData[] | IBookData[] | null = null;

    constructor (type: string) {
        this.type = type;
    }

    public setTotal = (total: number): void => {
        this.total = total;
    }

    public setStart = (start: number): void => {
        this.start = start;
    }

    public setDisplay = (display: number): void => {
        this.display = display;
    }

    public setType = (type: string): void => {
        this.type = type;
    }

    public setItems = (items: INewsData[] | IBookData[]): void => {
        this.items = items;
    }
}

 

Naver API에서 넘겨주는 total (전체건수), start (시작 인덱스), display (표시 건수)는 숫자 형태로, 초기값을 0으로 선언합니다. 그리고 items는 Naver API에서 넘겨주는 뉴스나 도서 목록 데이터입니다. INewsData, IBookData의 배열이나 초기값을 위해 null 타입을 허용합니다.

 

그리고 type이라는 속성을 string 타입으로 생성합니다. 현재 조회한 목록이 뉴스 데이터인지, 목록 데이터인지를 구분하기 위한 값입니다. RespData class 역시 HttpResp와 동일한 사유로 getter는 작성하지 않았습니다. 다음 포스트 등에서 필요하게 되면 추가하겠습니다.

 

이제 필요한 데이터 타입은 모두 작성해 보았습니다. 다음 포스트에서는 실제 사용자의 요청을 받는 역할을 하는 Controller와 Naver API와 인터페이스를 수행하고 데이터를 만드는 Service를 작성하여 인터페이스를 진행해 보겠습니다.

 

300x250

본 포스트에서는 Front-end는 리액트, Back-end는 Express 기반의 Node.js를 사용하여 하나의 프로젝트로 간단한 Application을 구성해 보겠습니다. 구성할 Application은 이전 포스트에서 진행했던 네이버 API 조회 Application을 재사용 하겠습니다.

 

React + Express + Typescript 프로젝트 구성하기

 

이전 포스트에서 진행했던 Naver API 조회 프로젝트는 연습은 할 수 있는 아키텍처이나 실제로는 사용할 수 없는 아키텍처 입니다. 브라우저에 있는 CORS 정책을 사용자가 해제해주지 않으면 실행이 되지 않는 구조이기 때문입니다. 하이브리드 앱으로 애플리케이션을 구성한다면 사용이 가능하지만 웹 페이지로는 사용이 불가능합니다.

 

그래서 Naver API를 조회하는 부분은 서버로 로직을 옮겨 서버 to 서버 인터페이스로 변경하고 화면에서는 동일한 Domain(IP)에 있는 서버 인터페이스를 사용하여  CORS 정책을 해제하지 않고도 사용할 수 있는 아키텍처로 변경하겠습니다.

 

서버 to 서버 인터페이스

 

위 그림과 같은 구성은 다른 서버와의 인터페이스 주체가 서버이므로, 서버 간 통신에는 브라우저의 CORS 정책이 영향을 주지 못합니다. 이렇게 로컬 서버에서 Naver API 서버와 통신하여 데이터를 받아온 후 동일한 Domain(IP)에 있는 화면에서 해당 정보를 사용해서 검색 기능을 구현해 보겠습니다.

 

먼저 아래 포스트를 참고하여 Express 기반의 Node.js 개발 환경을 구성합니다.

https://redballs.tistory.com/entry/Nodejs-Express-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95?category=569060 

 

Node.js Express 환경 설정

본 포스트는 Express 기반의 Node.js 애플리케이션 서버를 구성하고 static 경로를 설정하는 방법을 설명합니다. 서론 Node.js 서버 애플리케이션을 개발할 때 주로 사용하는 Framework는 Express와 Nest 정도

redballs.tistory.com

 

포스트를 따라서 구성하고 프로젝트를 구동해보면 "Hello World"를 확인할 수 있습니다. 하지만 우리는 TypeScript를 사용하기로 했으니 필요한 모듈을 설치하고 프로젝트 구조를 살짝 변경해 보겠습니다.

 

 

TypeScript 설치

개발 의존성으로 node와 express 라이브러리의 타입을 설치합니다.

D:\workspace\expressServer> yarn add --dev @types/node
D:\workspace\expressServer> yarn add --dev @types/express

 

app.ts 로 변경

./src/app.js 프로그램을 ./src/app.ts 로 변경하고 아래와 같이 작성합니다. 기본적인 내용은 변경이 없고 필요한 부분에 타입만 추가합니다.

import express, { Request, Response } from "express";
import path from "path";

const app = express();

app.use(express.static(path.join(__dirname, '../public')));
app.get('/', (req: Request, res: Response) => {
    res.sendFile(path.join(__dirname, '../public/index.html'));
});

app.listen('8001', () => {
    console.log('Server started');
});

 

타입 스크립트 컴파일 옵션 설정

프로젝트 루트에 tsconfig.json 파일을 아래와 같이 작성합니다.

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "outDir": "./dist",
        "rootDir": "./src",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
    }
}

 

사용하는 컴파일 옵션에 대한 설명은 제 블로그의 아래 글을 참고해주세요.

https://redballs.tistory.com/entry/React-%EA%B8%B0%EC%B4%88-%EB%AA%A9%EB%A1%9D-TypeScript-03-Hello-World?category=566801 

 

React 기초 (목록 - TypeScript) 03 - 컴파일

본 포스트에서는 리액트와 타입스크립트를 이용하여 네이버 API로 데이터를 검색해서 목록 화면을 구성해 보겠습니다. 저번 포스트에서는 프로젝트 경로를 생성하고 개발에 필요한 모듈들을 설

redballs.tistory.com

 

컴파일 옵션까지 작성했으면 tsc 명령으로 컴파일을 진행합니다. 컴파일한 결과 파일은 ./dist 하위에 생성됩니다.

D:\workspace\expressServer> tsc

 

실행 확인

현재는 start 스크립트를 ./src/app.js로 설정해 두었는데 이제는 컴파일한 ./dist/app.js 파일을 사용해야 하므로 package.json 파일의 start 스크립트를 아래와 같이 변경합니다.

"scripts": {
  "start": "node ./dist/app.js"
}

 

변경 후 yarn start 명령어로 로컬 서버를 기동하여 브라우저에서 "Hello World"가 잘 출력되는지 확인합니다. 현재까지 진행한 프로젝트 폴더 및 파일 구조는 아래와 같습니다.

프로젝트 구조

 

 

300x250

본 포스트는 Express 기반의 Node.js 애플리케이션 서버를 구성하고 static 경로를 설정하는 방법을 설명합니다.

 

 

 

서론

Node.js 서버 애플리케이션을 개발할 때 주로 사용하는 Framework는 Express와 Nest 정도가 있습니다. 장단점은 생각보다 명확합니다. Express는 빠르고 자유롭습니다. Express는 구조에 대한 자유도가 높기 때문에 특별히 Framework에서 제한하고 있는 구조가 없습니다. 이런 부분으로 애플리케이션을 빠르게 개발하고 프로토타이핑 해 볼 수 있는 장점이 있는 반면, 이 부분은 약점이 되기도 합니다. Express 같은 경우에는 개발자마다 개발하는 스타일이 충분히 다를 수 있어 프로젝트마다 완전히 다른 언어로 개발된 것처럼 보일 수도 있습니다.

 

Nest는 이런 점에서 완전히 반대편에 서 있습니다. Nest 역시 Express를 기반으로 만들어졌지만 Spring Framework가 떠오를 만큼 명확한 구조가 있습니다. Spring의 annotation과 유사하게 decorator를 제공하여 대규모의 애플리케이션을 일관성 있는 구조로 작성하고 운영할 수 있습니다.

 

하지만 Nest를 사용하다 보면 JavaScript의 장점인 자유롭고 가벼운 특성을 느끼지 못할 정도로 빡빡합니다. 개인적인 사견이기는 하지만 이럴 거면 굳이....왜? 라는 생각이 들기도 합니다. 대한민국에서 서버는 Spring 이라는 대중적인 Framework가 있으니깐 말입니다.

 

Express 기반 환경 설정

이번 포스트에서는 Express를 기반으로 서버를 간단하게 구성할 수 있는 환경설정을 진행해 보겠습니다. 기회가 되면 Nest에 대한 부분도 다음에 포스팅 해보겠습니다.

 

먼저 프로젝트 폴더를 하나 생성합니다.

D:\workspace> mkdir expressServer
D:\workspace> cd expressServer
D:\workspace\expressServer>

 

프로젝트를 초기화합니다.

D:\workspace\expressServer> yarn init -y

 

필요한 모듈을 설치합니다. 

D:\workspace\expressServer> yarn add express

 

VSCode에서 프로젝트를 엽니다.

 

VSCode에서 반입한 프로젝트의 현재 구조는 아래와 같습니다.

 

프로젝트에 ./src 경로와 ./public 경로를 생성합니다. src는 JavaScript 애플리케이션 소스를 작성하고 public 폴더에는 html, css, image 등과 같은 정적 resources를 관리합니다.

 

먼저 public 경로 하위에 index.html 을 아래와 같이 작성합니다. 그냥 "Hello World"라는 텍스트만 표시합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Express Sample</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    </head>
    <body>
        <div id="app">Hello World</div>
    </body>
</html>

 

 

다음은 src 경로 하위에 app.js 파일을 아래와 같이 작성합니다.

const express = require('express');

const app = express();
app.listen('8001', () => {
    console.log('Server started');
});

 

기존 Java 애플리케이션을 생각하면 정말 믿기 힘들 정도로 간단한 내용입니다. 이제 package.json 파일에 start 스크립트를 추가합니다.

{
  "name": "expressServer",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "express": "^4.18.1"
  },
  "scripts": {
    "start": "node ./src/app.js"
  }
}

 

여기까지 작업하고 웹 서버를 구동해 봅니다.

D:\workspace\expressServer>yarn start
yarn run v1.22.17
$ node ./src/app.js
Server started

 

너무나 간단하게 구동이 되어버렸습니다. 웹 서버가 구동되었으니 브라우저로 접속해서 확인해 봅니다.

해당 포트로 Listen을 설정했을 뿐 라우팅을 하나도 추가하지 않았으므로 위와 같이 GET으로는 루트에 접근할 수 없다는 "Cannot GET /"이라는 오류 메시지가 표시됩니다.

 

이제 app.js에 정적 static 경로를 설정하고 루트 경로 라우팅을 추가합니다.

const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, '../public')));
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../public/index.html'));
});

app.listen('8001', () => {
    console.log('Server started');
});

 

express.static 메소드를 사용해 정적 경로를 선언할 수 있는데, 현재 app.js 파일의 경로가 ./src 하위이므로 한 경로 상위의 ../public 경로를 정적 경로의 루트로 선언합니다.

그 다음 루트 경로에 Get 방식 라우팅을 추가하고 루트 경로로 접근할 경우 ../public/index.html 파일을 응답합니다.

 

여기까지 작성하고 다시 웹 서버를 중간 후 구동합니다. Ctrl + C 로 구동을 중단할 수 있고, yarn start 명령으로 재시작 합니다. 시작 후 브라우저로 루트 경로로 접근하면 아래와 같이 "Hello World"를 확인할 수 있습니다.

 

간단한 정적인 화면을 표시할 수 있는 웹 애플리케이션을 Express를 사용해서 설정해 보았습니다.

300x250

'Node.js > express 환경구성' 카테고리의 다른 글

Node.js express MySQL 연동 환경 구성  (0) 2022.08.14

+ Recent posts