좋은 API는 설명이 필요 없다
좋은 API는 설명이 필요 없다
API를 설계할 때 우리는 종종 문서를 얼마나 잘 쓸지부터 고민한다. 사용법을 자세히 설명하고, 예제를 추가하고, 예외 케이스를 정리하는 식이다. 물론 문서는 중요하다. 하지만 정말 좋은 API라면, 문서를 읽기 전에 이미 어느 정도 사용법이 보인다. 이름, 파라미터, 반환값만 봐도 “이건 이렇게 쓰겠구나”라는 감이 오는 상태다.
이 차이는 단순한 편의성 이상의 의미를 가진다. API를 사용하는 사람은 매번 문서를 찾아보지 않는다. 코드 안에서 빠르게 이해하고, 바로 사용할 수 있어야 한다. 만약 매번 문서를 확인해야 한다면, 그 API는 이미 사용성을 잃고 있다고 볼 수 있다.
직관적인 API의 핵심은 “의도를 드러내는 것”이다. 함수 이름이 무엇을 하는지 명확하게 표현하고, 파라미터는 왜 필요한지 자연스럽게 이해되며, 반환값은 어떤 결과를 기대할 수 있는지 예측 가능해야 한다. 이 세 가지가 맞물리면, 별도의 설명 없이도 API는 스스로를 설명하게 된다.
예를 들어 processData(data) 같은 이름은 너무 많은 해석의 여지를 남긴다. 반면 filterActiveUsers(users)처럼 구체적인 동작과 대상을 함께 표현하면, 이 함수가 무엇을 하는지 훨씬 명확해진다. 이름 하나만으로도 코드의 가독성과 이해도가 크게 달라진다.
파라미터 설계도 마찬가지다. 순서에 의존하는 여러 개의 인자를 받는 대신, 의미 있는 이름을 가진 객체로 묶으면 호출하는 쪽에서도 의도가 드러난다. createUser("john", true, 3)보다 createUser({ name: "john", isActive: true, roleLevel: 3 })가 훨씬 읽기 쉽고, 실수를 줄일 수 있다. 값 자체보다 “이 값이 무엇을 의미하는가”를 코드에 남기는 것이 중요하다.
반환값 역시 단순한 데이터 전달을 넘어 의미를 포함해야 한다. 성공 여부, 상태, 추가적인 정보가 필요한 경우라면 이를 명확한 구조로 표현하는 것이 좋다. 호출하는 쪽에서 반환값을 해석하는 데 추가적인 추측이 필요하다면, 그 API는 아직 충분히 명확하지 않은 상태다.
또 하나 중요한 요소는 일관성이다. 비슷한 역할을 하는 API들이 서로 다른 네이밍 규칙이나 패턴을 사용한다면, 사용자는 매번 새로운 규칙을 학습해야 한다. 반대로 일관된 패턴을 유지하면, 한 번 익힌 규칙을 다른 곳에도 그대로 적용할 수 있다. 이는 학습 비용을 크게 줄여준다.
좋은 API는 사용자의 실수를 줄여주는 방향으로 설계되기도 한다. 잘못된 값을 전달하기 어렵게 만들고, 잘못된 사용 방식이 자연스럽게 드러나도록 하는 것이다. 타입 시스템을 활용하거나, 기본값을 적절히 설정하거나, 명확한 에러 메시지를 제공하는 방식이 여기에 포함된다.
결국 API는 단순한 함수 집합이 아니라, 하나의 인터페이스다. 그리고 이 인터페이스는 사람이 읽고 사용하는 대상이다. 내부 구현이 얼마나 복잡하든, 외부에서 보이는 모습은 최대한 단순하고 명확해야 한다.
그래서 좋은 API는 “설명을 잘 해주는 API”가 아니라, “설명이 필요 없는 API”에 가깝다. 코드를 보는 순간 자연스럽게 사용법이 떠오르고, 별다른 고민 없이도 올바르게 사용할 수 있는 상태. 그 수준에 도달했을 때, 비로소 API는 진짜로 잘 설계되었다고 말할 수 있다.