deno
mongoDB
error log
에러로그: Connection was forcibly closed by a peer
혹시나 했는데 역시나 겪은 문제입니다.
tl;dr : deno oak에서 delete의 response.body
는 null
로 고정되어 있습니다.
문제: Connection was forcibly closed by a peer
- 서버를 구동하고 삭제요청을 보내면
Connection was forcibly closed by a peer
이라고 응답합니다. Connection was forcibly closed by a peer
응답을 받은 이후부터는 MongoDB Atlas에서는 다른 요청을 거부합니다.
시도: MongoAPI가 문제인가?
가설: MongoAPI 메서드에 문제가 있습니다.
import { config } from 'https://deno.land/x/dotenv@v3.2.2/mod.ts';
import CardRecord from '../model/cards.ts';
class MongoAPI {
async deleteCards($oid: string) {
try {
const result = await fetch(`${this.baseURL}/deleteOne`, {
...this.options,
body: JSON.stringify({
...this.cardBody,
filter: { _id: { $oid } },
}),
});
return result.json();
} catch (error) {
return error;
}
}
}
try {
const mongoAPI = MongoAPI.getInstance();
console.log(await mongoAPI.deleteCards('어떤 id'));
} catch (error) {
console.log(error);
}
MongoAPI에서 삭제 모듈를 독립적으로 실행했는데 문제가 없습니다.
갱신은 정상동작
async function updateCard(ctx: Context) {
const { request, response, cookies } = ctx;
const { id } = helpers.getQuery(ctx, { mergeParams: true });
try {
if (!request.hasBody) throw Error('No Data');
const jwt = await cookies.get('user');
if (!jwt) {
throw Error('인증이 안 되어 있습니다.');
}
const userId = await token.tokenToUserId(jwt);
if (!userId) throw Error('사용자 id가 없습니다.');
const { question, answer, submitDate, stackCount } = await request.body()
.value;
if (!question || !answer || !submitDate || !stackCount)
throw Error('question, answer, data, stackCount 중 값이 1개 없습니다.');
const card = new CardRecord(
question,
answer,
submitDate,
stackCount,
userId,
id
);
response.status = 200;
response.body = await mongoAPI.patchCards(card);
} catch (error) {
response.status = 400;
response.body = {
success: false,
msg: `${error}`,
};
}
}
갱신은 body가 필요한데 정상적으로 동작합니다.
하지만 delete는 body가 딱히 필요한 메서드는 아닙니다.
async function deleteCard(ctx: Context) {
const { response, cookies } = ctx;
const { id } = helpers.getQuery(ctx, { mergeParams: true });
try {
const jwt = await cookies.get('user');
if (!jwt) {
throw Error('인증이 안 되어 있습니다.');
}
const userId = await token.tokenToUserId(jwt);
if (!userId) throw Error('사용자 id가 없습니다.');
response.status = 204;
response.body = await mongoAPI.deleteCards(id);
} catch (error) {
response.status = 400;
response.body = {
success: false,
msg: `${error}`,
};
}
}
가설: DB 서버 보안문제
가설: 보안문제로 특정 요청에 대해서 설정을 풀어줘야 한다.
하지만 DB 서버에서 보안문제가 있었으면 독립적인 모듈로 통신할 때부터 요청 거절이 되어야 합니다. 하지만 문제가 없었습니다.
해결: Deno oak에서 delete의 response body는 null로 고정되어 있습니다.
async function deleteCard(ctx: Context) {
const { response, cookies } = ctx;
const { id } = helpers.getQuery(ctx, { mergeParams: true });
try {
const jwt = await cookies.get('user');
if (!jwt) {
throw Error('인증이 안 되어 있습니다.');
}
response.status = 204;
const msg = await mongoAPI.deleteCards(id);
console.log(msg);
response.body = null;
} catch (error) {
response.status = 400;
response.body = {
success: false,
msg: `${error}`,
};
}
}
이렇게 작성하니까 해결되었습니다. 즉 response.body = null
로 작성하면 삭제 구현이 됩니다.
학습: deno oak에서 delete의 response.body
는 null
로 고정되어 있습니다.
- deno oak에서 delete의
response.body
는null
로 고정되어 있습니다. - 디버깅할 때는 기록하면서 가설을 잘 설정하면 효율적입니다. 무엇이 아닌지 소거할 수 있습니다. 고급스러운 표현을 사용하면 버그 발원지의 면적을 축소할 수 있습니다.
- 에러메시지는 첫줄에 항상 주의합시다.
uncaught application error: TypeError - Response with null body status cannot have body
이런 메시지를 봤는데 나중에 발견했습니다.
백엔드 엔지니어의 고역
파일을 변경하고 API를 메뉴얼 테스트할 때 cookie를 새로 만들어야 한다는 백엔드 엔지니어의 고통을 공감할 수 있었습니다. 요청응답 시간이 3초만 넘겨도 엄청난 세월이 흐른 느낌이었습니다.
다른 고역도 있습니다. 테스트 코드 작성입니다. Deno를 테스트하는 방법이 익숙하지 않아서 그런 것 같습니다. 익숙해지면 쉽게 해결할 수 있을 것 같습니다. 일부 동작하는 테스트도 있지만 일부 작성에 실패한 테스트도 있습니다. 다른 프로젝트 진행하면서 학습할 수 있을 것 같습니다.