81강 실습 자료 없음
'81강. [Pain] 대규모 삭제 작업 시 발생하는 수많은 요청을 하나로 묶기'에 관하여 실습 자료가 없는데 혹시 의도된 것일까요?
Answer 2
0
안녕하세요, Yoon Robin님!
문의해주신 '81강. [Pain] 대규모 삭제 작업 시 발생하는 수많은 요청을 하나로 묶기' 차시와 관련하여 답변드립니다.
네, 말씀해 주신 내용이 맞습니다. 해당 강의는 별도의 실습 자료가 제공되지 않는 것으로 의도된 구성이 맞습니다.
학습 진행에 혹시나 도움이 될까 하여 강의 대본 자료를 함께 첨부해 드립니다!
학습에 참고해 주시기 바라며, 추가로 궁금하신 점이나 더 필요하신 사항이 있으시다면 언제든 편하게 문의해 주세요. 감사합니다!
지난 78강에서 우리는 MSW를 통해 서버 없는 테스트 환경을 구축하고 비동기 로직을 완벽하게 검증하는 법을 배웠으며, 이를 통해 우리의 코드는 개별 기능 단위에서 아주 높은 신뢰성을 확보하게 되었습니다. 하지만 실제 업무 현장은 그리 호락호락하지 않은데, 단일 요청의 성공과 실패를 넘어 수많은 데이터를 한꺼번에 조작해야 하는 이른바 규모의 문제가 우리를 기다리고 있기 때문입니다. 예를 들어 관리자 페이지에서 수백 명의 회원을 한꺼번에 선택하여 삭제하는 대규모 작업을 수행해야 할 때, 우리가 이전에 배운 방식대로 각각의 유저에 대해 독립적인 삭제 요청을 보내도록 설계할 수 있습니다. 그러나 이러한 방식은 곧 우리 앱과 서버에 엄청난 시각적이고 기술적인 고통을 안겨주는 네트워크 폭풍으로 변하게 되며, 오늘은 이러한 비효율이 발생하는 근본적인 원인과 그 고통의 실체를 하나씩 파헤쳐 보는 시간을 갖겠습니다.
가장 먼저 우리가 마주하게 될 첫 번째 고통의 단위는 브라우저와 서버 사이의 통신 효율성 문제입니다. 현대의 대부분 브라우저는 HTTP/1.1 규격을 기준으로 동일 도메인당 동시 연결 수를 보통 6개로 제한하고 있습니다. 만약 관리자가 100명의 유저를 한 번에 삭제하려 하고 우리가 이를 100개의 개별 요청으로 보낸다면, 브라우저는 물리적인 제약 때문에 한 번에 6개 정도의 요청만 동시에 보낼 수 있게 됩니다. 이로 인해 나머지 94개의 요청은 네트워크 탭에서 'Pending' 상태로 하염없이 앞선 요청이 끝나기만을 기다리는 현상이 발생합니다.
이러한 현상을 우리는 흔히 워터폴(Waterfall) 현상이라고 부르며, 이는 단순히 전체 삭제 프로세스를 매우 느리게 만들 뿐만 아니라 브라우저의 가용 자원을 독점하여 다른 중요한 요청들까지 가로막는 심각한 병목 현상을 초래하게 됩니다. 수백 개의 요청을 개별적으로 보내는 비효율적인 삭제 로직을 코드로 살펴보면 다음과 같습니다.
/**
* [Pain Scenario] 수백 개의 요청을 개별적으로 보내는 비효율적인 삭제 로직 예시입니다.
* userIds 배열을 순회하며 하나씩 mutate를 호출하는 방식은 네트워크 폭풍의 주범이 됩니다.
*/
const handleDeleteUsers = (userIds: number[]) => {
// 아이디 배열을 단순 반복문으로 돌리며 각각 요청을 트리거합니다.
userIds.forEach(id => {
/**
* [고통의 시작] 이 코드는 아이디가 100개라면 100번의 HTTP 통신을 발생시킵니다.
* 브라우저의 6개 동시 연결 제한 때문에 나머지 94개는 대기 상태에 빠지게 됩니다.
*/
deleteUserMutation.mutate(id);
});
};
이러한 상황에 대해 최신 HTTP/2 환경에서는 멀티플렉싱을 지원하니 여러 요청을 동시에 보내도 괜찮지 않느냐고 생각할 수 있지만, 이는 어디까지나 네트워크 레이어의 전송 효율이 좋아지는 것일 뿐 어플리케이션 레이어에서의 부하와 데이터베이스 트랜잭션 비용은 전혀 줄어들지 않는다는 점을 명심해야 합니다. 서버는 여전히 100개의 요청을 각각 독립적으로 수신해야 하고 100번의 인증 로직을 거쳐야 하며 100번의 로그를 일일이 남겨야 합니다. 특히 데이터베이스 관점에서 보면 이러한 방식은 커넥션 풀을 순식간에 고갈시키는 주범이 됩니다.
하나의 트랜잭션으로 묶어 한 번에 처리할 수 있는 작업을 100번의 독립적인 작업으로 쪼개서 보내는 것은 마치 마트에서 물건 100개를 사면서 매번 물건 하나를 집을 때마다 계산대로 달려가 따로 결제하는 것과 마찬가지입니다. 이 과정에서 발생하는 불필요한 입출력 부하는 서버 전체를 마비시킬 수 있는 위험을 내포하고 있으며, 클라이언트의 무심한 반복문이 서버의 자원을 어떻게 갉아먹는지 보여주는 가상 코드는 다음과 같습니다.
/**
* 서버 측의 고통을 시뮬레이션한 가상 코드입니다.
*/
app.delete('/api/users/:id', async (req, res) => {
/**
* 개별 요청마다 인증, 로깅, DB 커넥션 점유가 반복적으로 일어납니다.
* 50번째 요청에서 네트워크 에러가 발생한다면 원자성은 이미 파괴된 상태가 됩니다.
*/
const result = await db.users.delete(req.params.id);
res.json(result);
});
무분별한 요청 폭발은 사용자 경험에서도 치명적인 페인 포인트를 발생시키는데, 그중에서도 가장 골치 아픈 문제는 바로 '원자성(Atomicity)'의 결여로 인한 데이터 정합성의 붕괴입니다. 여기서 원자성이란 "전부 성공하거나, 혹은 전부 실패하거나(All-or-Nothing)"라는 원칙을 의미합니다. 100개의 개별 요청을 보내면 네트워크 상황이나 서버 상태에 따라 일부는 성공하고 일부는 실패하는 상황이 발생할 수 있는데, 전부 삭제되거나 아예 삭제되지 않아야 하는 이 원칙이 지켜지지 않아 어정쩡하게 절반만 삭제된 데이터는 복구조차 불가능한 재앙이 됩니다.
또한 시각적으로도 리스트 항목들이 하나씩 툭툭 끊기며 사라지거나 화면이 덜컥거리고, 100개의 로딩 인디케이터가 화면을 뒤덮으며 동시에 돌아가는 기괴한 광경을 연출하게 됩니다. 사용자는 삭제가 완전히 끝난 것인지 왜 일부는 여전히 남아있는지 알 수 없는 혼란에 빠지게 되는데, 이는 시니어 개발자가 결코 용납해서는 안 되는 설계의 실패라고 할 수 있습니다.
결국 우리가 직면한 이 거대한 고통의 핵심은 네트워크 통신의 높은 비용과 원자성의 결여에 있으며, 수백 개의 작은 요청을 하나의 큰 요청으로 묶어서 보내는 전략을 사용한다면 우리는 이 네트워크 폭풍을 평화로운 잔물결로 바꿀 수 있습니다. 오늘 우리는 대규모 데이터 조작 시 발생하는 수많은 요청이 왜 우리를 괴롭히는지 그 페인 포인트의 실체를 낱낱이 파헤쳐 보았으며, 이제 이 지독한 성능 문제를 해결하기 위해 우리만의 특수 요원을 투입할 차례입니다.
다음 강의에서는 비효율적인 네트워크 폭풍을 단 한 번의 깔끔한 통신으로 해결하는 솔루션인 Query Batching 전략을 통한 서버 부하 최소화에 대해 알아보겠습니다. 수백 번의 계산대 방문을 단 한 번의 카트 결제로 바꿔버리는 시니어의 마법 같은 최적화 기법을 기대해 주시길 바라며 오늘도 정말 고생 많으셨습니다. 그럼 다음 강의에서 뵙겠습니다.
0
안녕하세요, 인프런 AI 인턴입니다. Yoon Robin님.
강의를 수강하시면서 실습 자료가 누락되어 혼란을 겪으셨을 것 같습니다. 해당 ‘81강. [Pain] 대규모 삭제 작업 시 발생하는 수많은 요청을 하나로 묶기’ 강의에 대한 실습 자료가 없다면 의도적인 것인지, 혹은 단순히 누락된 것인지 강사님께 직접 문의하시거나 강의 페이지의 ‘강의 Q&A’ 섹션을 통해 확인하는 것도 좋은 방법입니다.
비슷한 사례를 겪은 다른 수강생들이 강사님의 빠른 조치로 문제를 해결한 경우가 많이 있습니다. 이에 따라 유사한 이전 질문 답변을 참고하시면 좋습니다:
- 63,65 중복 - 강의 자료 관련 문제 해결 사례입니다.
위 링크를 통해 비슷한 질문을 확인하시고, 강의에서 필요한 자료가 있으면 강사님께 요청하셔서 해결하실 수 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
섹션 18 PRD generator sub agent 관련 질문입니다.
0
5
1
ReactScriptExample 관련 질문
0
7
0
소스코드즘 부탁드립니다.
0
6
1
소리가 안 나네요. (이 질문은 인프런에서 하는것이 맞죠 하하)
0
12
1
MVP PRD를 Sonet5.0에서 AUTO모드로 만들었어요 결과가 맞는건지 모르겠습니다 조언부탁드립니다..
0
20
2
몽고디비 접속의 건
0
12
2
mcp 서버 설치
0
14
2
알려주세요.
0
7
1
Context engineering?
0
23
2
36~37강
0
18
1
해당 강의 영상이 안나옵니다.
0
28
2
cursor mcp 사용
0
33
2
타입 에러 관련 질문입니다.
1
19
1
Starter kit 작업 중 질문
0
41
2
프롬프즈 줄바꿈 문의
1
30
2
문의드려요
0
39
1
6장 ORM 에 관하여 질문
0
31
1
안녕하세요 한번 더 문의드립니다.
0
46
4
git 초기설정하고 Next Js 설치하는게 너무 어렵습니다.
0
27
1
62강 실습자료가 잘못되었습니다.
0
32
1
27강 Context내 RSC 사용 관련 문의
0
111
3
문의관련 문의
0
104
2
[실습] 80강 없음
0
106
2
63,65 중복
0
144
1

