타입 안전 API
어떤 프론트엔드/백엔드 프레임워크를 선택했든 클라이언트와 서버, 서버와 서버, 클라이언트 기기 간의 통신이 안전하게 이루어지기를 바랄 것입니다.
안전한 통신과 관련해 몇 가지 도구와 표준이 서로 경쟁하는 중입니다.
이들이 무엇이고 어떻게 동작하는지 살펴보기 전에 직접 해결책을 구현할 수 있는지, 그리고 직접 해결한다면 어떤 단점이 있는지 살펴보겠습니다.
예를 들어 현재의 클라이언트와 서버는 100% 타입 안전하지만 언젠가는 HTTP, TCP, 소켓 기반 프로토콜처럼 타입을 사용하지 않는 네트워크 프로토콜로 통신해야 할 수도 있을 것입니다.
그렇다면 어떻게 해야 그 상황에서도 타입 안전성을 유지할 수 있을까요?
타입 안전성을 제공하는 프로토콜을 직접 개발하는 방법이 있습니다.
아래는 직접 구현한 프로토콜의 예입니다.
type Request =
| {entity: 'member', data: Member}
| {entity: 'location', data: Location}
// client.ts
async function get<R extends Request>(entity: R['entity']): Promise<R['data']> {
let res = await fetch(/api/${entity})
let json = await res.json()
if(!json){
throw ReferenceError('응답이 비어있는뎁;;')
}
return json
}
// app.ts
async function startApp() {
let member = await get('member') // 사용자
}
그리고 대응하는 post, put 함수를 구현하여 REST API에 응답하도록 하고, 서버가 지원하는 각 엔티티에 타입을 추가합니다.
백엔드에선 각각의 엔티티 타입에 대응하는 핸들러들을 구현합니다.
핸들러들은 클라이언트가 요구한 엔티티를 데이터베이스에서 읽어 클라이언트로 전송해 주면 됩니다.
하지만 서버 코드가 TypeScript로 구현되지 않았거나, Request 타입을 클라이언트와 서버가 공유할 수 없는 상황이거나, REST를 사용하지 않는다면 어떻게 될까요?
그리고 IOS용의 스위프트 클라이언트나 안드로이드 용의 Java 클라이언트 등 다른 클라이언트도 지원해야 한다면 어떨까요?
이럴 때 바로 타입을 지원하는 코드 생성 API가 필요합니다.
시중엔 다양한 코드 생성 API가 존재하며, 각각은 TypeScript를 포함하여 수많은 언어를 지원합니다.
다음은 몇 가지 예입니다.
- RESTful API용 스웨거(Swagger)
- GraphQL용 아폴로(Apollo)와 릴레이(Relay)
- RPC용 gRPC와 아파치 스리프트(Apache Thrift)
이들 도구는 서버와 클라이언트가 동일한 프로토콜을 사용하도록 하며, 이를 특정 언어에 맞는 구조로 컴파일합니다.
코드 생성 기술 덕분에 클라이언트와 서버 간의 동기화가 깨지는 문제를 피할 수 있습니다.
모든 플랫폼이 같은 스키마를 공유할 뿐 세부적인 구현은 신경 쓰지 않아도 되기 때문입니다.
참고 사이트
https://github.com/swagger-api/swagger-codegen
https://www.npmjs.com/package/apollo
'👶 TypeScript' 카테고리의 다른 글
프로미스로 정상 회복하기 (0) | 2023.01.31 |
---|---|
비동기 스트림 - 이벤트 방출기 (0) | 2023.01.30 |
TSX = JSX + TypeScript (0) | 2023.01.28 |
프론트엔드 프레임워크 - 리액트 (0) | 2023.01.27 |
프론트엔드 프레임워크와 백엔드 프레임워크 (0) | 2023.01.26 |