Octoping의 블로그
article thumbnail

문제 상황

네이버페이 결제 시스템을 구현을 하는데, 네이버페이 결제창을 호출하기 위해서는 자기들의 js 파일을 script 태그를 이용해서 불러와야 했다.

 

네이버페이 개발자센터

응답 예 Response HTTP/1.1 200 OK { "code": "Success", "message": "", "body": { "businessNo": "2208162517", "differenceResults": [{ "differenceRequestId": "DR201810300000008013", "payHistId": "20181113NP1000488732", "orderNo": "TEST001", "sequence": "00"

developer.pay.naver.com

npm을 통한 설치 방식이나, js파일을 직접 다운받아서 사용하는 방식은 지양하라고 하였기에, 어쩔 수 없이 script 태그를 쓸 수 밖에 없었다.

React 환경에서 CDN의 script 잘 불러오기

React는 SPA 어플리케이션이기 때문에 index.html<script src=와 같은 방식으로 직접 박을 시, 결제창을 띄울 필요가 없는 (해당 라이브러리를 사용하지 않는) 페이지에서도 해당 js 파일이 다운로드가 될 것이기 때문에 사용자의 로딩 속도를 괜히 늦추는 요인이 될 것이라 생각했다. 이는 UX 측면에서도 감점 요소이기도 하고.

따라서 useScript 라는 훅을 사용하여 (유명한 분께서 만든 레퍼런스를 그대로 가져왔다) 동적으로 script 태그를 만들도록 하였다.

 

useScript

 

usehooks.com

 

import { useScript } from './useScript';

function useNaverPay() {
  const status = useScript('https://nsp.pay.naver.com/sdk/js/naverpay.min.js');

  function createPayInstance() {
    // Error!! Naver가 뭔지 알 수 없다
    return Naver.Pay.create({
      mode: 'development',
      clientId: 'secret',
    });
  }

  // ....
}

하지만 이렇게 불러온 js 파일은 Typescript 입장에서는 전혀 알 수 없는 친구이기 때문에, 정적 타이핑을 보장 받지 못함은 물론이고, 심지어는 에러까지 발생시킨다.

결국 저 ‘Naver’이라는 녀석을 쓰는 곳곳마다 @ts-expect-error 를 사용하며 덕지덕지 붙는 것을 눈뜨고 쳐다볼 수 밖에 없었다.
그런데, script 태그를 이용해서 얻어와진 변수들은 window.Naver과 같은 모양으로 window 전역 변수에 저장이 된다는 사실을 알았다. 아하!

본격적으로 타입 붙여보기

export type Naver = {
  Pay: {
    create: (clientInfo: ClientInfo) => PayInstance;
    getVersion: () => string;
  };
};

type ClientInfo = {
  mode: 'development' | 'production';
  clientId: string;
  chainId: string;
  payType: 'normal' | 'recurrent';
  openType?: 'page' | 'popup';
  onAuthorize?: (oData: any) => void;
};

// ...

우선 네이버페이 개발자 문서를 보면서 타입을 만들어 준다.

내가 만들 도메인 로직에 필요한 타입만 작성해줄 수 있다. (결제 상품이 보험 및 위험 업종 등인 경우에만 필수 값인 변수 같은 것들은 내 서비스에는 필요 없기 때문에 굳이 작성하지 않고 생략해도 된다는 뜻!)

import { useScript } from './useScript';

function useNaverPay() {
  const status = useScript('https://nsp.pay.naver.com/sdk/js/naverpay.min.js');

  // @ts-expect-error
  const Naver: Naver = window.Naver;

  function createPayInstance() {
    return Naver.Pay.create({
      mode: 'development',
      clientId: 'secret',
    });
  }

  // ....
}

이런 식으로 window에게서 Naver를 꺼내온 후, 변수에 이 Naver의 참조를 저장 해준다.

거기에 내가 직접 만들어준 타입을 단언해서 붙여준다면 끝이다.

끝! 바로 바로 나와주는 자동완성.

이 맛에 어려워도 타입스크립트 쓰는 것이 아니겠는가?

profile

Octoping의 블로그

@Octoping

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!