p-limit 란
p-limit은 Node.js 및 브라우저 환경에서 비동기 작업(Promise)의 동시 실행 개수를 제한하기 위해 사용하는 초경량 라이브러리입니다.
자바스크립트의 Promise.all()은 모든 작업을 동시에 실행하려는 성질이 있습니다. 하지만 실제 운영 환경에서는 서버의 자원(CPU, 메모리)이나 외부 API의 허용량(Rate Limit) 때문에 무한정 동시에 작업을 돌릴 수 없습니다.
p-limit은 이때 "한 번에 최대 N개만 처리해!"라고 명령하는 교통경찰과 같은 역할을 합니다.
왜 Promise.all만으로는 부족할까?
우리가 1,000개의 데이터를 마이그레이션해야 한다고 가정해 봅시다.
- Promise.all 사용 시: 1,000개의 네트워크 요청이나 DB 쿼리가 동시에 발생합니다. 이는 곧 커넥션 풀 고갈, 타임아웃, 혹은 상대 서버의 차단으로 이어집니다.
- p-limit 사용 시: 1,000개의 작업을 던져두어도 설정된 수치(예: 5개)만큼만 먼저 실행합니다. 하나가 끝나면 대기열(Queue)에서 다음 작업을 하나 꺼내어 실행하는 방식을 반복합니다.
작동 원리
- 제한기 생성: pLimit(concurrency) 함수를 호출하여 "동시 실행 허용 수"를 설정한 함수를 생성합니다.
- 작업 래핑: 비동기 함수를 해당 제한기 함수로 감싸서 실행합니다.
- 큐 관리: 내부적으로 대기열을 유지하며, 현재 실행 중인 비동기 작업이 설정값보다 적으면 대기열에서 꺼내 실행합니다.
사용 예시 (Usage Examples)
// 기본 사용법
import pLimit from 'p-limit';
const limit = pLimit(3); // 동시에 3개만 실행
const input = [1, 2, 3, 4, 5];
// limit()으로 감싸진 함수들은 즉시 실행되지 않고 순례를 기다립니다.
const tasks = input.map(item => limit(() => someAsyncTask(item)));
const results = await Promise.all(tasks);
// 예시 2 : 데이터 마이그레이션
import pLimit from 'p-limit';
import db from './db.js';
const limit = pLimit(10); // DB 커넥션을 고려해 동시 쿼리를 10개로 제한
async function migrateData(oldData) {
const migrationTasks = oldData.map(item => {
return limit(async () => {
// 1. 공통 정보 insert
// 2. 상세 정보 insert
console.log(`Processing ID: ${item.id}`);
return await db.insertNewDeal(item);
});
});
// 모든 태스크를 던져도 실제로는 10개씩만 차례대로 돌아감
await Promise.all(migrationTasks);
console.log('마이그레이션 완료!');
}
요약 및 결론
- 언제 쓰나요? 대량의 비동기 작업을 처리할 때, 서버나 API에 무리를 주지 않아야 할 때.
- 장점: 매우 작은 크기(Zero dependencies), 직관적인 사용법, 안정적인 리소스 관리.
- 주의사항: 제한 수치를 너무 낮게 잡으면 전체 처리 시간이 길어지고, 너무 높게 잡으면 p-limit을 쓰는 의미가 없어집니다. 환경에 맞는 적절한 N값을 찾는 것이 중요합니다.
관련 개념 (Related Concepts)
- 동시성 (Concurrency): 여러 작업이 겹치는 기간에 실행되는 것. (자바스크립트는 싱글 스레드지만 비동기 I/O를 통해 동시성을 구현함)
- 병렬성 (Parallelism): 여러 작업이 물리적으로 정확히 같은 시점에 실행되는 것.
- 처리량 (Throughput): 단위 시간당 처리하는 작업의 양. p-limit은 처리량을 안정적으로 유지하게 돕습니다.
- Rate Limiting: API 서버 등이 과부하를 막기 위해 요청 횟수를 제한하는 것.
'Nodejs' 카테고리의 다른 글
| Node.js 의 개념과 동작원리 (0) | 2025.05.27 |
|---|