본 포스트에서는 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

+ Recent posts