OAS로 API 자동화하기
이전 팀에 프론트엔드 개발자로 합류했을 당시 백엔드와 업무간에 병목이 있었다. 프론트는 백엔드가 내려준 API 양식을 따라 그대로 작업하는 구조였는데 여기서 두 가지 문제가 파생되었다. 첫째는 백엔드가 API 작업을 끝마치기 전 까지 제대로 된 구현을 할 수 없다는 점이다. 기획서에 기재된 요구사항을 보고 '이러저러한 응답값이 내려오겠다'를 예측해서 인터페이스를 정의할 순 있었지만, 이후 실제 API를 받았을 때 스키마부터 데이터 호출부와 컴포넌트에 전달하는 과정까지 여지없이 모두 고쳐야하는 노력이 반복되었다. 두번째 문제는 API가 잘못 설계되었을 때다. 프론트가 받아서 구현하는 중에 API의 문제점이 발견되면 다시 또 시간이 지연되었다. 버그성 이슈라면 사람이니 그럴 수 있다 치고 넘어가지만, 소통의 부재로 인해 놓친 경우는 뼈아픈 손실이다.
그래서 API 개발 착수 전에 프론트-백엔드가 기획서를 보고 논의하는 시간을 제안했다. 이를 통해 API가 요구사항을 반영하지 못하고 잘못 설계되는 빈도를 줄일 수 있었다. UI 구현에 있어 '데이터가 이런식으로 내려오면 편해요' 등을 어필 하면서 실속도 챙길 수 있었다. 하지만 이런식의 구두 논의로는 앞서 언급한 첫 번째 문제를 해결할 수 없었다. 결국 API가 완성되기 전 까지 '예측'해야 하는건 매한가지였다. 그리고 구현이 완료된 후에 요구사항 변경 등의 이유로 API 스펙이 변경되면 그걸 매번 팔로우하는 것도 지난하게 느껴졌다. 간혹 백엔드팀이 눈치를 보면서 '이 부분 이렇게 바꿔도 되나요?' 물어보고 변경이 진행될 때도 있었는데, 서로가 약간씩 피곤함을 느꼈을 거라 생각한다.
이즈음 해서 팀내 Slack에 프론트엔드가 API 설계를 주도하는 팀에 대한 글이 올라왔다. 흥미로웠지만 너무 급진적이라고 생각했다. 그보다 내 눈길을 끌었던 건 API first design이었다. 이 방식이면 개발 병목 구간도 사라지고, 프론트엔드도 API 설계에 의견을 낼 수 있다. 인프콘 발표 영상 을 보고 인프콘 세션 현장 에도 직접 참여해보면서 우리팀에 이 방식이 도입되기를 갈구하며 이것저것 찾아보고 시도했다.
Code-first design
Code-first design은 코드로 API를 구현하고나면 그때서야 OAS가 생기는 방식이다. 다음과 같은 프로세스를 떠올릴 수 있다.
- (생략 가능) 자유 형식의 API 문서 작성
- 코드 구현
- 문서화 도구 (Swagger, Redoc)
- API 문서 전달
이 방식의 문제는 확정된 스키마가 프론트엔드에게 전달되는 시점이 너무 늦다는 것이다. 프론트엔드는 백엔드의 코드 구현이 끝나야 비로소 Swagger나 Redoc 형태의 URL을 받아볼 수 있다. 이 간극을 좁히기 위해서 1번처럼 코드를 구현하기 전에 약식의 문서를 작성해서 프론트엔드에게 넘겨주는 경우도 있다. 주로 Notion, Confluence같은 팀 협업 노트를 매개로 공유된다. 하지만 이건 이거대로 문제를 낳는다. 1번에서 작성한 문서는 3번에서 생성된 문서와 단절되기 때문에 관리요소가 분산된다. '고작 두 개 아냐?'라고 하기엔 시간이 지날수록 문서간에 싱크가 안 맞아서 발생하는 혼동이 만만치 않은 비용으로 작용하는 걸 숱하게 경험했다.
API first design
API first design은 openAPI specifiaction(OAS)을 SSOT로 두고 여기서부터 작업을 시작하는 방식이다. openAPI 재단(Swagger)에서 프로토콜을 관리하고 있으며, Editor 예시를 보면 이해가 쉽다. yaml 또는 json 형식의 API 스펙 문서다. 개발자는 OAS spec 문서 하나로 요구사항 분석 및 API 설계를 논의할 수 있고 나아가 codegen을 통해 코드 구현까지 가능하다.
- OAS 작성
- 반복적 설계 (토론 + 공유)
- Open API 도구 활용&구현
- API 문서 전달
이제 본격적인 개발에 앞서 OAS를 통해 제대로 된 설계 및 소통이 가능해진다. 또한 OAS를 기반으로 프론트/백엔드가 병렬 작업이 가능해진다. 특히 프론트는 API를 Mocking해서 완성도 높은 테스트 및 구현하는 게 상당히 편리해진다.
실전 도입시의 장애물
백엔드의 적극적인 협조가 필수적이다. API first design를 도입하면 많은 이해관계자들의 업무 프로세스가 바뀐다. 타인의 업무방식까지 내가 이래라 저래라 할 순 없기에 설득에 있어 조심스러웠다. 의견을 몇 번 피력했으나 설득에 성공하진 못했다. DX 차원의 불편함이어서 이것보다 중요한 문제들에 우선순위가 밀렸다. 나는 프론트엔드 팀 내에서 OAS의 필요성을 이해시키는 데에만 그쳤다.
아쉬운대로 백엔드의 도움 없이 해볼 수 있는 방법들을 시도해봤으나 프론트엔드만 codegen 하는 방식은 의미가 없었다. 백엔드가 짠 API 코드가 OAS 규격으로 작성된다는 보장이 없어서 codegen 산출물이 기대한대로 나오질 않는다.
사이드 프로젝트 적용 방식
아쉬움은 회사 밖에서 달랠 수 있었다. 사이드 프로젝트를 시작하면서 API First design 방식을 적용해보자고 백엔드 개발자를 적극 설득했다. 첫 삽을 뜰 때 부터 업무 프로세스를 정해두면 부담이 적고, 백프가 병렬로 작업을 시작할 수 있음 부터 시작해서 OAS를 다뤄보는 게 서로에게 좋은 경험이 될 것임을 어필했다.


