티스토리 뷰

라즈베리 파이에서 naver 책 API를 열어 쉽게 정보를 가져왔었다.

https://ing-min.tistory.com/63

 

Naver 크롤링 : 파파고 python + 도서 API

라즈베리파이 LCD가 영어밖에 프린트가 안 되서 파파고로 번역기 돌리는 코드를 추가했다. import csv import drivers # import I2C_LCD_driver from time import sleep import os import sys import urllib.reque..

ing-min.tistory.com

하지만 Back(node.js)에서 처리 과정이 세분화되어있으므로 구조 관리하기 까다로웠다.

(DB -> dao -> service-> routers -> app.js)

dao  :  데이터 베이스를 관리하는 폴더 CURD

service : dao를 연결하여 서비스를 관리하는 폴더

routers : 각 주소마다 분리하여 라우터 관리해주는 폴더

app,js : 전체 Backend 서버를 관리하는 파일

따라서 프론트에서 POST 한 isbn 값을 이용하여, 백 서버에서 naver 책 API를 연결 isbn 값을 넘겨 책 이름 이미지 출판사 정보를 자동으로 받아와 DB에 저장해보자.

참고 네이버 문서

https://developers.naver.com/docs/serviceapi/search/blog/blog.md#%EC%B1%85

 

블로그 - Search API

블로그 NAVER Developers - 검색 API 블로그 검색 개발가이드 검색 > 블로그 네이버 블로그 검색 결과를 출력해주는 REST API입니다. 비로그인 오픈 API이므로 GET으로 호출할 때 HTTP Header에 애플리케이션

developers.naver.com

 

1. 블로그 검색 -> 책 검색

: 네이버 참고 문서에서는 '블로그'를 기본으로 설명되어 있다. 나는 '책' 주소가 필요하므로 '블로그' 주소를 '책' 주소로 바꿔주면 된다.

// 네이버 검색 API예제는 블로그를 비롯 전문자료까지 호출방법이 동일하므로 blog검색만 대표로 예제를 올렸습니다.
// 네이버 검색 Open API 예제 - 블로그 검색
//node.js
var express = require('express');
var app = express();
var client_id = 'YOUR_CLIENT_ID';
var client_secret = 'YOUR_CLIENT_SECRET';
app.get('/search/blog', function (req, res) {
   var api_url = 'https://openapi.naver.com/v1/search/book.json'; // json 결과
   var request = require('request');
   var options = {
       url: api_url,
       headers: {'X-Naver-Client-Id':client_id, 'X-Naver-Client-Secret': client_secret}
    };
   request.get(options, function (error, response, body) {
     if (!error && response.statusCode == 200) {
       res.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'});
       res.end(body);
     } else {
       res.status(response.statusCode).end();
       console.log('error = ' + response.statusCode);
     }
   });
 });
 app.listen(3000, function () {
   console.log('http://127.0.0.1:3000/search/blog?query=검색어 app listening on port 3000!');
 });

 

2. request -> axios

: request와 express로 app.get 메서드를 활용하여 값을 받아오는데, 나는 regi라는 라우터에서 naver 주소에서 값을 받아와 post로 front 서버에 값을 넘겨야 한다. 따라서 위에 설명했듯 service -> routers -> app.js 이렇게 구조를 나누어 /regi 경로로 요청(isbn)이 들어올 경우 post로 값을 보내줘야 한다.

>service.js

const logger = require('../lib/logger');
const storageDao = require('../dao/storageDao');
const axios = require('axios');
const { eventNames } = require('../app');


const service = {
...

  // NAVER book API search ************
  async more_info(params) {
    let result = null;
    const client_id = process.env.client_id;
    const client_secret = process.env.client_secret;
    console.log(client_id);
    console.log(client_secret);
    try {
      result = await axios.get('https://openapi.naver.com/v1/search/book.json',{
      headers: {
        'X-Naver-Client-Id' : client_id, 
        'X-Naver-Client-Secret' : client_secret,
      }, 
      params: {
        query : params
      }
      })
      .then(result => { return result.data.items })
      .catch(err => { console.log(err) })
      logger.debug(`(storageService.more_info) ${result}`);
    } catch (err) {
      logger.error(`(storageService.more_info) ${err.toString()}`);
      return new Promise((resolve, reject) => {
        reject(err);
      });
    }
    return new Promise((resolve) => {
      resolve(result);
    });
  },
  
  ...

  // delelte
  async delete(params) {
    let result = null;

    try {
      result = await storageDao.delete(params);
      logger.debug(`(storageService.delete) ${JSON.stringify(result)}`);
    } catch (err) {
      logger.error(`(storageService.delete) ${err.toString()}`);
      return new Promise((resolve, reject) => {
        reject(err);
      });
    }

    return new Promise((resolve) => {
      resolve(result);
    });
  },
};

