React | 유지, 보수를 위한 API 통신은 어떻게 할까? (Axios 모듈화)

Positive Ko·2021년 1월 3일
45

React

목록 보기
13/17
post-thumbnail

요즈음 Node.js 세션을 통해 배운 '모듈화'개념과, 기업 협업 프로젝트에서 피드백 받은 'API 통신 방식'에 대해 기록해보려고 한다.

최근에 배웠던 Node.js 세션에서 가장 인상 깊었던 부분은 Why do we modularize our applications? 에 대한 내용이었다.

왜 우린 모듈화를 해야할까?

  • 확장성(extensibility)
    확장성을 고려하지 않은 코드는 시스템의 규모가 커질수록 문제가 생길 확률이 높다.
  • 재사용성(reusability)
    반복되는 로직을 함수로 분리하는 코드상의 재사용성 뿐만 아니라, 우리가 설계한 구조가 재사용 되어야 한다.
  • 유지-보수 가능성(maintability)
    여러 로직이 뒤엉켜 있는 코드는 유지 보수가 안된다.
  • 가독성(readability)
    어려운 로직 일수록 더 가독성이 높아야 한다. 어려운 로직을 쉽고 간단하게 구현하는 것이 좋은 코드다.
    프로젝트의 구조 또한 한 눈에 그려져야 한다.
  • 테스트 가능성(testability)
    테스트를 하기 쉬운 코드는 모듈화가 잘 되어 있고, 한 가지 역할만 하는 함수 단위의 코드를 의미한다.
    프로젝트의 구조도 추상화가 잘 되어있고, 역할이 잘 나뉘어 있는 구조가 테스트하기 쉬운 구조다.
    출처: 깔끔한 파이썬 탄탄한 백엔드 - 송은우 저

출처: 위코드 Node.js Notion (by 최 준 멘토님)




이 수업을 들은 뒤부터는 보다 확장성을 위한, 재사용이 가능한, 유지와 보수에 쉬운 컴포넌트를 만드려고 노력하고 있다.
하지만 정작 가장 자주 쓰이고, 똑같은 코드를 반복하는 'API 통신'에 있어서 모듈화를 하지 않았고 이에 대해 좋은 피드백을 받았다.

기존에 사용하던 API 통신 방식은 다음과 같다.

먼저 config.js에 server로 변수를 지정해 서버 IP 주소를 넣어준다. (이 또한 환경변수로 .env에 숨겨준다). 그리고 각각의 API 변수에 엔드포인트를 넣어서 export해서 사용하는 방식이었다.

그리고 try catch에 async await으로 작성하거나 다음과 같이 then then으로 비동기 처리해주는 방식..(코린이 티😇)


자 일단, 받은 피드백을 정리해보자면

1) {SERVER}로 export하지 않고 server 주소가 들어가있는 apiClient 함수를 만들어서 export하자!

당시 query 검색을 위해서 그냥 서버주소를 통채로 가져와 query만 변수 처리를 해주는 리터럴 방식을 쓰고 있었다.
(url: ${SERVER}/map/search?search=${query} 이런식으로..다가)
하지만 이렇게 쓰게 되면 백엔드와 통신할 일이 굉장히 많기 때문에 SERVER를 매번 넣어주는 것 보다 axios와 기본 세팅이 되어 있는 apiClient 훅을 만들어서 사용하는 것이 좋겠다는 아-아주 유용한 피드백을 받았다.

2) async, await을 쓰자

코드 가독성에는 async, await으로 간결하게 작성하는 것이 최고겠쥬..
fetch then then으로 처음 api 통신을 배워서 아직까지도 then을 애용하던 나였다...


적용해보자!

1) apiClient.ts를 만들었다.

axios.create() 메소드를 이용해서 axios 인스턴스를 생성하도록 만들어준다.
공식문서 참고

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  headers: { 'X-Custom-Header': 'foobar' },
  timeout: 1000,
});

axios.create()이 핵심..!!✨
저렇게 axios의 .create() 내장 함수를 이용하면 통신할 때 필요한
쿼리나, 헤더, 바디 등등 여러 데이터를 함께 보낼 수 있다.

저렇게 baseURL에 SERVER 주소를 넣어주면 된다. instance에 넣을 수 있는 키값으로 params, data, responseType, xsrfHeaderName 같은 것들을 넣어줄 수 있어서 정말 편리하다!

(이제 이 ts 함수는 재사용성에 있어서 최고, 가장 많이 사용한 훅이 된다..)

2) 사용할 때에는 다음과 같이 사용하면 된다.

이렇게 endpoint와 query만 변수로 넣어주면 된다.
지금 보니 try catch문도 함께 넣어버리면 될 텐데 왜 저기서 그쳐버렸지..?하는 생각도 든다.. 🤭

정리

코딩을 배우면 배울수록 재사용이 가능한 코드. 누가 읽어도 가독성이 높은 그런 코드를 작성하고 싶어진다. 마치 레고 조각처럼 어디에든 들어가도 그 기능을 수행할 수 있는 그런 확장성 있는 코드. 요즘 들어 기능 구현에 급급한 그런 코드가 아니라 정성이 묻어난 코드를 작성하고 싶은 욕구가 있었는데,

이런 생각에서 가장 의미 있고 중요한 피드백과 세션 내용이었다.
(준님과 우성님께 감사..🙏🏻)

물론 이런 코드를 작성하기 위해서 그냥 코드를 나열하는 것보다 몇 배의 시간이 들지만... 이번 프로젝트를 통해 내가 아닌 다른 사람을 위한 코드, 오늘이 아닌 내일을 위한 코드를 작성하기 위해 계속 노력해보겠다🔥

profile
내 이름 고은정, 은을 180deg 돌려 고긍정 🤭

6개의 댓글

comment-user-thumbnail
2021년 1월 3일

은정님...진짜 왤케 잘해요...
감탄밖에 안나오내....그만잘해~~

1개의 답글
comment-user-thumbnail
2021년 1월 6일

긍정코.. 멋집니다.. token 없을 때 에러 핸들링은 어떻게 하고 있나요?

답글 달기
comment-user-thumbnail
2021년 1월 7일

제 경우에는 유지보수를 위해
api 함수는 api만 보내도록하였습니다.
export const getUserListAPI = ()=> apiClinter.get<User[]>("/users");
또한 제네릭을 이처럼 사용하면 Promise<AxiosResponse<User[]>>라는 타입을 얻게 됩니다.
또한 api를 구분하기 위해 카테고리별로 파일을 구분합니다.
"api/users/index.ts"
👍

답글 달기
comment-user-thumbnail
2021년 1월 14일

안녕하세요, 은정님!
온라인 클래스 플랫폼 클래스101 피플팀 로사라고 합니다.
티타임을 통해 은정님을 만나뵙고 싶은데,
따로 연락처를 받을 수 있을까요?^^
rosa@101.inc로 회신 주시면 감사하겠습니다.
연락 기다리겠습니다.

감사합니다.

'모두가 사랑하는 일을 하며 살 수 있도록'
CLASS101 로사드림

답글 달기
comment-user-thumbnail
2021년 2월 1일

몇달간 쭉 봐왔지만... 은정님은 참 대단한 사람인 것 같다.
"Grit" 이라는 단어가 가장 어울리는 사람인 것 같아요.... 개발자가 아니어도 뭘 해도 성공할 사람임!

답글 달기