PromiseRPC를 러프하게 구현해놓으면 호출 하는 입장에서는 상관 없고, 프론트엔드에 집중 작업한 이후 서버와 통신하는 코드로 깔끔하게 교체할 예정이다.
rpc.ts 파일을 수정할때 마다 cp명령어를 통해서 프로젝트 안으로 복사해주는 세팅을 하려고 한다.
쉘 스크립트란 간단히 말하자면 Unix커맨드등을 나열해서 실행하는 것이다. 언제 어떤 조건으로 어떠한 명령을 실행시킬 것인가, 파일을 컨텐츠를 읽어 들일 것인가, 로그 파일을 작성하는 것 등을 할 수 있다.
- 터미널에 치는 명령어를 미리 써놓고 나중에 실행 가능.
cprpc.sh 파일을 만들어 아래와같이 작성한다.
#!/bin/bash //shebang
cp rpc.ts frontend/src/rpcgen.ts
//cd <원본 파일> <복사된 파일>
-> rpc.ts 파일을 frontend/src/rpcgen.ts로 복사한다
#! 은 2 Byte 의 매직 넘버 (Magic Number) 로 스크립트의 맨 앞에서 이 파일이 어떤 명령어 해석기의 명령어 집합인지를 시스템에 알려주는 역할을 합니다.
#! 바로 뒤에 나오는 것은 경로명으로, 명령어들을 해석할 프로그램의 위치를 나타냅니다.
가장 일반적으로 사용되는건 #!/bin/bash 이며 앞으로 나올 명령어들을 주석을 제외하고 순서대로 실행시킵니다.
만약 경로가 정확하지 않다면 bad interpreter 가 발생하고 다른 인터프리터를 지정하면 문법 오류로 실패합니다.
결론적으로 스크립트 파일에서 어떤 프로그램으로 해당 파일을 실행시킬 지 결정합니다.
이후 맥에서는 권한설정때문에 다음과같은 명령어를 실행해주어야 한다.
chmod 755 cprpc.sh
첫자리 7은 모든권한 두번째 5는 그룹, 아더는 읽기/실행 권한만 부여한다.
chmod 는 change mode 의 약어로 시스템의 모드(권한) 를 바꾸는 명령어 이다.
파일의 권한은 읽기(r) 4 / 쓰기(w) 2 / 실행(x) 1 로 분류된다.
각 숫자의 합에 따라 권한이 결정된다.
ex)
7 => 모든 권한
5 => 읽기 / 실행 권한
또한 각 자리수마다 의미가 다르다. (ex 755)
첫번째는 소유자(user) 권한 / 두번째는 그룹 사용자(group) 권한 / 세번째는 기타 사용자(other) 권한이다.
import { Post, PromiseRpc, User, Comment } from "./rpcgen";
const server: PromiseRpc = {
//서버 변수에 PromiseRPC의 기본 틀을 잡는다.
createPost: async (req) => {
//데이터 추가
posts.push({
body: req.body,
comments: [],
id: posts.length,
author: user,
timestamp: Date.now(),
});
return {}; //그냥 값을 반환하는것 처럼 보여도 외부적으fh Promise가 붙음
},
createComment: async (req) => {
//댓글추가
const post = findPost(req.postId);
post.comments.push({
id: post.comments.length,
author: user,
body: req.body,
timestamp: Date.now(),
});
return {};
},
readPost: async (req) => {
return { post: findPost(req.postId) };
},
readRandomPost: async () => {
return { post: findPost(Math.floor(Math.random() * posts.length)) };
},
readProfile: async () => {
return { user };
},
readPreview: async () => {
//미리보기 구현
const comments: Comment[] = [];
posts.forEach((p) => {
p.comments.forEach((c) => {
if (c.author.id === user.id) {
comments.push(c);
}
});
});
return { posts: posts.filter((p) => p.author.id === user.id), comments };
},
updateProfile: async (req) => {
user.name = req.name;
return {};
},
};
export default server;
const user: User = { id: 3, name: "내 이름" }; //유저라는 정보로 로그인이된 상태.
const user2: User = { id: 4, name: "다른 유저" };
const posts: Post[] = [
//더미데이터
{
id: 0,
body: "내용1",
author: user,
timestamp: Date.now() - 2345432,
comments: [],
},
{
id: 1,
body: "내용2",
author: user2,
timestamp: Date.now() - 2131231231,
comments: [{ body: "댓글2", author: user2, timestamp: Date.now(), id: 2 }],
},
{
id: 2,
body: "내용3",
author: user2,
timestamp: Date.now(),
comments: [{ body: "댓글1", author: user, timestamp: Date.now(), id: 1 }],
},
];
function findPost(postId: number): Post {
//아이디로 글을 찾고 없으면 예외를 던지는 함수.
const post = posts.find((p) => p.id === postId); //그냥 find만 쓰면 undefined 에 대한 타입처리를 항상 해줘야되어 함수로 따로 뺴줌.
if (!post) {
throw Error("no post");
}
return post;
}