코딩 기록

Node.js Express 로컬 서버 구축(4) Request 다른 서버 이미지 얻기

시리즈 목록

  1. Node.js Express 로컬 서버 구축(1): npm 도입
  2. Node.js Express 로컬 서버 구축(2): Express 라우팅
  3. Node.js Express 로컬 서버 구축(3): JSON 반환 stub API
  4. Node.js Express 로컬 서버 구축(4) Request 다른 서버 이미지 얻기

개요

로컬 서버를 구축하면서, 썸네일 등의 많은 이미지 파일을 모두 로컬에서 준비하는 것이 번거로웠습니다. 그래서 특정 경로에 대한 요청(리퀘스트)을 받았을 때, 배포 및 개발 전용 서비스 등 다른 Server에서 데이터를 가져오게 해봤습니다.

응답받은 JSON 데이터의 이미지 ID를 사용했는데요. 동적으로 URL을 만들면 이미지 얻을 때 편리할 것으로 생각합니다.


이 글의 순서

  • 목적
    • Node.js Express를 이용하여 PC에서 로컬 서버 띄움
  • 이 포스트 결과
    • 특정 경로에 대한 요청을 받아 다른 서버의 이미지를 반환
  • 대상자
    • WEB 프런트 담당자
    • HTML, CSS, JavaScript (es2015 포함)의 기본 문법을 이해하는 사람
    • HTTP 통신 GET, POST 등을 어느 정도 이해하는 사람 (대충 알아도 됨)
    • 검은 화면에 명령어 입력하는 것에 거부감 없는 분
  • 환경 버전
    • Windows10
    • Node.js (권장 판) 10.15.01
    • npm 6.4.1
    • Express 4.16.4
    • request 2.88.0



Request 설치

Node.js의 Request를 이용하여 구현합니다. HTTP 통신이 편리한 모듈은 이미 있습니다.


$ npm install request --save


request | npm


Node js Request로 이미지 파일을 검색하여 전송

이번에는 고양이 사진을 얻을 수 있는 서비스 placekitten에서 사진을 가져올 겁니다.

해당 이미지 경로는 /nyaaaaaaaan/{N1}/{N2} 입니다. N1은 가로, N2는 높이를 나타내는 수치로 지정했습니다.

Node js 코드는 이런 느낌입니다.


const express = require('express');
const app = express();
// request를 읽음
const request = require('request');

app.listen(8080, () => {
  console.log('Running at Port 8080...');
});

app.get('/nyaaaaaaaan/:width/:height', (req, res) => {
  // 송수신 설정
  const options = {
    url: 'http://placekitten.com/' + `${req.params.width}/${req.params.height}`,
    method: 'GET',
    encoding: null
  };

  request(options, (err, response, body) => {
    res.set('Content-Type', response.headers['content-type']);
    res.send(body);
  });
});


Express 라우팅 방법으로 대상 경로를 선택합니다.

루트 파라미터(매개변수)를 사용하여 URL의 경로 값(실제 위치 패스)을 얻을 수 있습니다. 취득한 값은 req.params 객체 안에서 매개 변수 이름, 키로 저장됩니다.


'/nyaaaaaaaan/:width/:height' ⇒ params: { width: 000, height: 000 }


request 함수의 첫 번째 인수로, 요청한 URL 문자열 또는 설정 정보가 정리되어 객체로 지정됩니다.

options.url 요청한 도메인과 취득한 경로를 이어붙여 요청 리퀘스트 URL을 지정(이미지 패스)합니다.

options.encoding 아무것도 지정하지 않으면 기본 문자열(utf-8)로 인코딩됩니다. Server에서 바이너리 데이터를 처리하고 싶다면, null을 지정해야 합니다.


request 함수의 두 번째 인수에 응답 값 취득 시의 콜백 함수를 전달합니다.

그리고 Node.js expressget 메소드에서 두 번째 인수로 받은 응답 객체를 이용합니다. 이 객체를 이용해 클라이언트에 이미지를 전송합니다.

이때 request 두 번째 인수와 이름이 충돌하지 않도록 주의하시기 바랍니다.


app.get('/thumbnail', (req, res) => { /* 중략 */ request(options, (err, response, body) => { res.set('Content-Type', response.headers['content-type']); res.send(body); }); });


콜백 함수는 3개의 인수를 받습니다.


  1. err : 에러 객체 (오류 발생 시)
  2. response : 응답 정보 (Node.js http.IncomingMessage 객체)
  3. body : 실제 데이터


사진을 보낼 때, Content-Type 사진 종류에 따라 값을 설정할 필요가 있는데, 여기에서는 상대방에게 받은 content-type을 그대로 이용합니다.


그럼, 서버를 시작하고 localhost:8080/nyaaaaaaaan/300/200에 접속해 봅시다.



귀엽다 

URL 숫자를 바꾸면 또 다른 이미지를 얻을 수 있습니다.


참조 : node js request (options, callback) (영문)

스트리밍

위의 코드는 일단 모든 파일을 서버로 가져온 다음, 클라이언트로 전송합니다.

이 방법은 다운로드 하는 동안 대기 시간이 발생하고, 가져온 데이터는 일단 메모리를 차지합니다. 이 포스트에서 만든 건, 로컬 임시 Server이지만, 그래도 별문제는 없습니다.


다만, 모처럼 Node.js를 사용하기 때문에, 스트리밍을 이용하고 싶다는 생각이 듭니다. 여기서 말하는 스트리밍은 데이터를 조금씩 읽어(로드) 조금씩 클라이언트에 전송하는 것입니다.


Node.js의 HTTP 통신은 처음부터 조금씩 읽는다는 사양입니다. 이 조금씩 읽어내는 데이터 조각을 "Chunk (청크, 덩어리)"라고 합니다.


Node js Request로 스트리밍을 쉽게 구현할 수 있는 기능이 있어서 이를 이용합니다. 코드는 다음과 같습니다.


/** * 얻고자 하는 곳의 서버 도메인:https://sample * 이미지 패스:/thumbnail?id=00000 */ const TEST_DOMAIN = 'https://sample'; app.get('/thumbnail', (req, res) => { request(TEST_DOMAIN + req.originalUrl).pipe(res); });


Simple!

파일 확장자를 보고 쉽게 전송 처리 해줍니다. 편리하죠~.

request 응답 결과로 원하는 이미지 파일의 URL을 전달합니다. 그리고 메소드 체인으로 pipe 메소드에 응답 후 처리를 전달합니다. 여기에서는 res 객체를 그대로 전달합니다. 이렇게 하면 "request 취득 후 → 클라이언트 전송" 스트리밍에 적용됩니다.


req.originalUrl : 도메인 아래의 경로를 매개 변수마다 별도로 제공합니다.


성공시 · 실패시 이벤트 핸들러를 넣는 것도 가능합니다. (실행은 한 번만)


app.get('/thumbnail', (req, res) => { request(TEST_DOMAIN + req.originalUrl) // 성공 시 .on('response', (response) => { console.log(response.statusCode); console.log(response.headers['content-type']); }) // 실패 시 .on('error', function (err) { console.log(err); res.sendStatus(404); }) .pipe(res); });


에러 핸들러를 설정했는데, 처리 부분에서 응답 처리를 구현하지 않으면 응답 없음 상태가 됩니다.


참조 : Streaming (영문)


이상으로 4회에 걸친 node js Express 시리즈를 종료하겠습니다.

변변치 않은 글을 읽어 주셔서 감사합니다. 도움이 된다면 정말 다행입니다.




댓글(0)