티몬이 여러 API 와 RPC 서버를 호출할 때마다 반복되던 부가 정보 처리를, 자체 유틸 성격의 API 패키지로 묶어 정리한 기록이다. 호출 대상마다 다른 클라이언트 객체를 고르고 파라미터 순서를 맞춰야 하던 것을, 빌더와 메서드 체이닝으로 Request 를 만들고 ApiClient 하나로 실행하는 형태로 바꿨다.
핵심 포인트- 문제는 다양한 API 서버를 호출하려면 그에 맞는 부가 정보를 매번 일일이 확인해야 했다는 것이다.
- 순서에 맞게 파라미터를 넣어야 했고, 상황에 맞는 클라이언트 객체를 골라 써야 하는 것도 부담이었다.
- 해결은 체이닝 방식으로 Request 객체를 만드는 것이다. 서버를 enum 으로 고르고 경로와 파라미터, HTTP 메서드를 이어 붙인다.
- 클라이언트 선택은 ApiClient 안으로 숨겼다. 요청이 외부용인지, 레거시인지에 따라 PhpRpcClient 와 RestApiClient 중에서 내부적으로 고른다.
- 응답은 Response 타입으로 감싼다. 성공 여부와 코드, 메시지, 결과를 함께 담아 예외 종류별로 정적 팩토리를 둔다.
상세 정리- 유틸 클래스는 오픈소스를 쓰는 방법과 직접 만드는 방법이 있는데, 이 글은 티몬이 커스터마이징해 쓰는 쪽을 다룬다.
- 빌더는 URL 에 프로토콜이 이미 포함돼 있으면 서버를 비워두고, 아니면 기본 서버를 지정하는 식으로 분기한다.
- URL 이 비어 있으면 명시적인 메시지와 함께 예외를 던지도록 방어한다.
- 파라미터는 키와 값을 받아 다중 값 맵에 담고, 경로 변수는 별도로 보관한다.
- 메서드는 get 과 post 처럼 의미가 드러나는 이름으로 감싸 내부적으로 enum 값을 설정한다.
- ApiClient 는 단건 실행과 목록 실행을 나눠 제공하며, 결과 타입을 지정하지 않으면 기본으로 문자열 키 맵을 쓴다.
- RestApiClient 의 exchange 는 Request 에서 URL 과 경로 변수, HTTP 메서드, 헤더, 파라미터를 꺼내 실제 호출을 수행하고 결과를 Response 로 감싼다.
- 호출 실패는 세 갈래로 나눠 다룬다. 응답 자체를 못 받은 경우, 응답은 받았지만 유효하지 않은 경우, 그리고 예외 정보가 있는 경우다.
- 사용법은 세 단계로 정리된다. enum 으로 호출할 서버를 정하고, 체이닝으로 경로와 파라미터, 메서드를 지정해 Request 를 만들고, ApiClient 로 실행한다.
- 그 결과 호출부는 어떤 클라이언트를 써야 하는지 몰라도 되고, 서버가 늘어나도 enum 만 추가하면 되는 구조가 된다.
왜 읽나내부 API 와 레거시 RPC 가 섞여 호출부마다 다른 코드를 쓰고 있는 팀에게, 빌더와 단일 진입점으로 호출을 통일하는 구조를 코드로 보여주는 사례.