출시 날, 컨퍼런스 날, 갑자기 프로그램이 정상 작동하지 않는 경험 있으신가요?
얼마 전 정부과제 최종 감리 날 제가 만든 프로그램이 작동하지 않는 아찔한 일이 있었습니다.
로그인 후 대시보드 화면이 나와야 하는데 무한 로딩이 걸려버립니다. 무한까지는 아니었지만 api 요청 후 평균 1분 20초 정도 후에 response가 왔었으니, 사용자 입장에서는 무한이겠죠? 백엔드 서버를 재기동 시키면 다시 정상적인 속도로 돌아왔지만 새로고침으로 재요청할 때마다 50초, 1분 30초, 2분 기하급수적으로 늘었습니다.
이미 감리에서 프로그램이 무한 로딩걸려 작동하지 않았기 때문에 버스는 떠나갔고, 소 잃고 외양간 고치기겠지만 뒤늦게라도 문제를 해결하기 위해 서치해 봤습니다.
문제를 파악해 보니 처음 대시보드에서 요청하는 쿼리가 상당히 오래 걸리는 상황. 초기에 만들 때 문제 없이 잘 작동했고 완성했다 싶어 최종 감리 때까지 더 이상 손대지 않고 있었습니다. 그런데 그동안 DB에 데이터가 축적되었고 계산식이 많았던 한 쿼리의 속도가 상당히 느려져있었습니다.
문제 사항
1. 첫 요청은 성공적. 다음 요청부터 2배 이상의 시간이 소요된다.
2. 이런 상황에서는 다른 api 요청도 모두 pending 상태에서 멈춘다.
의심되는 부분
1. 대시보드는 실시간 동작을 위해 10초 마다 새로운 데이터를 받는다.
2. 데이터를 요청하고 응답을 받을 때까지 15초가 소요된다. (query 계산식 때문에)
3. 아직 응답을 받지 못한 상태에서 새로운 요청이 간다.
근데 아무리 10초 마다 새로운 요청을 보낸다해도 비동기 요청인데 왜 다른 API의 요청이 pending 되는건지 의문입니다.
여러모로 찾다가 DB connection 개념을 알게 되었습니다.
제가 개발하던 백엔드 서버의 구조는 쿼리를 보낼 때마다 DB connection을 시도합니다. connection 후에 응답을 완료하면 connection을 close 합니다. 클라이언트(프론트)에서 첫 화면 대시보드를 그릴 때 총 4개의 쿼리 요청이 있습니다. 근데 첫 쿼리 요청이 15초 걸립니다. 그리고 응답을 받지 못한 상태에서 10초 후, 실시간 구현을 위해 또 4개의 쿼리가 요청됩니다. 이런 경우 connection이 끊기는 수보다 연결되는 수가 많아지고 이것이 누적되면서 병목현상이 생기는 것으로 추측했습니다.
이쪽으로 방향을 잡고 찾다 보니 위 같은 현상을 막기 위한 connection pool 이라는 방식이 존재한다는 것을 알아냈습니다.
커넥션 풀(connection pool)
커넥션 풀은 수용 가능한 connection을 미리 할당하고 이를 pool에 담아두는 방식입니다.
쉽게 말하면 connection 개수를 정하고 미리 연결해두는 개념입니다. 코드로 보면 이해가 빠릅니다.
참고로 npm의 postgres용 pool 라이브러리를 사용했습니다.
import { Pool } from "pg";
export const client = new Pool({
// DB 정보
user: POSTGRESQL_USER,
password: POSTGRESQL_PASSWORD,
host: POSTGRESQL_HOST,
database: POSTGRESQL_DATABASE,
port: POSTGRESQL_PORT),
// connection pool 설정
max: 25, // connection 최대 개수 설정
connectionTimeoutMillis: 30000, // 30초 동안 연결이 안될 경우 오류 반환
idleTimeoutMillis: 10000, // 클라이언트가 유휴 상태일 때 10초 후 연결 종료
maxUses: 7500, // 7500번 connection 후 새로운 연결로 교체
});
이렇게 설정하니 미리 준비된 25개의 connection 덕분에 오래 걸리던 쿼리 외에 다른 api 요청은 병목 현상 없이 정상 작동했습니다. 오래걸리던 쿼리는 최적화를 시도하다가 실패했고, 대신 무한정 요청되지 않도록 30초 기다린 후 응답이 없으면 connection을 강제 종료하도록 설정했습니다.
maxUses나 max connection의 수 같은 경우 시나리오 기반으로 테스트 후에 추정 값을 구할 수 있습니다. 저는 요청되는 api 수와 각 api 응답까지 걸리는 시간을 대충 고려해서 위와 같이 설정했습니다.
아래 참고한 블로그에 connection pool 실험 내용도 있으니 관심있다면 꼭 한번 읽어보시는 것을 추천드립니다.
참고 자료
https://jojoldu.tistory.com/634
'프로그래밍⚡️ > server' 카테고리의 다른 글
proxmox 설치하기 (feat: ventoy usb) (0) | 2025.01.24 |
---|---|
맥북으로 우분투 부팅 USB 만들기 +usb 강제 초기화 (1) | 2024.05.04 |
자작 나스 만들기 - 소프트웨어편(헤놀로지) (0) | 2023.08.13 |
자작 nas 만들기 - 하드웨어편 (0) | 2023.08.12 |
크론탭을 이용한 반복 로직 구현 (0) | 2023.07.31 |