본문 바로가기
[IT] Node.JS

[Node.js] Express 설치, 프로젝트 생성 및 Rest API 서버 만들기 (+웹크롤링 데이터 전달)

by 오리엔탈킴 2022. 3. 2.

안녕하세요, Node.js의 강력한 웹 프레임워크인 Express.js를 설치하고 Express 프로젝트 생성 및 Rest API 서비스를 작성해보겠습니다.

전달할 데이터는 이전에 작성한 [웹 크롤링] Node.js Puppeteer - investing 원자재(금은/천연가스/원유) 가격 가져오기 포스트에서 작성한 것을 활용하여 웹 크롤링해서 가져온 원자재 가격 데이터를 전달하는(송신하는) API 서비스를 개발해보도록 하겠습니다.

Express 설치 및 프로젝트 생성

Node.js와 VSCode는 설치가 안되어 있다면 하기 포스트를 참고하여 설치를 한 후, Add Folder Open Folder를 통해 프로젝트 폴더를 오픈합니다. 그리고 하단 터미널 창에서 npm init을 통해 초기 프로젝트 세팅을 진행합니다. (참고: [Node.js 개발환경] Node.js 및 VS code 설치, Node.js 초기 프로젝트 생성 및 실행)

그런 다음 아래의 순서로 Express 설치 및 프로젝트 생성을 진행합니다.

  •  npm i express -save : 터미널 창에서 하기 npm install 명령을 통해 Express 모듈을 설치
  • npm install express-generator -g : Global 영역에 express프로젝트의 기본 골격을 빠르게 자동 생성해주는 도구인 express-gernerator를 설치
  • express (--view=ejs)생략 (설치위치)생략 : Express 프로젝트 기본 골격 자동 생성 (터미널 창에서 위치가 프로젝트 생성 위치여야 함) 

  

express 생성
express-generator 자동 생성

위와 같이 public, routes, views, bin, app.js자동 생성된 것을 확인할 수 있습니다.

- express --view=ejs|hbs|hjs|jade|pug|twig|vash와 같이 뷰 템플릿 엔진을 선택할 수 있고, default는 jade입니다. 다만 여기선 뷰는 작성 계획이 없어서 아무거나 설정해도 됩니다.

- VSCode 내장 터미널인 파워쉘에서 "express.ps1 파일을 로드할 수 없습니다." 에러가 발생할 경우, Windows에서 Powershell을 관리자 권한으로 실행 후 Set-ExecutionPolicy RemoteSigned > Y를 통해 권한을 설정하면 됩니다.

웹크롤링 서비스 생성

위와 같이 Express 프로젝트 기본 골격이 완성이 되었으면, 지난 포스팅에서 작성한 [웹 크롤링] Node.js Puppeteer - investing 원자재(금은/천연가스/원유) 가격 가져오기 Puppeteer를 활용하여 원자재 실시간 가격을 가져오는 서비스를 작성합니다.

아래와 같이 service 폴더를 생성하고 그 아래 crawlingSvc.js 파일을 생성합니다.

서비스 파일 생성
express 프로젝트 구조

아래 명령으로 puppeteer 모듈을 설치합니다. (나중에 패키지화를 위해 puppeteer-core가 아닌 puppeteer를 설치합니다)

npm i puppeteer

crawlingSvc.js 파일은 아래와 같이 매개변수를 입력받아 all일 경우 전체를 크롤링하고, 특정 원자재일 경우 그것만 크롤링하는 형태로 변경합니다.

const puppeteer = require('puppeteer');

// 각 원자재 이름과 URL 정보가 있는 MAP을 생성
const urlMap = new Map([
  ['silver','https://kr.investing.com/commodities/silver'],
  ['wti','https://kr.investing.com/commodities/crude-oil'],
  ['gas','https://kr.investing.com/commodities/natural-gas']
]);

