현재 우리 회사의 백엔드 서비스는 Express + PM2 기반으로 서버들로 구성되어 있다.(상세한 서비스 인프라 구성은 다음에 설명하겠다!) 최근 서비스 출시에 앞서 MVP 형태의 서비스를 출시했는데, 푸시를 담당하는 백엔드 서버 단에서 Express Payload Too Large 413 에러가 발생했다. 해당 에러가 발생한 원인과 문제 해결 방식에 대해서 작성하려고 한다.
문제상황
문제 상황을 말하기에 앞서서 현재 회사에서 운영중인 서비스는 B2B, B2C 기반의 초등학교 방과 후 시스템을 관리해 주는 시스템이다.
학교 내부에 강사, 코디분들이 주로 사용하며 주요기능으로는 학생, 수업 관리 학교 방과 후 전반의 시스템을 관리해 주는 시스템의 일종이다.
이 많고 많은 기능 중 에서 특히 민감(?)한 부분이 있다면 학교별 전체 학생들에게 수강신청 단체 문자 발송 기능이 있다. 문제도 여기서 발생했는데, 1개의 학교에 총 577명의 학부모님들에게 단체 문자 발송을 하는 기능에서 PayLoadTooLarge Error가 발생했다.
문제원인
PayLoadTooLarge 에러는 이전에 부득이하게 이미지 데이터를 바이너리 형식으로 변환해서 보낼때나 경험했는데, 현재 우리 서비스에서 왜 발생했는지를 확인해 보니 백엔드 Express의 body-parser 미들웨어의 json 파서에서 default로 설정된 payload의 수치인 102,400 Byte 보다 초과된 데이터가 들어온 것이 문제였다.
현재 전체 문자를 발송하는 기능은 크게 3가지로 분류되고 있다. 단체 문자 발송을 할 때, 프론트엔드와 총 3번의 API 통신이 발생하는데, 발송 목록 저장, 실제 단체문자 발송, 발송 결과 업데이트를 하는 과정에서 백 단에서 프론트로 값을 넘겨줄 때, 데이터의 양이 payload 수치를 초과했어서 발생한 이슈였다. 기존에는 하나의 API에서 해당 프로세스를 처리했는데, 열람, 발신 여부 및 단체 문자 발송을 처리하는 과정에 있어서 프론트와 api 로직을 분리시킨 것이 원인이었다.
문제해결
해결 할 수 있는 방식은 크게 2가지라고 생각했다.
- 기존 로직을 사용하고 Express PayLoad의 제한을 늘려주는 것.
- 3번의 호출로 프론트에 발송되는 데이터의 크기를 1번의 API 호출에서 처리하는 방법. (로직 자체를 변경하는 법)
1번은 비교적 간단하게 처리할 수 있다.
/**
* Express 내장 모듈인 json Parser의 limit값을 조정 EX)200kb
* Default 값은 100,240 Byte
*/
app.use(express.json({ limit: '200kb' }));
app.use(express.urlencoded({ limit: '200kb', extended: true }));
위 방식을 적용하면 Request Body에 payload를 파싱 할 때, 데이터 제한을 방지할 수 있다. json parser, urlencoded 사용은 클라이언트에서 요청하는 payload 방식에 따라서 적용시켜서 사용하면 될 것 같다.
2번은 PayLoadTooLarge 에러가 발생하지 않을 상황이 나오도록 설계하면 된다.
프론트 개발자분과 초기 설계 미스와 충분한 테스트(🥲) 없이 급하게 기능을 설계했기 때문에 이런 문제가 발생했지만, 로직단에서 프론트로 대량의 데이터를 한 번에 주고받는 케이스를 최소한으로 하던가, 제한을 두면 이런 이슈를 미연에 방지할 수 있을 거다. 중요한 건 실제 사용자가 얼마라고 사전공지가 되었다면 그에 맞는 충분한 테스트를 하는 것도 방법일 거 같다.
1번의 방식으로 처리를 한다면 임시방편으로 해당 에러를 핸들링할 수 있다. 하지만 사용자가 늘어나서 가용할 수 있는 Data 사이즈가 limit으로 제한 둔 범위를 넘어간다면 또다시 에러가 발생할 것이다. 일부 블로그나 서칭을 했을 때, 1번과 같은 방식으로 해결하는 케이스가 많이 있었는데, 가져오는 데이터의 양이 한정되어 있거나 사이즈를 예측할 수 있는 상황에서는 옳은 방식이라고 생각한다. 하지만 우리 같은 경우에는 가져오는 데이터의 사이즈가 계속해서 커질 우려가 있기 때문에 2번과 같은 방식(하나의 기능에서 API 3개를 주고받던 방식을 하나의 API에서 Service 로직을 호출해서 처리하는 과정)으로 문제를 해결했다.
Node(Express) + Pm2 기반의 서비스에서 PayLoadTooLarge 문제를 핸들링하는 방식에 대해서 알아봤다. PayLoadTooLarge 413 Errors는 모든 HTTP 기반의 통신이 발생하는 서비스에서 발생할 수 있는 항목이기 때문에 사용 중인 서비스 Nginx, Apache, IIS 등 다양한 서비스에 PayLoadTooLarge Default Size 가 몇인지 확인하고 핸들링하면 좋을 거 같다.
참고