REST API 설계의 고민
REST한 API Design에 대한 고민
좋은 아키텍처, 좋은 시스템 디자인을 위한 고민 중 하나
작년 부터 가장 큰 관심을 두고 있는 건, “어떻게 하면 처음부터 좋은 시스템 디자인을 만들 수 있을까?” 이다.
조금만 더 풀어서 얘기하자면, 3~4명 규모의 팀이 처음 시작하는 프로젝트에서 1년 후 50명 규모의 팀이 되더라도 기존 시스템을 전부 갈아엎거나 고통스런 과정을 통해 중대한 기술적인 의사결정을 내리는 일 없이도 시스템을 확장 가능하게 설계할수 있을까? 에 대한 고민이다.
이에 대해 이야기할 부분들은 아주 많지만, 다른 글에서 좀 더 자세히 다뤄보기로 하고, 이 글에서 고민해볼 것은 좋은 API 디자인이 무엇이고 왜 필요할까에 관한 부분이다. 왜 좋은 시스템 디자인에 좋은 API 디자인이 필요할까? 시스템을 마이크로서비스로 나누었을 때 좋은 API 디자인이 설계되어야만 시스템이 커지면서 팀이 나누어지더라도 팀들간에 불필요한 의사소통 에너지 낭비가 없지 않을까 싶고, 마이크로서비스가 아니더라도 클라이언트와 서버간에도 API 디자인이 시스템이 커질수록 점점 중요해지기 때문이다.
이런건 그냥 문서화를 잘하면 된다고 생각할수도 있지만, 생각보다 큰 회사에서도 빠르게 성장하는 프로젝트에서는 문서화가 깔끔하게 이루어지지 않는다. 특히 첫단추를 잘못 끼우면 그 여파가 생각보다 굉장히 오래가고, 심지어 첫단추를 잘 끼웠더라도 중간에 조직개편이 잘못 이루어지거나 물갈이 판이 벌어지면, 처음에 잘 작성되던 문서는 점점 덕지덕지 기운 누더기가 되어버린다. (그리고 그건 그 서비스의 상태를 말해주기도 한다.) 얼떨결에 업무를 맡게된 담당자들은 자신들이 제공하는 API가 정확히 어떤 역할을 하는지도 모르고 그냥 최소한의 유지보수만 하게되고, 기존의 디자인을 따라서 다음 API들을 찍어낸다. API 디자인만 잘못되어있어도 서버에서 단순한 캐시조차 적용하기 힘들어질수 있다는 점은 참 놀랍다.
물론 언제나 그렇듯이 이런건 꼭 하나의 원인만 탓하기는 힘들기에, API 디자인 탓만 할 수는 없다. 그렇더라도 최소한 하나의 원인이라도 제거할 수 있다면, 충분한 가치가 있지 않을까? 그러한 이유로 좋은 API 디자인을 고민해본다.
좋은 API 디자인이란 무엇일까? 내가 생각하기엔, 문서화에 의존하지 않고도 API를 다른 팀이나 외부에서 잘 사용할 수 있어야 하며, 내부적으로 너무 복잡하지 않아야 하고, 각 API들이 역할이 명확히 구분되고, 재사용이 가능해야 하고, 등등… 사실 아직 간단명료하게 정리되진 않는다.
그래서 찾아보던 중, 다음 세션을 찾게 되었다. 꽤 오래전에 지나가듯 본것같은데, 다시 보니까 상당히 깊이 와닿았다. 안보신 분들이 있다면 꼭 한번 보는걸 추천드린다.
평소에 RESTful한 API를 만들어야지 하면서, URI path 이름짓는거에나 신경을 쏟아붓곤 했는데, 그런건 전부 REST한 API가 아니라는 것을 새삼 깨닫는다.
결국 다음 2가지가 빠진 이상 REST한 API가 될수 없는 것이다.
- self-descriptive
- HATEOAS(Hypermedia as the engine of application state)
특히 JSON API는 2가지를 만족하기가 상당히 어렵다. HTML은 공식적인 명세들이 많아서 2가지를 만족시킬 수 있지만, JSON API는 그 형식이 너무 자유롭기에 응답이 무엇을 나타내는지(self-descriptive)나 여기서 다음 동작을 어떻게 진행할수 있는지(HATEOAS)를 나타낼 방법이 너무 제각각이란 것이다.
사내에서만 사용하는 API인 경우에는 개발자들이 그냥 구두로만 합의하거나 문서화로 이걸 해결한다. 문서화를 한다고 해도 사실 중간중간에 API 요구사항이 추가되거나 변경되기 쉽상인데, 그러한 부분들이 문서화에 제대로 반영되지 않는 경우도 빈번하다.
물론 이건 사실 변명의 여지도 많이 있다. 웹, 모바일 클라이언트와 서버가 통신하기위해 외부에도 노출이 되는 API의 경우에는 엄격한 보안심사를 받기도 하고, 그런 경우에 API가 스스로를 너무 드러내는 부분을 오히려 지적받기도 한다. 그리고 영상에서도 마지막에 사내에서 쓰이는 API의 경우에 서버와 클라이언트가 모두 자신의 통제하에 있다면 굳이 REST를 만족시키려 애쓸 필요 없다고도 한다(대신 REST API라고 부르지 말라고…)
하지만, 이걸 핑계로 삼기에는 뒷맛이 쓰다. 지금 내가 유지보수하고 있는 서비스만 봐도, API가 더럽다. 문서화도 완벽하지가 않고, 히스토리를 모르면 난처한 상황을 당하기 일쑤다. 새로 온 개발자는 이런 부분에 적응하는데만도 오랜 시간이 걸리며, 문서를 봐도 잘 모르겠으니 몸으로 부딪혀가며 알아내는 수밖에 없다. 이런 불협화음은 겉으로 드러나지 않으며 조직장들은 왜이렇게 개발이 느린지 답답해한다.
개인적으로는 그런 이유들을 변명으로 삼지 않고자 한다. 보안 심사에는 분명 기준이 있으며, ‘의도치 않게’ 서버의 정보나 개인정보를 노출시키지 않는 것이 중요하지, 어떤 API가 인증된 사용자에게 충분히 허락될법한 정보들을 제공하는 것에 대해 막는게 아니다. (물론 좀 너무하다 싶을 때도 있긴 하다. GraphQL API 보안심사는 아직도 잘 납득이 가질 않는다.)
따라서 사내에서 쓰이는 API들에도 REST한 원칙들을 적용해보고자 노력하는건 충분한 가치가 있다고 생각한다. 어떻게 하면 좋은 API 디자인을 만들 수 있을지는, 계속 공부해봐야 할것 같다.
Conclusion
좋은 시스템 디자인을 위한 고민중 하나로, 좋은 API 디자인의 중요성에 대해 고민해 보았다. REST한 API가 무엇인지에 대해 5년전의 세션 영상을 보며 대부분의 서비스에서 못 지키는 2가지 원칙을 새삼 되새겼다. 앞으로는 API 디자인에 더 신경쓰고, 특히 어떻게하면 보안 기준을 만족시키면서도 REST한 API가 될수 있을지도 계속 고민해보려고 한다.
덧
사실 내가 이것보다 좀더 현실적이며 개발자로서 흥미롭다고 생각하는 것은, “Docs as Code” 방법론이다. 문서화를 개발과 따로 보지않고, 개발 과정, 즉 코드에 포함시키는 것이다. Elixir에서는 ex_doc
과 hex
가 좋은 도구와 예라고 생각되며, swagger같은 도구도 이제는 많이 보편화 되었는데, 좀 더 잘 쓰는 방법을 연구해봐야겠다는 생각이 든다.