let getCommodityPrice = async function(comdiName) { 
  // puppeteer 실행
  const browser = await puppeteer.launch({ 
    //headless : false
    });
  const page = await browser.newPage(); 

  // 매개변수가 all이면 전체 map을 수행, 아니면 해당 원자재만 수행
  var resultList = new Array();
  if(comdiName === 'all'){
    let urlKeys = urlMap.keys();
    for(var v of urlKeys){
        await getPrice(v);
    }
  }else {
    await getPrice(comdiName);
  }

  async function getPrice(v){
    // map에 저장된 url 가져와서 방문
    var url = urlMap.get(v);
    await page.goto(url);

    // 가격 보여지는 DIV가 페이지 나타나면, 가격 값을 가져 옴
    await page.waitForSelector('div[data-test="instrument-header-details"]'); 
    let comdiPrice = await page.$eval('div[data-test="instrument-header-details"] span[data-test="instrument-price-last"]', x=> x.innerHTML);
  
    console.log(v,':',comdiPrice,'$');
    // Json 형태로 결과를 생성
    resultList.push({
        name:v,
        price:comdiPrice
    });
  }

  await browser.close();

  return resultList;
}
 // 다른 js 파일에서 참조하기 위해 Export 설정
module.exports.getCommodityPrice = getCommodityPrice;

 

Express Rest API 추가

routes/index.js 파일에 getPrice라는 Get Method를 추가합니다. http://localhost:3000/getPrice라는 URL로 API 호출을 하였을 때, investing.com을 방문하여 웹 크롤링을 통해 현재 원자재 실시간 가격을 가져와서 Json 형태로 데이터를 전달해주는 API를 생성할 예정입니다.

name 파라미터를 추가하여, http://localhost:3000/getPrice?name=gas와 같이 호출하면 gas의 가격 정보만 전달하고, 파라미터를 추가하지 않으면 사전에 정의한 3개 원자재(은, WTI, 천연가스) 가격 모두 전달하는 API를 구현하도록 하겠습니다. (Exception 처리 등은 우선 제외하고 간단하게 구현하는 것을 목표로 하겠습니다)

자동생성된 routes/index.js 파일을 오픈하여 기존에 작성되어 있던 부분은 건드리지 않고 getPrice API 구현 부분을 추가하면 아래와 같습니다.

var express = require('express');
var router = express.Router();

// crawlingSvc.js 파일 import
var crawlingSvc = require('../service/crawlingSvc.js');

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

// getPrice API 구현 부분
router.get('/getPrice', async function(req, res) {
  var result;

  // name parameter가 null 이면 매개변수를 all로 호출, null이 아니면 입력 값 그대로 호출
  if(req.query.name){
    result = await crawlingSvc.getCommodityPrice(req.query.name);
  }else{
    result = await crawlingSvc.getCommodityPrice('all');
  }
  
  console.log(JSON.stringify(result));
  res.send(result);
});

module.exports = router;

 

Express 프로젝트 실행

터미널에서 프로젝트의 폴더로 이동한 후 npm start 명령을 통해 Express Node.js 서버 실행이 가능합니다.

VSCode 프로그램의 UI를 통해 좀 더 편리하게 실행 및 재시작 등을 하려면, VSCode 좌측 [Run and Debug] 메뉴로 이동하여, 상단 셀렉트 창에서 [Add Config(프로젝트명)]을 클릭하여, .vscode/launch.json 파일을 생성하여 아래와 같이 작성합니다.

프로젝트 실행

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceFolder}/bin/www"
            //,"console": "integratedTerminal" //상세한 에러 메시지 출력을 위해
        }
    ]
}

 

작성 후 Run and Debug 탭에서 상단 "Launch Program"을 통해 서버를 실행하고, 상단에 아이콘을 통해 정지 및 재시작을 할 수 있습니다.

서버가 실행되면 아래와 같이 API를 날려서 우리가 원하는 결과를 Json 형태로 받을 수 있습니다.

  • http://localhost:3000/getPrice (3000이 Express 기본 포트로 www 파일에서 수정 가능)

api 결과1
all 결과

  • http://localhost:3000/getPrice?name=gas

api 결과 2
gas 결과

 

위와 같이 진행을 하여 아주 간단한 Puppeteer 웹 크롤링을 통해 수집한 데이터를 전송하는 Node.js Express 프레임워크를 이용한 Rest API 서비스를 구현해 봤습니다. 간단한 샘플 예제를 통해 Express도 설치 및 세팅하고, 간단한 API Get 메서드까지를 구현하는 것을 정리할 겸 구현을 해 보았습니다.

 

반응형

댓글