문제 상황
네이버페이 결제 시스템을 구현을 하는데, 네이버페이 결제창을 호출하기 위해서는 자기들의 js 파일을 script
태그를 이용해서 불러와야 했다.
npm을 통한 설치 방식이나, js파일을 직접 다운받아서 사용하는 방식은 지양하라고 하였기에, 어쩔 수 없이 script
태그를 쓸 수 밖에 없었다.
React 환경에서 CDN의 script 잘 불러오기
React는 SPA 어플리케이션이기 때문에 index.html
에 <script src=
와 같은 방식으로 직접 박을 시, 결제창을 띄울 필요가 없는 (해당 라이브러리를 사용하지 않는) 페이지에서도 해당 js 파일이 다운로드가 될 것이기 때문에 사용자의 로딩 속도를 괜히 늦추는 요인이 될 것이라 생각했다. 이는 UX 측면에서도 감점 요소이기도 하고.
따라서 useScript
라는 훅을 사용하여 (유명한 분께서 만든 레퍼런스를 그대로 가져왔다) 동적으로 script
태그를 만들도록 하였다.
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의 참조를 저장 해준다.
거기에 내가 직접 만들어준 타입을 단언해서 붙여준다면 끝이다.
끝! 바로 바로 나와주는 자동완성.
이 맛에 어려워도 타입스크립트 쓰는 것이 아니겠는가?
'언어 > Javascript & Typescript' 카테고리의 다른 글
함수의 파라미터를 리터럴로 받는 방법과 응용 (0) | 2023.08.22 |
---|---|
레거시 프론트엔드 프로젝트 점진적으로 개선하기 (0) | 2023.04.13 |
배열 안의 원소들을 파라미터로 하는 Promise 체이닝하기 (0) | 2023.04.13 |
자바스크립트로 난수 만들기 (0) | 2022.09.06 |
현재 날짜를 원하는 포맷으로 출력하기 (2) | 2022.06.21 |