July 22, 2024
새로운 기술을 도입하는 건 언제나 도박이다. 특히 팀 전체가 영향을 받는 기술이라면 더욱 그렇다. ts-rest 도입 과정에서 겪은 실패를 통해 배운 것들을 정리해본다.
우리 팀은 TypeScript를 사용하면서도 API 경계에서는 타입 안전성을 포기하고 있었다.
// 프론트엔드가 기대하는 타입
interface User {
id: number;
name: string;
email: string;
}
// 실제 서버 응답 (email이 userEmail로 변경됨)
{
"id": 1,
"name": "John",
"userEmail": "john@example.com" // 💥 런타임 에러
}배포 후에야 발견되는 이런 문제들이 반복됐다. 뭔가 해결책이 필요했다.
여러 대안을 검토했다. tRPC는 REST와 거리가 멀었고, GraphQL은 러닝커브가 컸다. OpenAPI Generator는 계약 우선 개발이 어려웠다.
ts-rest는 기존 REST API 구조를 유지하면서도 타입 안전성을 확보할 수 있었다. 중간 다리 역할을 할 수 있을 거라 생각했다.
// 계약을 한 번 정의하면
const contract = c.router({
getUser: {
method: 'GET',
path: '/users/:id',
responses: {
200: UserSchema,
},
},
});
// 서버와 클라이언트 모두 타입 안전팀에 제안했다. 반응은 긍정적이었다.
점진적 도입 계획을 세웠다. 내가 담당하는 API부터 적용하고, 기존 API는 천천히 마이그레이션하기로 했다. 모두가 동의했다.
실제 적용 단계에서 문제가 드러났다.
당장 처리해야 할 업무들이 있었고, ts-rest 학습은 계속 미뤄졌다. 계약을 수정하면 에러가 빵빵 터졌는데, 이게 장점임을 알면서도 팀원들에게는 부담이었다.
결국 서버의 일부, 클라이언트의 극히 일부에만 적용됐다. 두 가지 방식이 공존하는 애매한 상태가 되었다.
서버와 클라이언트를 함께 전환해야 가치가 나오는데, 처음부터 함께할 동료를 확보하지 못했다.
“제가 먼저 확인해볼 테니까 관심 있으신 분은 말씀주세요”
바쁜 와중에 누가 선뜻 나서겠는가. 시작부터 최소 팀(이 경우에는 서버 1명, 클라이언트 1명)을 구성했어야 했다.
점진적 도입도 최소 가치는 있어야 한다. 서버에서만 사용하는 건 기존 NestJS 데코레이터를 다른 방식으로 표현하는 것에 불과했다.
// 기존 NestJS
@Get('/users/:id')
async getUser(@Param('id') id: string) { ... }
// ts-rest (서버만 사용)
// 이게 뭐가 더 나은가?
contract.getUser: {
method: 'GET',
path: '/users/:id',
...
}진짜 가치는 클라이언트에서 타입 안전하게 호출할 때 발생하는데, 그 부분이 빠졌다.
향로님의 블로그를 읽고 깨달았다. 내게 부족했던 건 ‘신뢰 자본’이었다.
기술의 장점만 설명했을 뿐, 실제로 이 도구가 팀원들의 일상적인 고통을 어떻게 해결해줄지 보여주지 못했다. “타입 안전성”보다 “어제 그 버그를 막을 수 있었다”는 구체적인 증명이 필요했다.
“바쁜 시간이 지나면 배우자”
바쁜 시간은 끝나지 않는다. 처음부터 학습 시간을 공식적으로 확보했어야 했다.
MVP 단위로 도입하자
처음부터 팀을 구성하자
구체적인 문제를 해결하자
학습 시간을 확보하자
내게는 ts-rest를 사용한 API들이 테스트하기 쉽고 안정적인 코드다.
하지만 팀원들에게는 통일성 없이 작성된, 수정하기 어려운 코드일 뿐이다. 내가 만든 ‘좋은 코드’가 팀에게는 새로운 레거시가 되어버렸다.
ts-rest는 일부에만 적용되어 있으며 기존 API들은 변경되지 않았다.
우리 팀은 여전히 클라이언트-서버 간 타입 불일치로 고통받고 있다. API 인터페이스 변경은 두려운 작업이다.
점진적 접근이 맞았는지, 더 과감하게 뛰어들었어야 했는지는 아직도 모르겠다. 신중한 접근이었지만, 결과는 어정쩡했다.
이 실패에서 배운 가장 큰 교훈:
나에게 좋은 코드가 팀에게도 좋은 코드는 아니다.
기술 도입은 기술만의 문제가 아니다. 팀이 함께 이해하고, 함께 유지보수할 수 있어야 진짜 좋은 코드다.
새로운 기술을 도입하려는 누군가에게.