OAS를 관리하는 별도 레포가 존재하고, PR을 통해 API 설계 논의 및 피드백을 주고 받는다. 이후 각자의 레포에서 git submodule 형태로 OAS를 가져와서 사용한다. 이를테면 프론트는 Orval을 이용해서 MSW, Zod 등의 형태로 codegen하고 그것을 가져다 사용한다. 안타깝게도 백엔드는 연동 이후 구현 과정까지 자동화하지는 못했다. 이로인해 수동으로 구현한 API 스펙이 OAS와 다른경우가 간혹 있었다. 도식에 있는 빨간색 경로가 이렇게 생겨났다. 만약 백엔드도 codegen을 활용했다면 이런식의 역방향 경로는 사라지고 좀 더 깔끔한 단방향의 흐름이 형성되었을 것이다.
조금 아쉬운 흐름이었음에도 불구하고 너무 편리했다. API 스펙이 변경되어도 큰 비용 없이 대응이 가능했다. 특히 하위호환이 지켜지는 기준의 변경들은 거의 대부분 개발자가 따로 손 볼 필요가 없었다. 그리고 API에 대해 공식적으로 피드백을 할 수 있는 루트가 생겼다는 점도 만족스러웠다. 자동 생성된 코드에 문제가 있을 때 OAS를 수정할 수 있어야 하므로 이 경로는 꼭 필요하다.
마무리
회사에서 API first 방식을 운용해보지 못한 데는 어쩌면 내 탓도 있다. 그 당시 나는 1~2년간 틈틈이 어필했으나 좀처럼 받아들여지질 않아서 지쳤고, 포기했었다. 그런데 어느날 다른 FE 개발자가 BE 개발자를 설득해서는 조금씩 자동화를 구축해나가는 모습을 보고 조금 놀라웠다. 프로젝트가 안정권에 접어들었다는 사실이 설득에 호재로 작용했을 수도 있고, 아니면 단순히 설득 방식의 차이에서 갈렸을수도 있다. 나는 부담을 주지 않겠다는 의도로 조금 미적지근한 태도였던 것 같은데, 차라리 그것보단 유쾌하면서 명료한 방식이 나았겠다고 생각한다.
개인적으로 단일 진실 공급원의 원칙을 진리로 여기고 찬양하는 편이다. 업무에서 겪은 많은 문제들이 이 원칙을 준수하지 못할 때 발생하는 것을 봐왔다. 물론 모든 상황에 이를 적용할 순 없겠지만, SSOT 관점에서 생각해보고 파이프라인을 조금만 틀어보면 답이 나오는 경우가 있었다. 기획문서 관리에 활용한 적이 있었는데 다음에 소개해보도록 하겠다.
