— #OpenAPI-Specification #FEConf-2020
나는 계획을 잘 세우지 않는 편이다. "계획을 세워도 그대로 가지 않는 게 대부분이고, 계획만 고집해서는 변화하는 상황에 대처하기 힘들다"는 그럴싸한 변명으로 나의 충동적인 성향을 포장한 지도 오래됐다.
그렇지만, 세상에는 계획이라는 것을 세우고 치밀하게 접근해야만 잘 해내는 일이 분명히 있기 마련이다. 많은 사람이 관여하는 큰 행사일수록 더더욱 그렇다. 나에게는 FEConf 2020에서 발표를 했던 것이 그런 일이었다. 그 어느 때보다도 치밀하게 준비했고, 덕분에 개인적으로 만족스러운 발표를 할 수 있었다. 이 글에서는 컨퍼런스 발표를 준비한 과정이 어땠는지 복기하려 한다.
본격적인 이야기에 앞서, 발표했던 영상을 첨부해본다.
FEConf는 치열한 티케팅으로 유명한 국내 최대 규모의 웹 프론트엔드 개발 컨퍼런스다. 약간(?)의 관종기가 있는 나는 언젠가는 저기서 한 번 발표해보겠다고 오래전부터 생각해왔다. 물론, 팀 채용에 도움이 되겠지 하는 대의명분도 없었던 것은 아니었다.
하지만 티케팅이 치열한 행사에서 발표자로 선정되는 것 역시 쉬울 리가 없다. 아시다시피 자바스크립트 커뮤니티는 넓다. 그곳에서 활동하는 사람이 그렇게 많은데, 다들 하고 싶은 이야기가 얼마나 많겠는가. 커뮤니티 활동을 거의 하지 않는 나도 발표자 신청을 준비하고 있는데, 나 같은 사람이 많을 것 역시 뻔했다. "당신이 하는 생각은, 다른 누군가가 반드시 해봤을 생각이다." 발표 역시 그렇다.
내가 발표자로 선정될 확률이 높을까? 아니었다. 나는 커뮤니티 활동을 하지 않는 편이다. 유명한 사람도 아니다. 이런 행사에 참여해봤던 전례도 없다. 빙글에서 주최하는 테크 톡에 한 번 참여해본 적은 있으나, 그렇게 사람이 많이 왔던 것은 아니었다. 게다가 오류 덕분에 영상 녹화도 실패해, 어떻게 발표를 했는지 아는 사람도 별로 없다. 그러니, 컨퍼런스를 준비하는 사람은 나를 모를 것이다. 그렇다면 내가 무엇을 해야 발표자로 선정이 될 수 있을까? 매력적인 주제, 그리고 내가 발표를 충분히 준비했다는 티가 팍팍 나는 제안서. 이 2개가 필요하다고 생각했다.
먼저, 매력적인 주제란 어떤 주제일까? 발표를 듣는 사람의 입장에서 생각해봤다. FEConf 2020은 온라인으로 진행됐다. 발표는 영상 형태로 공유된다. 바쁜 시간을 투자해 긴 영상을 볼 때, 글로 읽는 것보다 얻어가는 것이 더 적다고 느낀다면 굉장히 허무할 것이다. 또, 그 내용이 시청자의 지식수준과 비슷하거나 떨어진다면, 발표를 보는 것 자체가 시간 낭비처럼 느껴질 것이다.
이렇게 생각하다 보니, '글로 많이 공유되지 않았으며, 내가 많이 경험해본 것'을 발표하자는 것을 기본적인 기조로 삼을 수 있었다. 그러다 보니, 우리 회사에서 프론트엔드 기능을 개발할 때마다 가장 첫 관문을 담당하는 OpenAPI Specification을 발표해보자는 생각을 하게 되었다.
OpenAPI Specification은 자바스크립트 커뮤니티에서 한국어로 글이 많이 공유되지 않았다. 덕분에 온갖 고생을 하기도 했다. 그러다 보니 나에게 노하우가 그래도 어느 정도는 쌓여있는 기술이기도 했다. 그러고 주위 친구들에게 이 기술을 써본 적이 있냐고 물어봤다. 생소하다는 답변만 돌아왔다. 가려운 곳을 잘 긁어주는 기술인데, 사람들에게 생소하다? 이런 주제야말로 발표했을 때 많은 사람들에게 도움이 될 수 있는 주제다. 이렇게 발표 주제가 정해졌다.
하지만 발표 주제를 선정했다고 모든 것이 끝나는 것은 아니다. 발표 주제 선정은 준비 작업의 시작에 불과할 뿐이다. 이제 포장지로 주제를 감쌀 시간이다.
스타크래프트 게임 해설가 엄재경 씨와 스티브 잡스의 공통점은 무엇일까? 포장의 전문가라는 점이다. 엄재경 씨는 별로 중요하지 않을 것 같은 경기도 온갖 의미를 부여하고, 선수 하나하나에 캐릭터를 정해 게임을 보는 사람들을 환호하게 했다. 스티브 잡스야 뭐, '현실 왜곡 장'으로 유명하지 않았나. 그가 직접 발표하는 모든 제품은 이 행성에서 가장 멋있고(그가 즐겨 쓰던 표현이다), 나의 삶을 완전히 바꿔줄 것 같다는 느끼게 했다.
OpenAPI Specification이라는 기술 자체가 주위의 개발자들에게 워낙 생소하다 보니, 나도 이들처럼 포장을 해야겠다고 생각했다. 하지만, 포장은 그냥 한다고 되는 것이 아니다. 명품을 비닐봉지로 포장할 수도 없는 것이고, 마트 상품을 박스로 정성스레 포장할 수도 없는 노릇이다. 이 발표를 듣는 사람, 그리고 그들이 필요로 하는 것을 적확하게 긁어줄 수 있도록 발표를 구성해야 했다.
먼저, 이 발표의 타겟을 설정했다. 어쨌든, OpenAPI Specification은 전통적인 RESTful API를 위한 도구다. 물론 API에는 GraphQL부터 gRPC까지 다양한 대안이 있는 것이 맞다. 하지만 가장 전통적이고, 서버 개발자들이 가장 익숙해하는 것이 RESTful API인 것은 엄연한 현실이다. GraphQL을 쓰자고 설득하는 것이 조금 어려운 것이 아니니 말이다. 그래서 이 발표의 타겟을 "현업에서 RESTful API를 사용하고 있지만 개발에 불만족하는 사람"으로 꼽았다.
그렇다면 불만족하는 사람이 만족할만한 요소는 무엇일까? 여기서 내가 '셀링 포인트'로 꼽은 단어가 타입-세이프(type-safe)다. OpenAPI Specification은 명세 문서를 기반으로 API 함수를 자동으로 만들어준다. 타입스크립트 지원도 해준다. API 함수의 리턴 타입 역시 문서를 기반으로 자동으로 지정해준다. 타입스크립트를 처음 접하는 사람들이 가장 귀찮음을 느끼는 포인트를 잘 해결해주고, API 리턴 타입을 기반으로 타입-세이프한 개발을 할 수 있게 한다는 것이 내가 느낀 OpenAPI Specification의 가장 큰 장점이었다.
하지만 무조건 장점만 얘기하면 오히려 비전문적으로 보일 수 있다. 속된 말로 '약 팔이'나 '기술 장사'처럼 보인다면 그거야말로 최악이다. '아 그런가 보다.. 하지만 실제로 적용하면 뭐 불편하겠지~' 정도의 인상만 남기고 잊히게 되기 때문이다. 다시 보고 싶은 유용한 발표를 하려면 이상적인 시나리오만 전달하는 것이 아니라 현실적으로 겪었던 어려움을 같이 전해 발표를 좀 더 실용적이게 느껴지도록 해야 한다.
이런 생각을 바탕으로 이 발표의 제목을 정했다. 여러 사람들의 의견을 들으며 조금씩 워딩을 조정했고, 덕분에 약간 미디엄식 click bait 같긴 하지만 어쨌든 현실은 잘 반영하고 있는 제목을 확정했다. 그 제목이 바로 여러분도 보셨을 "OpenAPI Specification으로 타입-세이프하게 API 개발하기: 희망 편 vs 절망 편"이었다.
이렇게 발표 재료를 정하고, 타겟을 설정하고, 강조할 지점을 정하면서 발표를 어떻게 진행할지 자연스레 얼개가 짜이기 시작했다. 이제 내가 해야 하는 것은 그 얼개를 구체화해 제안서에 담아내는 일이었다.
전반적인 발표 구성은 '3의 법칙*'에 따라 도입부 - 희망 편 - 절망 편 3개 섹션으로 구성했다. 사람들이 가장 익숙하고 편안해하는 구성이기 때문이다. 여기에 덧붙여 마지막으로 짧은 요약정리 정도로 발표를 마무리하면 되겠다는 생각을 했다.
3의 법칙: 3은 적음의 끝이자 많음의 시작이다. 포인트를 3가지로 요약해 전달하면 내용이 많지도 적지도 않고 적당하게 느껴진다.
코로나19로 인해, FEConf 2020은 온라인으로 진행되었다. 온라인 발표와 오프라인 발표는 아주 다르다. 오프라인 발표는 한 번 세션을 선택하면 다른 세션으로 이동하기 힘들다. 눈치도 보이고, 다른 발표는 이미 자리가 꽉 차 있을 테니까. 하지만 온라인 발표는 지루하거나 내용이 마음에 들지 않으면 언제든지 끌 수 있다. 시청자의 이탈을 고려해, 도입부에는 스토리텔링 요소를 조금 넣었다.
현실 왜곡 장의 대가인 스티브 잡스는 아이폰을 발표할 때 초반부에 아이폰이 시장에서 어느 영역에 있을 것인지, 스크린이 화면을 꽉 채운 이유가 무엇인지, 스타일러스 펜을 쓰지 않는 이유가 무엇인지 등을 기존 제품과의 비교와 유저 스토리를 통해 완벽하게 제시했다. 비슷하게, 프론트엔드 개발자로서 일을 할 때 어떻게 하고 있는지, 그것이 얼마나 고통스러운 작업인지, 그리고 OpenAPI Specification이 그 문제를 어떤 문제를 해결해주는지 설명하는 것을 도입부로 삼는다면 사람들이 충분히 생소한 기술에 대한 발표에 흥미를 느낄 것이라 생각했다.
그래서 아래와 같이 '개발자의 경험'에 초점을 맞춰 도입부의 개요를 완성했다.
1* "여러분은 서버 개발자와 어떻게 API 명세를 공유하나요?"2 * 가장 나쁜 방법: 구두 공유3 * 그나마 낫지만 손이 많이 가는 방법: 위키/Google Docs/...4 * 괜찮긴 하지만 여전히 손이 많이 가는 방법: Postman Collection5* "여러분은 API 함수의 타입을 어떻게 정의하시나요?"6 * 서비스 레이어를 만들어 해당 함수의 리턴 값을 `as`문을 이용해 강제로 할당한다?7 * 그 모델들을 하나하나 정의하기 힘들지 않으신가요?8* OpenAPI Specification9 * Swagger에서 시작되어, 오픈 소스 표준으로 자리잡음10 * [GitHub - OAI/OpenAPI-Specification: The OpenAPI Specification Repository](https://github.com/OAI/OpenAPI-Specification)11 * json 또는 yaml로 API의 스펙을 명시함
처음에는 희망 편을, 단순히 'OpenAPI Specification이 이렇게 좋아요!' 느낌으로 정리하려 했다. '3의 법칙'에 맞춰 개발자에게 좋은 점 / 생태계 / 프론트엔드 개발 편의로 3단 구성을 했고, 이를 사무실에 있던 팀원들에게 쓱 공유했다. 생소한 기술이다 보니 좀 더 프론트엔드 개발자 입장에서 와닿도록 설명해주는 것이 좋겠다는 피드백을 받았다. (해균님 감사합니다...)
피드백을 받은 후, 타겟 청중을 다시 생각하며 프론트엔드 개발 편의를 좀 더 많이 강조하는 쪽으로 구성을 틀었다. 발표의 제목을 생각하며 타입 세이프한 API 개발이 얼마나 편한지 좀 더 풀어서 설명하는 쪽으로 구성했다.
피드백을 거쳐 완성된 '희망 편'의 개요는 아래와 같다.
1* "개발자에게 매력적인 기능을 제공하는 API 명세"2 * 경로, 요청 타입, 요청 헤더/본문, 응답 헤더/본문 등을 json/yaml로 명시할 수 있다.3 * 간단한 예시를 명시할 수 있다.4 * API 리뷰를 돕기 위해, API 스펙의 문서를 보기 좋게 만들어주는 Redoc과 같은 오픈 소스 솔루션도 많다.5 * API 작성을 쉽게 하기 위해, [Swagger Editor](https://editor.swagger.io/?_ga=2.237387712.1936030727.1599824716-106185824.1599824716)나 VS Code용 플러그인을 사용할 수 있다.6* "API 스펙을 기계가 이해할 수 있다"7 * Postman을 사용할 때, 스펙 파일을 import 하면 자동으로 collection을 만들어준다.8 * swagger-codegen / openapi-generator를 사용하면 다양한 템플릿을 기반으로 API 처리 코드가 만들어진다.9 * 서버 사이드: API 통신용 컨트롤러/서비스 코드 자동 생성10 * 클라이언트 사이드: API 통신 클래스 함수 덩어리 자동 생성 (TypeScript 지원: 함수 및 interface 제공)11 * API 개발이 완료되기 전에 사용할 수 있는 간단한 stub 서버도 자동 생성할 수 있음12* 됐고, 프론트엔드 개발자 입장에선 무엇이 편해지나요?13 * fetch / axios 코드를 직접 작성하지 않는다.14 * `fooApi.listBars(1, 30)` 과 같은 형태로 API를 호출한다.15 * URL 오타, get/post 오타 등 다양한 실수에서 자유로워진다.16 * 이때 해당 API들의 타입 역시 `Promise<BarListResponse>` 형태로 정의되고, 해당 타입도 모두 정의돼있으니 타입 정의를 손수 하지 않게 된다.17 * API에 어떤 값이 있는지 확인하기 위해 일일이 호출하지 않아도 된다.18 * Redoc 문서로 확인을 할 수도 있지만...19 * API 메서드에 F12를 눌러 정의로 이동을 몇 번 하다 보면 인터페이스가 제공되므로 문서를 볼 일도 많지는 않다.20 * 실제로 현업에서 작업을 하면서 데이터를 미리 생성하거나 변경해야 할 일이 아닌 이상, 데이터 형식 확인을 위해 Postman을 써야 할 일은 없었다.21 * API 호출 시 발생할 수 있는 데이터 오류를 선제적으로 감지할 수 있다.22 * 개체 필수 필드 누락, 문자/숫자 타입 혼동 등 다양한 문제들이 타입 오류로 감지되므로, 이 문제들이 빌드 타입에 잡힌다.23 * 더 이상 개체 필드명 오타로 고통받지 말자!24 * API 스펙 변경에 따른 런타임 오류도 쉽게 잡을 수 있다.25 * 서버에서 건네준 API 스펙을 openapi-generator로 빌드한 뒤, 타입스크립트 빌드를 돌려보면 문제가 생기는 코드를 빌드 타임에 확인할 수 있다.26 * 서버에서도 openapi-generator로 컨트롤러 코드를 Java와 같은 강 타입 언어로 자동 생성하고 있다면, 약속과 다른 데이터를 넘겨주는 문제는 빌드 타임에 미리 잡을 수 있다.27 * 서버 개발자들도 그렇게 싫어하지 않는다.28 * OAS의 전신인 Swagger가 Java 생태계에서 나온 것이다 보니, Java 지원이 강하다. 컨트롤러 코드 자동 생성 결과 퀄리티도 높은 편. 따라서 서버 개발자들의 OpenAPI Specification에 대한 거부감이 작다.29 * 이는 협업에 있어서 큰 이점이 된다.30 * 결과적으로, **안전한 코드를 빠르게 만들 수 있다.**
사실 OpenAPI Specification은 여러 가지 이유로 실제 적용을 할 때 예상치 못한 귀찮음이 생기곤 한다. 특히 제너레이터가 이런저런 문제를 만들곤 하는데, 이런 점들을 솔직하게 정리하는 식으로 절망 편을 구성했다.
실제 발표 자료를 만들 때 좀 더 구체화를 하기로 다짐하고, 제안서에는 최대한 드라이하게 내가 실제로 겪었던 문제들을 정리했다. 어쨌든 발표자가 다양한 상황을 많이 겪었다는 것을 보여줘 신뢰를 얻자는 것이 처음 생각한 '절망 편'의 방향성이었기 때문이다.
희망 편보다는 약간 대충 정리된 절망 편의 개요는 아래와 같다.
1* "결국 템플릿은 사람이 만드는 것" - 다양한 템플릿이 있지만, 다들 조금씩 하자가 있다.2 * OpenAPI Specification의 모든 기능을 openapi-generator가 100% 지원하지 않는다. (oneOf, 상황에 따라 달라지는 타입 등 고급 스펙을 잘 지원하지 못한다.)3 * `typescript-axios`: TS 개발자가 가장 많이 사용하지만(노드/브라우저 환경 둘 다 사용할 수 있기 때문), 좋아서가 아니라 axios 특성상 앞뒤에서 커스텀하기 쉽기 때문에 많이 사용한다. (그만큼 커스텀할 일이 많이 일어난다는 뜻)4 * `typescript-fetch`: 네이티브 fetch를 사용해서 깔끔할 것 같지만, 메이저 버전업을 할 때마다 구조 전체를 틀어버리는 등 안정적이지 않다.5 * 실제로 fork를 해 사용하고 있으나, 2.x -> 3.x -> 4.x로 올릴 때마다 변경점이 너무 많다 보니 rebase를 시도조차 못하고 있다.6 * enum, Date 등 JS/TS가 다른 언어에 비해 약점을 갖고 있을 때 문제가 생기는 경우가 많다.7 * `date-time`과 `date`를 하나의 `Date` 타입으로 처리하다 보면, 여기저기서 많은 문제가 생긴다.8* "결국 스펙은 사람이 써야 하는 것"9 * 코드에서 역으로 API 문서를 생성하는 툴도 있지만, 퀄리티가 높지 않고 손이 많이 간다.10 * 실제로 서비스에서 사용하면서 겪었던 수많은 문제 사례 소개11 * 모델 하나하나를 전부 다 파일에 json/yaml 개체로 정의하기 때문에, 이런 것을 귀찮아하는 서버 개발자와 함께 작업을 하다 보면 어느 순간 꼬이는 날이 올 수 있다.12 * 익숙치 않은 사람이 만든 문서에는 필수 값 정의가 누락되는 경우가 허다한데, 이 경우 클라이언트 코드에서는 `?.`과 `!.`이 여기저기에 난무하게 된다. 모두의 이해도가 높지 않으면 귀찮은 일을 여러 곳에서 겪을 수 있다는 뜻.
절망 편에서 발표를 끝내면 정말로 이도 저도 아닌 발표가 된다. 이 기술이 괜찮고, 사람들이 많이 썼으면 좋겠다는 방향성을 명확하게 제시하는 것으로 발표를 마무리하는 것을 보여주며, 제안서를 마무리했다.
1* 결론2 * 그래도 OpenAPI Specification은 API 명세를 공유하고 사용할 수 있는 가장 합리적인 방식이다.3 * 손이 많이 가는 타입 정의를 줄여, API 코드를 type-safe 하게 만들어보자.4 * 대부분의 문제는 사람의 손으로 만들어진다. 많은 분들이 OpenAPI Specification을 사용해 실제 사용에서 일어나는 문제들에 대한 솔루션을 많이들 공유하길 바란다.
다행히 얼마 뒤 나는 발표자로 선정이 되었다. 이제 사람들에게 보일 발표 소개글 및 발표 자료 제작 등 본격적인 단계로 넘어가게 되었다.
(2부에서 계속...)