Request Timeout(408) 에러
❗ 문제 상황
어느날 갑자기 로그인 후 메인 페이지로 넘어가는데 계속 로딩이 뜨더니 에러가 발생하였다.
처음에 에러로 예상한 부분은 두가지였다.
- 로그인 기능 문제
- 호스팅 서비스 문제
먼저 1의 로그인 기능을 확인해 보았다.
로그인 기능은 AWS의 Congnito 서비스를 이용하였고 확인 결과 토큰이 쿠키에 잘 저장되어 있는 것을 보아 로그인 기능의 문제는 아니였다.
그렇다면 AWS 호스팅 서비스(Amplify)에 일시적인 에러이지 않을까? 생각하였지만 처음 에러가 발생한 이후에도 몇번씩 같은 상황이 반복되었다.
이전에 로컬환경에서는 작동이 잘 되었고, 에러가 매번 발생하는 것이 아니라 가끔 발생하기에 코드의 문제보다는 세팅에 문제라고 생각되었다.
앞에서 말했듯이 에러가 매번 발생하는 것이 아니었기에 어떤 에러인지도 파악하기 힘들었다.
그러다가 Request Timeout(408) 에러가 떴다가 사라지는 것을 보았다!!
에러에 대해 찾아보니 웹 브라우저가 웹 서버로부터 응답을 받지 못하는 경우 일정 시간 동안 기다린 후 연결을 종료될때 발생한다고 하였다.
즉, 서버로부터 데이터를 받아오는데에 너무 오래 걸려서 발생한 에러이다.
💡 문제 원인 찾기
서버 없이 클라우드 환경에서 개발하고 있어 DB에 접근하여 데이터 가져오는 부분을 AWS의 Lambda서비스를 이용하였다.
로그인 후 메인 페이지에서 처음 Lambda를 호출하여 데이터를 받아왔기에 Cold Start 때문이라고 예상하였다.
* Cold Start
- 람다함수를 실행하기 위한 부수적인 준비 세팅이 필요하고 이로인해 대략 수초~수십초 정도 코드 딜레이가 발생
- Lambda 최대 단점인 상대적으로 느린 response를 제공
하지만 브라우저의 타임아웃 기준은 기본 1분인데 Cold Start로 1분이 넘어갈리는 없다고 생각하였다.
그 다음으로 의심되는 부분은 서버에 요청을 보낼 때였다.
Next의 SSR로 페이지가 랜더링 되기 전에 요청 3번으로 데이터를 받아오는데, 이 요청이
1
2
3
await 요청 A
await 요청 B
await 요청 C
위와 같은 식으로 요청 A가 끝나면 요청 B를 실행하고, 요청 B가 끝나면 요청 C가 실행되는 방식이였다.
이를 PromiseAll로 한번에 요청을 보내는 방식으로 수정하였다.
1
2
3
4
5
await Promise.all([
요청 A,
요청 B,
요청 C
]);
그럼에도.. 문제는 해결되지 않았고 마지막으로 각 요청에 대한 시간이 얼마나 걸리는지 확인해봐야겠다고 생각하였다.
역시나 요청 하나가 엄청 오래걸리는 것을 확인하였고 백앤드 팀에게 오래걸리는 요청에 대해 말씀드렸다.
💡 문제 해결
백앤드 팀원분이 AWS에서 사용하고 있는 DynamoDB의 스케일링의 문제라고 설명해주셨다.
메인 페이지에서 필요한 데이터를 얻기위해 DB에 갑자기 많은 처리량을 요청하다보니 가능한 처리량보다 처리해야할 양이 많기 때문에 발생하는 것 같다고 하셨다.
현재는 문제가 되는 부분의 요청을 제거하여 에러가 발생하지 않는다.
수정이 필요한 요청에 대해서는 개선 후 말씀해 주신다고 하였다.😊