Remote Procedure Call(원격 프로시저 호출)의 약자로, 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 *함수나 **프로시저를 실행할 수 있게 하는 프로세스 간 통신 기술을 말한다.
다시 말해, RPC를 이용하면 프로그래머는 함수 또는 프로시저가 실행 프로그램이 존재하는 로컬 위치에 있든, 원격 위치에 있든 상관없이 동일한 기능을 수행할 수 있음을 의미한다.
Client-Server 간의 커뮤니케이션에 필요한 상세정보는 최대한 감춘다. (=> 언어나 환경에 구애를 받지 않는다! )
Client와 Server는 각각 일반 메소드를 호출하는 것처럼 원격지의 프로시저를 호출할 수 있다.
const res = await fetch("http://example.com/api/v1/user");
const user = await res.json();
console.log("이름: ", user.name, "나이: ", user.age);
console.log(user.asdf + user.qwer);
특정 사이트에 http요청을 보내고, 받은 응답을 json으로 해석해서 자바스크립트 객체를 만들고 그 객체에서 네임과 에이지의 프로퍼티를 출력하고 있다.
유저는 서버에서 온 문자열을 제이슨으로 해석한거라 타입 추론이 전혀 안된다.
유저의 타입은 any이고 타입스크립트에서는 타입 추론을 포기한다는 뜻이다.
any타입은 타입스크립트의 보호를 전혀 받지 못한다.
const res = await fetch("http://example.com/api/v1/user");
const user = (await res.json()) as { name: string; age: number };
console.log("이름: ", user.name, "나이: ", user.age);
console.log(user.asdf + user.qwer);
해결책은 제이슨 파싱한 결과를 as키워드를 사용해서 유저를 any 대신에 name과 age를 가진 오브젝트 타입으로 바꾼다.
하지만 이 방식은 작성자를 너무 신뢰한다는 문제가 있는데,
이 문제를 개선하기 위해 RPC를 정의하여 사용한다.
서버와 클라이언트가 사용할 공통 타입 정하기
서버의 기능을 함수들로 가지고 있는 타입을 정의하는데, 이 타입의 이름은 큰 의미없다.
가독성과 재사용성을 위해 입출력 타입을 따로 만들자.
export interface User {
id: number;
name: string;
}
export interface Post {
id: number;
author: User;
body: string;
timestamp: number;
comments: Comment[];
}
export interface Comment {
id: number;
author: User;
body: string;
timestamp: number;
}
export interface CreatePostRequest {
body: string;
}
export interface CreatePostResponse {}
export interface CreateCommentRequest {
postId: number;
body: string;
}
export interface CreateCommentResponse {}
export interface ReadPostRequest {
postId: number;
}
export interface ReadPostResponse {
post: Post;
}
export interface ReadRandomPostRequest {}
export interface ReadRandomPostResponse {
post: Post;
}
export interface UpdateProfileRequest {
name: string;
}
export interface UpdateProfileResponse {}
export interface ReadProfileRequest {}
export interface ReadProfileResponse {
user: User;
}
export interface Preview {
id: number;
body: string;
timestamp: number;
}
export interface ReadPreviewRequest {}
export interface ReadPreviewResponse {
posts: Preview[];
comments: Preview[];
}
export interface IRpc {
createPost: (req: CreatePostRequest) => CreatePostResponse;
createComment: (req: CreateCommentRequest) => CreateCommentResponse;
readPost: (req: ReadPostRequest) => ReadPostResponse;
readRandomPost: (req: ReadRandomPostRequest) => ReadRandomPostResponse;
readProfile: (req: ReadProfileRequest) => ReadProfileResponse;
readPreview: (req: ReadPreviewRequest) => ReadPreviewResponse;
updateProfile: (req: UpdateProfileRequest) => UpdateProfileResponse;
}