Web/Quasar

Axios를 이용한 통신 모듈 구조화 - ts 버전

leonhong 2024. 7. 9. 12:01

연계 컨텐츠

1. Axios를 이용한 통신 :  https://dev-leon.tistory.com/82

2. Axios를 이용한 통신 모듈 구조화 : https://dev-leon.tistory.com/83

 

구조화가 필요한 이유

1. 통신 결과를 Interface로 선언하여, 통신 결과를 사용하는 개발자는 ts 모듈이 약속된 타입을 모두 알려줍니다.

2. 요청과 응답을 한곳에서 관리하므로, 백엔드 API가 변경되더라도 프런트엔드의 한 곳에서만 수정해주면 전체에 반영됩니다.

즉 개발자들이 호출한 곳을 일일이 찾아가며 변경할 필요가 없어 집니다.

 

통신의 반환값의 타입을 Interface로 지정하는 방법

ts에서는 반환값을 지정할수 있는데, 함수를 하나 만들어서 백엔드와 약속된 형식이 있다면 해당 형식을 Promise<Interface Type> 형태로 반환해 주면 가능합니다.

// Echo API 응답 데이터 형식
export interface RespEcho {
  result_code: string;
  result_desc: string;
}  

// get 요청을 RespEcho 타입으로 반환받기
// 중요. 예외처리는 따로 해줘야 함.
export public get(): Promise<RespEcho> {
  return api.get(this.url).then((res) => res.data);
}

 

비동기 통신을 동기 방식으로 변경하기

 비동기 통신은 통신이 완료될때까지 작동을 멈춰서 기다리지 않고 다른 작업을 해줄수 있게 해주는 좋은 방법입니다. 

 그런데 프런트엔드에서 비동기 통신을 하려면 then 구문아래에 원하는 작업을 넣어줘야 하는데, 2~3개만 연계해서 처리 하려고 하면 then, then 코드지옥이 펼쳐지면서 보기 힘들어 집니다. 

  따라서 동기통신이 시스템에 문제가 없다면 동기통신으로 하는게 유지보수에 편합니다.

// Get API 호출을 동기 방식으로 변경
// 기존 방식에서 async과 await를 추가하면 완료
 export public async get(): Promise<RespEcho> {
   return await api.get(this.url).then((res) => res.data);
 }

 

사용시에는 아래와 같이 하면 됩니다.

함수를 호출할때 주의사항이 있습니다. 

Aixos를 동기방식으로 호출할때는 예외처리를 반드시 해줘야 합니다.

관용적으로 이렇게 사용해야 안전합니다.

...
import { RespEcho, get } from 'src/common/gateway';
...

// component에서 실제로 get api를 호출하기
// get api 호출할때도 async, await를 붙여줘야 하므로 함수를 새로 선언한다.
// 중요! 항상 try catch로 묶어서 처리해야 한다.
async function testFunc() {
  try {
    const commEcho = new CommEcho();

    // get 방식 호출
    const respGet: RespEcho = await get();
    console.log('Echo code Get:', respGet.result_code);
    console.log('Echo desc Get:', respGet.result_desc);

  } catch (e) {
    console.error('error:', e);
  }
}

 

클래스로 묶어서 최종적으로 구조화 완료

클래스로 묶어주면 동일한 URL에 대한 일관성 있는 관리가 가능해집니다. 

 

1. 통신을 수행할 클래스 내부에 요청 URL 설정

2. 통신 클래스에  get, post, put, delete 함수를 필요에 따라서 작성

import api from './api';

// Echo API 응답 데이터 형식
export interface RespEcho {
  result_code: string;
  result_desc: string;
}

// Echo관련 통신을 담당하는 클래스
export class CommEcho {
  // 요청 URL
  url: string;

  constructor() {
    this.url = 'test/test-url';
  }

  // Get API 호출
  public async get(): Promise<RespEcho> {
    return await api.get(this.url).then((res) => res.data);
  }

  // Post API 호출
  public async post(echoCode: string, echoDesc: string): Promise<RespEcho> {
    return await api
      .post(this.url, {
        echo_result_code: echoCode,
        echo_result_desc: echoDesc,
      })
      .then((res) => res.data);
  }
}

 

사용시에는 아래와 같이 하면 됩니다.

......
import { CommEcho, RespEcho } from 'src/common/gateway';
......

async function init() {
  try {
    const commEcho = new CommEcho();

    // get 방식 호출
    const respGet: RespEcho = await commEcho.get();
    console.log('Echo code Get:', respGet.result_code);
    console.log('Echo desc Get:', respGet.result_desc);

    // post 방식 호출
    const respPost = await commEcho.post('0', 'Hello, Quasar!');
    console.log('Echo code Post:', respPost.result_code);
    console.log('Echo desc Post:', respPost.result_desc);
  } catch (e) {
    console.error('error:', e);
  }
}