1. 발단

  • 가족과 같이 특정 영화를 보고자할 때..
    • 애들과 같이 봐도 될지 등급은 어떻게 매겨진건지 알고 싶을때가 있다.
  • 우리나라 영화 등급은 영상물등급위원회에서 설정한다.
    • 영등위는 open api 도 제공한다.
  • 사용하는 예제를 만들어보자

2. 전개

이슈들

API Key가 URL encoding 처리가 되어 승인되지 않은 키 에러가 나는 문제

  • 기본 부족 보충
    • URL - Uniform Resource Locator
      • 웹 브라우저는 웹서버로 부터 페이지를 요청할 때 URL을 사용한다
      • URL은 웹 페이지의 주소이다.
    • URL Encoding (Percent Encoding)
      • URL encoding은 URL에 사용되는 문자를 인터넷을 통해 전달할 수 있는 format으로 변환한다
      • URL은 ASCII 문자셋 만 사용할 수 있다.
      • URL은 종종 ASCII set외의 문자를 포함하기 때문에, URL은 유효한 ASCII format으로 변환될 필요가 있다.
      • URL encoding은 unsafe ASCII 문자를 “%”와 16진수 숫자 두개로 변경한다.
      • URL은 공백을 포함할 수 없다. URL encoding은 보통 space를 plus(+) 나 %20 으로 변환한다
  • request 혹은 axios를 사용하여 URL을 구성할 때 서비스 키가 없다면 다음과 같이 구성하게 된다
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    const option = {
      query : '뱀파이어',
      start : 1,
      display : 10,
      yearfrom : 2014,
      yearto : 2014
    }
    request.get({
      uri: 'https://api.koreafilm.or.kr/openapi-data2/wisenut/search_api/serach_json2.jsp',
      qs: option
      }, function(err, res, body) {
        ...
      })
    
    • 그런데 서비스 키가 있다면 단순히 option에 ServiceKey를 넣으면 될거라고 생각하게 된다.
      1
      2
      3
      4
      5
      
      const option = {
        ServiceKey : '나는서비스키',
        query : '뱀파이어',
        ...
      }
      
  • 승인받은 키에 “..%3D..” 문자가 섞여 있는데 “..%253D..”로 변환되어 승인되지 않은 키라는 에러가 계속 나옴
    • 해당 키가 이미 URLencoding된 상태이지만 한 번 더 encoding되면서 나오는 문제임
    • double encoding이라는 공격기법에도 언급되는 내용?
      • ”%”를 인코딩하면 “%25”로 변환됨
  • 해결책은 한번 더 인코딩되지 않도록 URI에 직접 포함시킴

request deprecated …

config-js 사용하기

  • open api를 사용하다보면 필연적으로 credentials를 사용하게 된다.
  • 이런 정보들은 남에게 공개되면 안되는 정보들이므로 github에 올릴때 제외해야 한다.
  • 제외하는 방법에 대한 글 : Keeping secrets
  • 나는 설정파일 사용하는 방법을 사용하기로 하고 config-js를 찾아내었다.

CommonJS 방식과 ES Modues 방식의 조합

main.js 에서 config-js 불러오기
  • CommonJS 방식
    1
    2
    
    var Config = require('config-js');
    var config = new Config('...');
    
  • ES module 방식
    1
    2
    
    import Config from 'config-js'
    let config = new Config('...')
    
  • 이 부분의 실패
    • 처음에는 new 없이 let config = Config('...') 으로만 호출하여 다음과 같은 에러가 계속 났다.
      1
      2
      3
      4
      
      ~/node_module/config-js/index.js:56
      this.pathToDefaults = path.join(path.dirname(pathToConfig.FileIn)
                          ^
      TypeError: Cannot set property 'pathToDefaults' of undefined
      
    • 즉, thisundefined인 상태에서 this의 propety인 pathToDefaults에 접근하려고 했다.
    • thisundefined인 이유는 Confignew로 생성하지 않았기 때문
debug.js 의 사용
  • 위 섹션의 실패를 경험하면서 config-js 패키지 내부에서 사용한 debug.js 모듈의 출력을 보고 싶었다.
  • debug.js의 github에 설명이 잘되어 있는데 ..
    • 내가 사용중인 node.js + windows powershell 환경에 관한 설정도 나와있다.
    • package.jsonscripts 옵션에 다음과 같이 추가한다
      1
      2
      3
      4
      
      "scripts": {
        "main": "@powershell -Command $env:DEBUG='';node ./src/main.js"
        "debug": "@powershell -Command $env:DEBUG='*';node ./src/main.js"
      }
      
      • 위와 같이 설정하고 쉘에서 npm run debug하면 쉘에 디버그로그가 출력된다.
        • 웹에서 사용하면 브라우저 디버그 모드에서 컬러링된 출력을 지원한다고 한다
      • 위에서 DEBUG='*' 부분에 * 대신 원하는 로그를 지정할 수 있는듯 하다.
      • color를 지원하는 쉘에서 보면 debug로그가 이쁘게 나온다.
      • 해당세션에서 임시로 DEBUG 변수를 선언했기에 해당 세션이 죽기전까지 계속 DEBUG 활성화상태이다.
        • npm run main시에 디버그로그를 죽이고 싶다면 main을 위와 같이 바꾼다.
설정파일의 확장자 문제
  • 이 부분에서 많이 헤맸는데 아래 링크를 잘 참조해보자
  • 이 부분의 실패
    • cfg_secret.jsconfig file을 만들었는데…
      • 파일 경로에는 문제가 없지만 require로 config file을 불러올 때 계속 다음 에러가 난다
        1
        2
        3
        4
        5
        
        > npm run debug
              
        ...(debug.js 출력)
        config-js Could not load target config: "~/OpenApiTest/src/cfg_secret.js" +1ms
        ...
        
    • 문제가 되는 config-js의 코드 부분은 다음과 같다.
      1
      2
      3
      4
      5
      6
      
      try{
        targetConfig = require(pathToConfigFile);
        debug('Required config: '+pathToConfigFile);
      } catch(err) {
        debug('Could not load target config: "'+pathToConfigFile+'"');
      }
      
    • 위 catch 블럭에 err 찍는 내용이 없어 추가해서 찍어보니 다음과 같았다.
      1
      2
      3
      4
      5
      
      ...(debug.js 출력)
      config-js err: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ~/OpenApiTest/src/cfg_secret.js
      config-js require() of /OpenApiTest/src/cfg_secret.js from ~/OpenApiTest/node_modules/config-js/index.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines 
      config-js Instead rename cfg_secret.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from ~/OpenApiTest/package.json.
      config-js  +1ms
      
  • 해결
    • 위 지시사항대로 cfg_secret.jscfg_secret.cjs로 수정하고, 관련코드를 수정하고 실행해보니 잘 되었다.
  • 소감
    • 결과적으로 CommonJS와 ES Module은 호환은 가능하지만 신경을 써줘야한다.