module.exports = service;

 

 

>regi.js

const express = require('express')

const router = express.Router()
const logger = require('../lib/logger')
const storageService = require('../service/storageService')

// 등록
router.post('/', async (req, res) => {
  try {
    const params = {
      isbn: req.body.isbn,
      price: req.body.price,
      location: req.body.location,
      review: req.body.review
    }
  
    // 입력값 null 체크
    if (!params.isbn) {
      const err = new Error('Not allowed null (name)')
      logger.error(err.toString())
      res.status(500).json({ err: err.toString() })
    }
    
    // 네이버 상세정보 조회
    const result_2 = await storageService.more_info(params.isbn)
    logger.info(`(storage.more_info.result) ${result_2}`)
    
    const params_list = { ...params, result_2 }
    const total_params = {
      isbn: params_list.isbn,
      review: params_list.review,
      price: params_list.price,
      location: params_list.location,
      title: params_list.result_2[0].title,
      author: params_list.result_2[0].author,
      publisher: params_list.result_2[0].publisher,
      image: params_list.result_2[0].image,
      link: params_list.result_2[0].link,
    }
    logger.info(`(storage.reg.params) ${JSON.stringify(total_params)}`)

    // 비즈니스 로직 호출
    const result = await storageService.reg(total_params)
    logger.info(`(storage.reg.result) ${JSON.stringify(result)}`)

    // 최종 응답
    res.status(200).json(result)
  } catch (err) {
    res.status(500).json({ err: err.toString() })
  }
})

...

})

module.exports = router

 

>index.js

const express = require('express');
const homeRouter = require('./home');
const regiRouter = require('./regi');

const router = express.Router();

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

// RESTFull API
router.use('/home', homeRouter);
router.use('/regi', regiRouter);

module.exports = router;

 

 

>app.js

const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const dotenv = require('dotenv');
const cors = require('cors');
const corsConfig = require('./config/corsConfig.json');
const models = require('./models');
const logger = require('./lib/logger');
const bodyParser = require('body-parser');

dotenv.config();

const NODE_ENV = process.env.NODE_ENV;

//라우터 불러오기 **********************
const indexRouter = require('./routes/index');

const app = express();

logger.info('app start');

// view engine setup
// views -> 사용하는 템플릿 엔진 이 있는 디렉토리 설정 
app.set('views', path.join(__dirname, 'views'));
// 뷰 엔진 설정 - express에서 사용할 템플릿 엔진을 설정합니다. ejs로 생성했기 때문에 ejs 지정
app.set('view engine', 'ejs');

app.use(cors(corsConfig)); // 해당 파일에 적힌 내용에 대해 교차통신 허용
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// 라우터 연결********************
app.use('/', indexRouter);


// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

...

module.exports = app;

 

exports와 require를 잘 이용하여 파일을 구조화하여 사용한다!

 

결론은 엑시오스를 사용하여 naver api를 간편하게 불러왔다.

axios.get(주소, 아이디 비번이 담긴 헤더와 isbn 값을 담은 params를 담은 query)로 값을 네이버로 보내고

값을 result에 담아 return 하여 front로 전송하는 것!

 result = await axios.get('https://openapi.naver.com/v1/search/book.json',{
      headers: {
        'X-Naver-Client-Id' : client_id, 
        'X-Naver-Client-Secret' : client_secret,
      }, 
      params: {
        query : params
      }
      })
      .then(result => { return result.data.items })
      .catch(err => { console.log(err) })
      logger.debug(`(storageService.more_info) ${result}`);
    } catch (err) {
      logger.error(`(storageService.more_info) ${err.toString()}`);
      return new Promise((resolve, reject) => {
        reject(err);
      });
    }
    return new Promise((resolve) => {
      resolve(result);
    });
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함