API 스펙만 주세요

59INU·2022년 2월 27일
0

프론트엔드 미니세미나 #2


새로운 기능을 추가하기로 했다.
요구사항 분석이 끝나고 백엔드는 API 작업에 착수한다.
프론트엔드는 예쁘게 배포된 API를 활용해 작업을 이어나간다.
-앗, 아름다워.

하지만 현실에서는 프론트엔드 작업 착수 시점에 다소곳하게 준비된 API가 나를 기다리고 있고, 정갈한 목록을 보며 불러다 쓰면 되는 상황은 그다지 흔하게 만나는 일이 아니다. 기획이 공유되고 요구 사항 분석이 끝나고 나면 백엔드와 프론트엔드가 작업을 병행해야 비로소 겨우 아름다울 일정이 눈 앞에 주어진다.

응답 받은 데이터 모델을 화면에 잘 그리는 것만으로 족하다면 임의 객체를 소스코드에 때려 박아 개발하는 것으로도 좋을것 같다(^^7). 하지만 네트워크 요청 처리 상태에 따른 테스트와 구현 작업 등에는 한계가 있었고, 반쪽짜리 모킹과 모지란 작업으로 몇차례 마무리 일정에 쫓기고나니 결국 진지하게 API 모킹에 대한 필요성을 느끼게 되었다.

History of Trying

1: 네트워크 그런 거 모르겠고 소스코드에 때려박기

정말로 이런 코드를 썼다.

  // const { data } = thisIsRealQueryFunction()
  const data = {
    aKey: value,
    anotherKey: anotherValue,
    theOtherKey: theOtherValue
  }
  // const { data } = thisIsRealQueryFunction()
  const thisIsRealQueryFunction = ()=>({data: stubData()})
  const { data } = thisIsRealQueryFunction()
  • 장점: 뇌를 빼놓고 출근해도 할 수 있다. 쉽고 빠르다.
  • 단점: 기본적으로 네트워크 응답 상태 같은 건 고려하지 않는다.
  • 귀찮고 까먹으면 위험한 점: 서비스 로직을 구현하는 소스 코드에 직접적인 수정이 동반된다.

2: 서버가 문제니까 서버를 만든다

목서버를 직접 띄워 개발 과정에 사용하는 옵션이 존재한다는 것을 알게 되었다. 생각만으로 벌써 귀찮지만 postman의 MockServer 기능을 활용하면 사실 쉽게 사용할 수도 있다.

  • 장점: 서비스 로직을 수정하지 않는다. 네트워크 응답 상태를 고려할 수 있다.
  • 단점: 목서버 관리하기, 동일 요청에 대한 상이한 응답 케이스를 테스트하기에 유연하지 않음
  • 귀찮고 까먹으면 위험한 점:
    postman일 경우; 서버 url
    (환경 변수로 관리 가능하지만 다른 작업자와 서버상태를 공유해야한다면? 귀찮다)

3: 그 요청 서버로 보내지 않습니다

소스코드와 서버를 건드려봤다. (사실 저는 서버는 건드리지 않았지만 머리속으로 했다 치고)
서비스 로직을 직접 수정하긴 싫고, 서버는 유연하지 못한데다 귀찮으니까 소스코드와 서버 사이에 어딘가에서 요청을 탈취한다. ta-da. msw로 모시겠습니다.

What is msw

Mock Service Worker is an API mocking library that uses Service Worker API to intercept actual requests.

실제 네트워크 요청을 가로채기 위해 ServiceWorker API를 사용하는 API 모킹용 라이브러리다.

프로그래밍 가능한 네트워크 프록시인 ServiceWorker를 사용해, 클라이언트에서 전송한 실제 요청을 가로채서 사전에 정의한 응답을 매칭시켜 다시 클라이언트 메인 스레드로 돌려보내는 방식으로 에러, 대기, 응답 등 다양한 네트워크 상태를 쉽게 정의할 수 있어 별도로 목서버를 구현하지 않고도 네트워크 수준의 모킹을 가능하게 해준다.

Why I chose

