API 호출 로직에 Typescript 입히기

호박고구마·2022년 2월 16일
7

Typescript

목록 보기
1/1

기존의 javascript로 구현된 레거시 프로젝트에 typescript를 입히는 과정에서 겪은 상황과 해결방법을 정리한 포스팅입니다.

1. Request 파라미터 타입 정의

서버에 데이터 요청시 공통으로 사용하는 파라미터의 타입들을 정해준다.
주로 리스트의 데이터를 가져오는 API 호출을 많이 사용해서 Request에 paging 관련 정보를 넣는다.

export interface CommonRequest {
  pagingNo: number;
  pagingSize: number;
  pagingSort: string;
}

2. Response 데이터 타입 정의

서버에서 공통으로 응답되는 것과 상황별 응답 데이터를 구분한다.

공통 데이터 타입 정의

서버에서 응답값을 줄 때 공통적으로 주는 부분을 정의한다.

export interface CommonResponse {
  resultCd: string;
  errCd: string;
  errMsg: string;
  // 아래 데이터는 필수값이 아니므로 ? 사용
  pagingLastPageNo?: number;
  pagingNo?: number;
  pagingRowCnt?: number;
  pagingTotCnt?: number;
}

상황별 정리

실제 API를 호출하는 상황에서 응답 받을 데이터를 정의한다.
예를 들어 장바구니 아이템 리스트를 가져오고 싶다면, 장바구니 아이템 자체에 대해 먼저 타입을 정의한다.

장바구니 아이템 타입 정의

export interface Item {
  name: string;
  price: number;
  type: string;
  createDate: string;
}

실제 데이터는 장바구니 아이템이 여러개 담긴 배열 형태로 떨어진다.

장바구니 아이템 리스트 조회 Request 타입 정의

export interface ItemListResponse extends CommonResponse {
  list: Item[]
}

extends를 활용해 공통으로 사용하는 응답 타입들을 사용하고, list라는 변수의 타입을 먼저 정의한 Item 객체 배열로 정의한다.


3. Axios 및 API 호출 로직 정의

axios 라이브러리를 통해 공통으로 API 호출을 정의하는 로직을 정의한다.

import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { CommonRequest } from '@/modules/types/api/common';

// axios instance 생성
const customAxios: AxiosInstance = axios.create({
  headers: {
    access_token: `${accessToken}`
  }
});

// 실제 API 통신
// path : API url
// params : request parameter
export const doAxios = async <T>(path: string, params: CommonRequest): Promise<T | null> => {
  try {
    const { status, data }: AxiosResponse<T> = await customAxios.post(path, params);
    return status < 500 ? data : null
  } catch (err) {
    console.log(err)
  }
};

제네릭을 이용해서 위 메소드를 호출하는 시점에 타입을 넘겨줄 수 있도록 한다. 이렇게 하면 doAxios 로 반환되는 값은 특정 타입을 갖게 된다.

4. API 호출하기


import { useCallback } from 'react';
import { doAxios } from '@/modules/common/api';
import { CommonRequest } from '@/modules/types/api/common';
import { ModuleResponse } from '@/modules/types/api/product';

const loadData = useCallback(async () => {
    const path = `${path}`
    const params: CommonRequest = {
      pagingNo: 1,
      pagingSize: 10,
      pagingSort: `${pagingSort}`
    }
    const data = await doAxios<ModuleResponse>(path, params)
  }, [])

이렇게 하면 data.resultCd, data.errMsg, data.pagingNo 등 CommonResponse interface에 정의한 값들에 바로 접근 가능하다.
동시에 ItemListResponse interface에 정의한 data.list에 접근 가능하다.
data.list에서 forEach, map 등의 메소드를 통해 각 배열의 인자의 키 값에도 접근 가능하다.


typescript가 없었다면 응답 값으로 무엇이 있는지 알 수 없고, 객체 안에 어떤 데이터가 있는지 알 수 없었을 텐데 type을 정의하니 자동으로 타입과 객체 추론이 가능하다!

1개의 댓글

comment-user-thumbnail
2022년 7월 19일

멋져유

답글 달기