야놀자클라우드 키오스크 서버팀이 TypeScript 인터페이스 하나에서 입력 검증과 API 문서, 코드 문서를 함께 뽑아내는 구조를 정리한 글이다. 치밀한 검증은 개발 비용을 올리고 느슨한 검증은 안정성을 떨어뜨린다는 딜레마를 자동화로 푼다. 마지막에 제약 네 가지를 스스로 짚는다.
핵심 포인트- 주석을 잘 단 TypeScript 인터페이스 하나로 JSONSchema와 Swagger 문서, 코드 문서를 모두 생성할 수 있다.
- 검증 패키지가 여럿 있을 때는 다운로드 추이를 비교해 고르는 방법을 권하며 ajv가 압도적이었다.
- JSON 자체는 스키마를 설정할 수 없어 검증 기능이 없다시피 하고, JSONSchema가 그 규격을 보완한다.
- 인터페이스의 JSDoc 주석에 최솟값과 최댓값을 적으면 그대로 스키마 제약으로 변환된다.
- fastify는 ajv를 내장하고 있어 생성한 스키마를 넘기면 요청 검증이 자동으로 걸린다.
- JSONSchema는 스키마일 뿐이라 커스텀 검증 코드를 넣을 수 없다는 한계가 있다.
상세 정리- 문제의식: 사용자 입력 검증은 안정 운영에 필수인데 꼼꼼하면 비용이 오르고 느슨하면 검증 안 된 곳에서 장애가 난다.
- 도구 선택: Joi와 Yup, validator.js, JSONSchema가 후보였고 다운로드 추이를 비교해 ajv를 골랐다.
- JSONSchema의 역할: 나이는 음수가 안 되고 최대 200까지 같은 규칙을 최솟값과 최댓값으로 정의할 수 있게 해준다.
- ajv의 역할: 그 스키마를 받아 요청이 규격에 맞는지 검사한다.
- TypeScript를 쓰는 이유: 서버를 만들며 모든 부분을 통제하고 싶다면 정적 타이핑이 필요하다는 발표 내용을 인용한다.
- 인터페이스 설계: 요청 추적용 식별자와 인증 헤더, 본문의 숙소 이름과 위경도, 설명을 하나의 인터페이스로 정의한다.
- 주석 규칙: 각 값의 이름을 주석으로 달고 JSDoc 태그 형식으로 최솟값과 최댓값 같은 세부 규격을 적는다.
- 부수 효과: 이렇게 정리해두면 편집기에서 마우스를 올렸을 때 코드와 주석이 함께 뜨고 선언부로 이동할 수도 있다.
- 변환 도구: 인터페이스를 스키마로 바꾸는 도구가 둘 있는데, 하나는 컴파일러 API를 써서 더 정교하지만 느리다.
- 사용성 개선: 두 도구 모두 CLI를 제공하지만 인터페이스 이름을 직접 타이핑해야 해서, 대화형으로 파일과 인터페이스를 고르는 래퍼를 쓴다.
- 변환 결과: 숙소 이름에 설명과 길이 제약이, 위경도에 각각의 범위 제약이 들어가고 선택 값을 뺀 나머지가 필수로 지정된다.
- 검증 연결: fastify가 ajv를 내장하고 있어 생성한 스키마를 넘기는 것으로 요청 검증이 붙는다.
- 인터페이스 구성 취향: 본문과 쿼리스트링, 경로 변수, 헤더를 나눌 수 있지만 합쳐두는 편을 선호한다. 변환 횟수와 생성 파일 수를 줄일 수 있기 때문이다.
- 문서 자동화 1: 다른 프레임워크는 문서 파일을 따로 쓰거나 변수마다 데코레이터를 달아야 하는데, 이 조합은 스키마에서 바로 API 문서가 나온다.
- 문서 자동화 2: 검증과 문서를 위해 붙인 풍부한 주석이 그대로 코드 문서의 완성도를 올려준다.
- 제약 1: 연결고리가 취약하다. 개별 패키지에 대한 정확한 지식이 없으면 제대로 동작시키기까지 진입 장벽이 높다.
- 제약 2: JSONSchema 규격이 아직 draft라 바뀔 수 있고, ajv도 특정 버전 전후로 큰 변화가 있어 프레임워크 지원을 따라가야 한다.
- 제약 3: 변환 도구 하나가 매핑된 타입 접근을 변환할 때 오류가 있어, 원본 변경이 참조 쪽에 전파되는 이점을 요청·응답 객체에서는 쓰기 어렵다.
- 제약 4: 스키마이므로 방문객 나이가 100살 이하여야 한다는 식의 커스텀 규칙은 넣을 수 없다. Joi나 Yup은 가능한 부분이다.
- 운영 연계: 배포 자동화 도구가 배포 과정에서 생성된 문서를 곧바로 스토리지에 올려 항상 최신 문서가 제공된다.
- 결론의 근거: 검증과 문서화가 자동화되지 않으면 누락은 필연이며 인력으로 막기 어렵다는 조언에 공감해, 단점보다 장점이 크다고 본다.
왜 읽나API 문서가 늘 코드보다 뒤처지고 검증 규칙이 여기저기 흩어져 있다면, 인터페이스 하나를 원본으로 삼아 셋을 함께 생성하는 구조와 그 대가를 함께 확인할 수 있다.