최근에 주로 작업하고 있는 다노핏 웹의 api 요청들은 정해진 경로의 get 요청에 따라 정해진 정보값을 가져오는 단순 데이터 조회용 api와는 거리가 멀다. 페이로드가 같거나 혹은 페이로드를 받지도 않는 동일한 api 요청에 대해 인증 유저의 고유한 상태에 따라 천차만별의 응답을 받고 각 케이스에 대한 뷰와 작동을 구현해야한다.
포스트맨의 팀 기능과 콜렉션 공유 기능 등 목서버 설정과 공동작업을 위한 공유 기능이 지원됨에도 결국 유연성을 고려했을 때 msw를 우선순위에 둔 이유는 api 요청에 대한 응답을 얼마나 유연하게 변경하고 재정의할 수 있느냐를 생각했기 때문이다.
개발 과정에서의 api 모킹 수단을 고려하기 앞서 이미 테스트코드와 스토리북에서 msw를 사용하고 있었고, 테스트 케이스마다 필요한 응답 상태를 정의할 수 있다는 점은 그만큼 요청에 대한 응답을 컨트롤하기에 유연하다는 의미이기도 하다.

When to use

  1. 아직 세상에 없는 API의 응답을 받아야 할 때
  2. API 응답 시 에러와 엣지 케이스 대응 작업이 필요할 때
  3. 테스트 시나리오에 필요한 API 호출과 결과를 컨트롤해야 할 때

How to use

1. 패키지 설치하기

$ npm install msw --save-dev
# or
$ yarn add msw --dev

2. 서비스워커 등록 파일 생성

/public /build 등 프로젝트의 공용폴더 경로를 참고하여 아래 명령어를 실행한다.

$ npx msw init <PUBLIC_DIR> --save

위 명령어의 실행 결과는 지정한 경로에 자동 생성되는 mockServiceWorker.js 파일로 브라우저에서 서비스워커를 설치하기 위한 코드와 msw에서 요청을 탈취해 조작하기 위한 핸들러를 정의하는 코드를 포함하고 있다.

3. mock API 정의하기

$ mkdir src/mocks
$ touch src/mocks/handlers.js

파일을 생성해 모킹이 필요한 api 핸들러를 정의한다.

요청 핸들러는 요청객체, 응답객체, 응답형태변환을 위한 컨텍스트를 전달받는다. 이 때 두 번째 인자인 응답객체(response) 자체를 직접 조작하는 것도 가능하지만 결국 컨텍스트에 정의한 작업을 거쳐 서비스워커에 최종 전달하는 응답 객체를 반환하게되므로 컨텍스트를 사용해 모킹하는 것을 권장한다.

import {rest} from 'msw'

const handlers = [
  rest.get('/api/user', (req, res, ctx) => {
    return res(
      ctx.status(200, 'Custom status text')// 응답 상태 코드와 텍스트
  	  ctx.json({
      	name: 'KimUser',
      	age: 7,
      }),
  })
]

4. 워커 인스턴스 구성

$ touch src/mocks/browser.js

파일을 생성해 정의해둔 핸들러를 주입하여 브라우저 환경의 워커 인스턴스를 생성한다.

import { setupWorker } from 'msw'
import { handlers } from './handlers'

export const worker = setupWorker(...handlers)

What about in NodeJs environment ?
테스트 등 NodeJs 환경에서 api를 모킹해야 한다면 setupServer 함수를 이용해 인스턴스를 생성할 수 있다. (이 때, msw 는 브라우저 환경과 달리 서비스워커를 사용할 수 없으므로 http,https 등 네트워크 관련 모듈을 몽키패칭하여 요청을 가로채는 방식으로 작동한다)

5. 워커 실행

구성한 워커 인스턴스를 런타임에 실행하기 위해 애플리케이션 코드에 워커 실행 코드를 주입한다.

import { worker } from './mocks/browser'

worker.start()

실행 환경에 따라 모킹 여부를 달리하고 싶다면 아래의 예제와 같이 환경변수를 사용한 조건문을 통해 msw의 실행 여부를 통제할 수도 있다.

if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser')
  worker.start()
}

후기

msw의 개발 과정 도입에 앞서 팀에 소개하기 위해 미니세미나에 준비했던 내용만 겨우 정리했다.
핸들러 파일에 모의 응답을 미리 정의하는 방식 외에 서비스 로직 구현 코드 가까이에서 쉽게 응답을 재정의할 수 있는 모듈을 만들어두고 천오백십이번 응답 상태를 마구 바꾸면서 개발을 하고 싶고. 천오백이십번 마구 손쉽게 바꾸면서 개발한다는 게 중요함.
NODE_ENV === development 환경에 실행되는 게 아니라 실행 명령어 옵션을 통해 msw 실행 여부를 통제할 수 있도록 설정할 것이며 아무튼간에 완료되면 다시 글을 써야지.

profile
개랑 사는 개발자

0개의 댓글