본문으로 건너뛰기

falsy를 조심합시다.

· 약 3분
arch-spatula

서버에서 body 유효성을 검증한 로직을 잘 못 짜는 일이 있었습니다. request body에 0을 검증할 때는 존재 여부로 검증합시다.

tl;dr 0을 숫자로 전달하면 0은 falsy해서 에러를 던졌습니다.

// ...생략
const { question, answer, submitDate, stackCount } = await request.body().value;
if (!question || !answer || !submitDate || stackCount === undefined)
// stackCount의 0은 falsy 하기 때문에 undefined으로 활용
throw Error('question, answer, submitDate, stackCount 중 값이 1개 없습니다.');
// ...생략

백엔드 엔지니어링 할 때는 테스트 코드를 정말 성실하게 작성하고 테스트 방법론을 열심히 공부합시다.

위가 최종 형태이지만 그 전에는 에러를 recipe for disaster

무슨일이 있었는가?

// ...생략

const { question, answer, submitDate, stackCount } = await request.body().value;
if (!question || !answer || !submitDate || !stackCount)
throw Error('question, answer, submitDate, stackCount 중 값이 1개 없습니다.');

// ...생략

원래는 이렇게 되어 있었습니다. 만약 stackCount가 falsy한 값이면 에러를 던지도록 했습니다. status code는 406으로 했습니다.

{
"question": "정답은 1",
"answer": "1",
"submitDate": "Sun Jun 25 2023 14:57:20 GMT+0900 (한국 표준시)",
"stackCount": "0"
}

그리고 구현 확인할 때는 JSON 택배는 위처럼 보냈습니다.

이렇게 보내면 문제가 없는 이유가 0은 문자열이기 때문에 falsy하지 않습니다.

{
"question": "정답은 1",
"answer": "1",
"submitDate": "Sun Jun 25 2023 14:57:20 GMT+0900 (한국 표준시)",
"stackCount": 0
}

하지만 프론트엔드에서 작업할 때는 이렇게 보냈습니다. 0은 falsy해서 406에를 돌려줬습니다.

역시 프론트엔드에게 백엔드를 시키면 신뢰할 수 없습니다(시키는 사람은 더 신뢰할 수 없을 것입니다. 여기서 함정은 시킨 사람이 본인이라는 거).

그래서 undefined으로 바꿨습니다. 하다하다 이런 실수도 해보네요. ㅂㄷㅂㄷ...