Slack에서 API를 설계하는 방법
[번역] How We Design Our APIs at Slack
5년보다 전에, 우리는 개발자가 슬랙에서 쉽게 앱을 구축하고 앱 디렉터리에 게시하는 방법을 제공하는 슬랙 플랫폼을 론칭했습니다. 오늘날, 수백만 명의 사용자가 슬랙으로 작업을 가져오고 있으며, 플랫폼에서 885,000명 이상의 활성 개발자가 만든 앱들은 슬랙에서 협업을 더욱 향상하게 시키는 핵심입니다.
수년 동안 우리가 가장 중요하게 생각하는 것은 훌륭한 개발자 경험을 설계하는 것입니다. 눈치채지 못하게 기능 구현을 변경할 수 있지만, 기존 API의 동작 계약을 제거하거나 변경하는 것은 매우 어렵습니다. 그러므로 API 설계를 처음부터 신중하게 생각하는 것이 중요합니다.
API가 잘 설계된다면, 개발자들이 좋아할 것이고 또 그들은 API를 이용하여 가장 창의적인 혁신가가 될 수도 있으며 나아가 막대한 투자를 할 것이고 때로는 API의 전도사가 될 수도 있습니다. 우리는 또한, 플랫폼에서 개발자의 시간과 위험을 감수하는 자원(resource)을 소중하게 생각합니다. 잘못된 API 설계는 최소한으로 채택될 것이며 심지어 좌절감을 초래합니다. 잘못된 API는 기업의 책임이 됩니다.
그렇다고 슬랙이 항상 API를 잘 설계해 왔다고 말하는 것은 아닙니다. 우리가 실수를 저지른다면, 플랫폼은 보다 개발자 친화적 경험을 제공할 수 있을 것입니다. 이러한 실수를 인식하고 개선하는 방법을 파악함으로써 - 심지어 과거의 선택과 일관성을 끈질기게 유지하는 것에 대해 현재 우리가 동의하지 않을 때도 있습니다 - 개발자 경험을 전체적으로 개선할 수 있습니다.
자신만의 API 스타일 가이드를 개발한다고 해서 형편없는 결정을 내리거나 오늘의 열정적인 선택이 내일의 후회가 되는 것을 완전히 막을 수는 없습니다. 그렇지만 솔직하게, 정직하게, 명확하게 결정을 내리는 데 도움이 될 것입니다. 이 글에선 우리의 API 설계 원칙과 더불어 새로운 API 사양, 검토 및 테스트하는 프로세스에 관해 설명합니다. 마지막에는, 여러분의 API 프로세스로 가지고 갈 수 있는 몇 가지 아이디어를 얻을 수 있을 것입니다.
설계 원칙
수년에 걸쳐, API 설계를 가이드하는 몇 가지 원칙을 정했습니다.
1. 한 가지 일을 잘 해내라
API 설계를 시작하면 한 번에 너무 많은 문제를 해결하려고 하는 유혹이 생깁니다. 많은 것을 하려고 할수록, 복잡해지고 이해하기 어려워집니다. 특정 사용 사례를 택하면 단일 설계에 집중하고 API를 단순하게 유지할 수 있습니다. 단순한 API는 이해하기 쉬울 뿐만 아니라 확장, 성능 향상 및 안전성도 향상됩니다. 또한 API에 새로운 기능을 추가하기는 쉽지만 제거하기는 어렵습니다.
슬랙에서는 대부분의 API가 이러한 철학을 따르고 있습니다.
그러나 어떤 경우에는 기존의 복잡한 API를 보다 단순하고 집중적인 API로 나눠야 했습니다.
가장 인기 있는 API 메서드 중 하나인 rtm.start
는 시간이 지나면서 상당히 비용이 비싸졌습니다.
이 메서드는 팀, 채널 및 멤버에 대한 다양한 데이터와 함께 웹 소켓 API에 연결하기 위한 URL을 반환합니다.
팀 규모가 커짐에 따라 이 페이로드는 다루기 어렵고 커져서 개발자들이 감당하기에는 비용이 많이 들었습니다.
소수의 개발자가 이 메서드에서 반환된 데이터를 사용했지만, 개발자 대부분은 웹 소켓에만 연결하기를 원했습니다.
그 결과, 슬랙은 페이로드에 다른 데이터를 반환하지 않고 웹 소켓 API 세션 URL을 반환하는 새로운 API 메서드인 rtm.connect
를 도입했습니다.
이 새로운 메서드는 애플리케이션 개발자와 슬랙이 rtm.start
의 확장 문제를 해결하는 데 도움이 되었습니다.
이 구체적인 이야기에서 얻을 수 있는 한 가지는: 확실하지 않을 때, 어떤 컬렉션에서든 한정된 수의 객체를 적용하거나 페이지화를 하는 것입니다. 정상적이고 합리적인 상한을 정의하는 것은 시기상조인 최적화가 아닙니다. 유기적 성장이 그 경계가 어디에 있는지 보여줄 때, 더 합리적인 것을 포함하기가 훨씬 더 어렵습니다.
2. 빠르고 쉽게 시작하라
개발자가 API를 이해하고 신속하게 시작할 수 있는 것이 중요합니다. API에 익숙하지 않은 개발자가 적절한 시간 내에 “Hello world” 연습을 완료할 수 있도록 보장해야 합니다. 이를 평가하는 데 사용할 수 있는 메트릭 중 하나가 “첫 Hello World까지의 시간”입니다. 슬랙에서는 초급 개발자가 플랫폼에 대해 배우고, 앱을 만들고, 약 15분 이내에 첫 API 호출을 보낼 수 있기를 바랍니다. 목표인 “첫 Hello World까지의 시간”은 실행하는 플랫폼과 개발자 대상의 경험 수준에 따라 달라집니다.
시작하기 가이드, 자습서, 샘플 코드 및 상호작용을 하는 문서는 개발자가 빠르게 시작할 수 있도록 많은 도움을 줍니다. 슬랙에선, 시작하기 가이드와 자습서 외에도 개발자가 브라우저에서 API 엔드포인트를 사용해 볼 수 있는 상호작용을 하는 API 테스터가 포함되어 있습니다. 또한 점점 늘어나는 SDK 컬렉션을 사용하여 코드에 쉽게 연결할 수 있는 여러 언어로 된 코드 조각을 짜기 시작했습니다.
빠른 시작도 좋지만, 개발자가 “Hello World”를 넘어서고 있습니까? 개발자의 경험을 측정하려면 개발자가 달성하고자 하는 다른 목표에도 관심을 기울여야 합니다. 슬랙에서는, 개발자가 적어도 다른 한 명의 사용자에게 앱을 제공하거나 앱이 지시에 따라 메시지를 브로드캐스트하는 것 이상의 작업을 수행할 수 있는 상호 작용 지점에 도달하는 것이 중요하다고 생각합니다.
초기 API 문서를 설계할 때 항상 물어봐야 할 질문은 다음과 같습니다: 현재 구축 중인 플랫폼에는 무엇이 중요합니까?
3. 직관적인 일관성을 위해 노력하라
API가 직관적으로 일관성을 유지해야 합니다. 이는 엔드포인트 이름, 입력 매개 변수(input parameters) 및 출력 응답(output responses)에 반영되어야 합니다. 그리고 개발자는 설명서를 읽지 않아도 API 일부를 추측할 수 있어야 합니다. 또한 그들이 이미 알고 있는 것과 유사하게 작동해야 합니다. 아래는 3가지 수준의 일관성입니다:
- 업계 표준과의 일관성: 업계에서 받아들이는 모범 사례를 최대한 준수해야 합니다.
- 제품과의 일관성: 제품에서 이러한 개념을 기반으로 필드 이름을 선택해야 합니다. 약어, 두문자어 그리고 전문 용어는 피하십시오. 장황하게 말씀하십시오.
- 다른 API 메서드와의 일관성: 다른 API 메서드에서 사용하는 이름은 서로 일치해야 합니다.
API 설계에 대한 자신의 의견을 공고히 하고 기록하는 것이 일관성을 확보하는 가장 좋은 방법의 하나입니다. 특히 API 설계에 대해 옳고 그른 방법이 없을 때는 더욱 그렇습니다. 선택하고 그것을 고수하십시오. 슬랙에서는 API에 대한 일관된 관행과 패턴을 정의하는 포괄적인 API 설계 가이드라인을 작성했습니다.
4. 의미있는 에러를 반환하라
API를 설계하는 또 다른 원칙은 의미 있는 에러를 반환하여 개발자가 문제를 더욱 쉽게 해결할 수 있도록 하는 것입니다. API 설계 중에 엔지니어는 API에 의해 반환되는 에러에 거의 주의를 기울이지 않습니다. 부정확하거나 불분명한 에러는 불만스러울 수 있고 API 채택에 부정적인 영향을 미칠 수 있습니다. 그리하여 개발자는 막혀서 포기할 수 있습니다. 좋은 에러는 이해하기 쉽고 모호하지 않으며 실행 가능하며 문제를 이해하고 어떻게 해결할지 도울 것입니다. API에서 구현 세부 정보, 특히 에러가 빠져서는 안 됩니다.
에러 코드를 반환하는 것 외에도 설명서나 API 응답의 다른 곳에서 긴 형식의 에러를 추가하는 것이 종종 유용합니다. 여기에는 문제 해결 방법이나 추가 정보 링크를 포함하여 사용자가 읽을 수 있는 에러 설명이 포함될 수 있습니다.
개발자를 위한 SDK 및 라이브러리도 구축하는 경우 에러 메시지 및 경고를 “삼키지” 않는 것이 중요합니다. 개발자가 HTTP 헤더 및 원시(raw) 요청 본문(body)와 같이 끔찍한 디버깅 세션에서 유용할 수 있는 모든 것에 액세스할 수 있는지 확인하십시오. SDK가 에러를 해석하여 훨씬 더 유용하게 사용할 수 있다면 좋겠지만, 개발자는 에러에 대한 원시(raw) API 문서를 읽고 SDK 수준에서 에러를 정확히 파악할 수 있어야 합니다. 우리는 때때로 우리 플랫폼의 유용한 에러 메시지를 개발자들에게 도둑질하여 죄를 지기도 합니다.
5. 규모와 성능을 위한 설계를 하라
잘못된 설계는 성능을 제한할 수 있습니다. 그래서 API를 설계할 때 다음과 같은 몇 가지 사항을 확인해야 합니다:
- 큰 컬렉션을 페이지화 하십시오: API는 대규모 데이터 세트를 처리해야 하는 경우가 아주 많습니다. API 호출 한 번으로 수천 개의 항목이 반환될 수 있습니다. 이로 인해 웹 애플리케이션 백엔드에 과부하가 걸릴 수 있으며 심지어 대규모 데이터 세트를 처리할 수 없게 클라이언트가 느려질 수 있습니다. 이런 이유로, 큰 결과 세트를 페이지화 하는 것이 중요합니다.
- 큰 컬렉션 안에 다른 큰 컬렉션에 중첩하지 마십시오: 이 경우 페이지화는 너무 복잡합니다.
- API 비율을 제한하십시오: 애플리케이션을 다운시키는 잘못 행동하는 한 명의 개발자나 제어가 안 되는 코드 루프를 원하지 않을 것입니다. 인프라를 보호하는 동시에 애플리케이션의 안정성과 가용성을 높이려면 합리적인 비율 제한을 추가해야 합니다.
슬랙의 API 중 하나인 channels.list
(지금은 사용 중지)는 채널 목록과 각 채널의 모든 멤버를 반환하는 데 사용되었습니다. — 기본적으로 컬렉션을 다른 컬렉션에 중첩합니다.
슬랙이 만들어졌을 때, 우리는 각 팀이 수백 명의 사용자로 제한될 것이라는 가정을 했습니다.
그러나 제품이 발전하고 성장함에 따라 이러한 가정은 더는 사실이 아니게 되었습니다.
우리는 수만 명의 사용자를 가진 팀을 구성하기 시작했습니다.
그 시점에, 같은 API 호출에서 모든 채널과 각 채널의 멤버를 반환해야 하는 이 구조는 지원하기가 너무 어려워졌습니다.
그래서 그다음 이를 두 개의 서로 다른 간단한 API로 나눴습니다: conversations.list와 conversations.members.
이는 API 성능을 향상할 뿐만 아니라 개발자 경험 향상에도 도움이 되었습니다.
페이지화는 중요할 뿐만 아니라 그 실수의 패턴이 같으므로 페이지화에 대한 주제를 다시 언급합니다. 여러분에게 “그 정도면 충분하다”라는 말은 아마 다른 사람들에게 충분하지 않을 겁니다. API의 즐거움 중 하나는 다른 개발자가 API를 어떻게 사용할지 전혀 모른다는 것입니다. 그러나 특히 같은 API를 사용하는 사용자라면 그들을 볼 수 없게 하는 많은 가능성을 예상하는 것은 여전히 여러분에게 달려 있습니다.
6. 호환성을 깨는 변경 사항 breaking changes을 피하라
마지막으로 제품의 새 업데이트를 출시할 때 API 변경으로 인해 클라이언트의 코드를 깨는 일은 절대 발생하지 않게 하는 것입니다. 그래서, 호환성을 깨는 변경 사항은 무엇입니까? 기존 앱이 변경 전처럼 작동하지 않을 수 있는 모든 변경 사항입니다.
슬랙에서 우리가 따르는 철학은 어제 동작했던 것이 내일도 동작해야 한다는 것입니다. 그렇긴 하지만, 변화는 불가피합니다. 드물지만 예외적인 경우, 우리는 호환성을 깨는 변경 사항을 도입하기로 합니다. 개발자의 원활한 경험을 위해 얼마나 많은 공지사항을 전달하고 어느 정도까지 진행할 것인지는 사용자 수와 작업 공간의 영향, 개발자의 다루기 어려운 정도 등 여러 요인에 따라 달라집니다. 같은 개발자에게 몇 달에 한 번씩 호환성을 꺠는 변경 사항을 처리하도록 요청해서는 안 됩니다.
모든 것이 여러분이 원할 때 항상 깨지는 것은 아닙니다. 예상치 못한 변경 사항과 롤백할 수 없을 때 어떻게 대응해야 하는지 (사과적인) 커뮤니케이션 계획을 세워야 합니다.
설계 프로세스
잘 정의된 API 설계 가이드라인을 넘어서, 슬랙의 모든 팀이 공용 API를 구축할 수 있는 엄격한 API 설계 프로세스도 있습니다. 다음은 우리가 따르는 단계입니다:
1. API 사양 작성하기
일단 팀이 해결하고자 하는 문제를 확실하게 하고 API에 관한 사용 사례를 정의한 후, API 사양을 작성하는 것부터 시작합니다. 이 사양은 개발자가 사용할 API의 다양한 측면에 관해 설명합니다. 여기에는 메서드 이름, 목적, 요청 예제, 응답 및 가능한 에러와 같은 정보가 포함될 수 있으며 API 설계를 통해 충분히 생각할 수 있는 기회를 줍니다. 또한 모든 사람이 우리의 목표가 무엇인지, 그리고 우리의 자원(resource)이 어떻게 노출되는지에 대해 일치하도록 하는 중심 초안 역할을 합니다.
그런 경향이 있는 팀에 속해 있다면 OpenAPI 또는 AsyncAPI와 같은 공개 형식으로 JSON 스키마 및/또는 사양을 작성하면 구현 전에 API 프로토타입 제작에도 도움이 될 수도 있습니다.
개발자를 위해 스키마를 게시하는 것은 자체 툴링을 시작하는 데 도움이 될 수 있지만, 사양을 최신 상태로 유지하기 위한 노력은 쉽지 않습니다. 이것은 우리가 스스로 개선할 수 있는 또 다른 영역입니다.
2. 내부 API 리뷰
코드를 작성하기 전에 설계상의 문제를 파악하는 것이 훨씬 더 효율적입니다. 슬랙에서는 API 사양을 작성한 후, 엔지니어가 #api-decisions라는 내부 슬랙 채널에서 공유합니다. 이것은 API를 구축한 엔지니어가 개발 관계, 엔지니어링, 제품 관리, 개발자 지원, 파트너 엔지니어링 및 보안 담당으로 구성된 여러 직종의 그룹에서 제안에 대한 다양한 관점을 얻을 수 있는 기회입니다. 변경 사항에 대해 더 깊은 논의가 필요한 경우 정기적으로 예약된 API 업무 시간에 검토합니다. 이 회의에서 그룹은 “변경 사항이 기존의 다른 API와 일치합니까?” 및 “API 설계 가이드라인과 일치합니까?” 와 같은 주제를 논의합니다. 또한 이 그룹은 변경 사항에 대한 이름 지정, 사용성, 보안 및 성능 고려 사항에 대해서도 자세히 토론합니다.
3. 초기 파트너 피드백
내부 이해당사자와 함께, 또한 API를 구현할 수 있는 이상적인 개발자인 파트너에게 API 사양 초안을 제공합니다. 이들의 피드백은 API가 해결해야 할 문제를 해결하고 개선이 필요한 API 측면에서 이해하는 데 있어 매우 중요합니다. 코드를 작성하기 전에 이러한 피드백을 받음으로써 API 설계를 빠르게 반복하고 훨씬 더 나은 API를 구축할 수 있습니다.
4. 베타 테스트
새로운 API를 널리 사용하기 전에 선별된 파트너에게 조기 액세스를 제공합니다. 이러한 파트너는 자사 제품에 API를 통합하고 API에 대한 자세한 피드백을 제공합니다. 이를 통해 API 설계를 더욱 개선하고 공개하기 전에 확인된 문제를 해결할 기회를 얻을 수 있습니다.
유연성 유지
자신만의 API 설계 가이드라인을 직접 설정하고 API에 대한 검토 프로세스를 구축하는 데 어려움을 겪었다면, 이제 팀에서 가이드라인을 어느 정도 내재화했을 가능성이 큽니다.
얼마 지나지 않아 예상했던 시나리오와 일치하지 않는 사례가 발생할 것입니다. 여러분은 자신의 좋은 조언에 어긋나는 타협을 할 것입니다. - 때로는 엔지니어링 조직에 도움이 되거나 여전히 실망스러운 일관성을 추구하기 위해. 그러나 때로는 완전히 새로운 종류의 API가 제공되며, 가이드라인 정신에서 영감 을 받아 여러 직종의 일을 하는 파트너를 차단 해제할 수 있습니다. 여러분은 나중에 언제든지 정책을 정할 수 있습니다.
마치며
직관적이고 일관되며 사용하기 쉬운 API를 설계하는 것은 어렵습니다. 이 글에서는 슬랙에서 따르는 API 설계 원리와 설계 과정을 다루었습니다. API를 구축할 때 몇 가지 중요한 점은 API 설계에 대해 미리 생각하고 설계 선택이 의도적이어야 하며 여러 이해 관계자의 피드백을 모으는 것입니다.
우리는 이제 막 시작하는 단계이며, 다음에 무엇을 할 수 있을지 기대됩니다! 여러분이 개발자가 좋아하는 플랫폼에서 작업하고 API 구축을 좋아한다면 함께합시다!