> 웹 프론트엔드 > JS 튜토리얼 > 청크 버스터즈: 강을 건너지 마세요!

청크 버스터즈: 강을 건너지 마세요!

Linda Hamilton
풀어 주다: 2024-12-02 05:00:10
원래의
854명이 탐색했습니다.

⚠️ 광과민증이 있으신 분들은 생략하셔도 좋을 것 같아요.
아래의 정적 이미지를 참조하세요. 표시등이 정말 빠르게 깜박이기 시작합니다!

Chunk-Busters: Don’t cross the Streams!

인터넷은 어떻게 작동하나요?

제목을 기억하세요... 여기서는 스트림에 대해 이야기하고 있습니다.

프로토콜, 패킷, 순서 지정, ack 및 nack에 대해 이야기할 수 있지만 여기서는 스트림에 대해 이야기하고 있습니다. 아마 짐작하셨겠지만(저는 당신을 믿습니다 =D) 스트림은 바이너리이거나 문자열입니다.

예, 문자열은 전송되기 전에 압축됩니다. 하지만 프런트엔드 및 백엔드 개발에서 일반적으로 관심을 두는 부분은 문자열과 바이너리입니다.

다음 예에서는 JS 스트림을 사용합니다.

Node에는 고유한 레거시 구현이 있지만 앞이나 뒤의 동일한 코드인 스트림을 처리할 수 있는 방법이 있습니다.

다른 언어에도 스트림을 처리하는 방식이 있지만 보시다시피... 스트림을 처리하는 실제 코드 부분은 그다지 복잡하지 않았습니다(복잡한 일이 발생하지 않는다는 뜻은 아닙니다).

예제 문제

여러 소스의 데이터를 소비해야 하는 프런트엔드가 있습니다.

IP/포트를 통해 각 소스에 개별적으로 액세스할 수 있지만 사용 및 제어가 용이하도록 API 게이트웨이 뒤에 배치합니다.

레포

링크에서 저장소를 확인하고 직접 실행하는 방법을 배워서 직접 사용해 보세요.

https://github.com/Noriller/chunk-busters

비디오

따라 볼 수 있는 비디오 버전:

https://youtu.be/QucaOfFI0fM

v0 - 순진한 구현

소스가 있고 가져오고 기다리고 렌더링합니다. 헹구고 반복하세요.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
로그인 후 복사
로그인 후 복사

아무도 그렇게 하지 않을 거라고 생각하실 수도 있겠지만…

이 예에서는 뭔가 잘못되었다는 것이 분명하지만, 여기에 빠지는 것은 그리 어렵지 않습니다.

분명한 점은 느립니다. 각 요청을 실행하고 기다려야 하며, 느리면… 기다려야 합니다.

v1 - 열망하는 버전

각 요청을 개별적으로 기다리고 싶지는 않으시므로 모두 실행한 다음 완료될 때까지 기다립니다.

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
로그인 후 복사
로그인 후 복사

이런 걸 했을 테니까 좋은 거겠죠?

즉, 하나의 요청이 느린 경우를 제외하고는 다른 모든 요청이 이미 완료되었더라도 해당 요청이 완료될 때까지 기다려야 한다는 의미입니다.

v2 - 더 똑똑하고 열성적인 버전

느린 요청이 있을 수 있으므로 모두 실행하고 기다리지만 요청이 오면 가능한 경우 이미 결과에 대해 작업을 수행하므로 마지막 요청이 도착하면 다른 요청도 이미 완료됩니다.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
로그인 후 복사
로그인 후 복사

이것이 최고의 솔루션이겠죠?

음… 뭔가 이상한데요?

v3 - 거짓말을 했어요… 이것이 v1의 모습입니다

v1을 기억하시나요? 네… 다음과 같아야 합니다.

http/1에서 정확히 동일한 엔드포인트로 가질 수 있는 연결 수에는 제한이 있으며, 그뿐만 아니라 브라우저에 따라 다르며 브라우저마다 제한이 다를 수 있습니다.

그냥 http/2만 사용하면 된다고 생각할 수도 있지만… 이것이 좋은 해결책이더라도 여전히 프런트엔드에서 여러 엔드포인트를 처리해야 합니다.

이 문제에 대한 좋은 해결책이 있을까요?

v4 - 스트림에 입장하세요!

v0을 다시 살펴보지만 스트림을 사용합니다…

당신은 똑똑하기 때문에 경고가 조금 망가졌기 때문에 이것을 기대했을 것입니다…

어쨌든... 가져오는 동안 렌더링합니다.


await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
로그인 후 복사
로그인 후 복사
대신 다가오는 스트림을 탭하면 들어오는 데이터 덩어리로 뭔가를 할 수 있습니다. (예! Chat GPT 등이 그렇습니다.)

v0이 이 문제를 처리하는 최악의 방법이라 할지라도 스트림을 사용하면 크게 개선됩니다. 총 대기 시간이 같아도 무엇이든 보여 주어 사용자를 속일 수 있습니다.

v5 - v1, 다시 말하지만 스트림이 있습니다!

http/1 문제는 여전히 문제이지만, 이미 상황을 그대로 확인할 수 있습니다.

네...더 이상은 못 참겠어요...그래서...

v6 -

하나의 API로 모두 관리 가능!

아니면... 어쩌면 그럴 수도 있나요?

프런트엔드에서 너무 많은 것을 관리해야 했습니다. 이를 백엔드로 오프로드할 수 있다면 모든 소스를 처리할 하나의 엔드포인트를 가질 수 있습니다.

이는 프런트엔드 및 http/1 문제의 복잡성을 해결합니다.


await Promise.all([
  fetch1().then(handleResult),
  fetch2().then(handleResult),
  ...
  fetch9().then(handleResult),
]);
로그인 후 복사


// usually we do this:
await fetch(...).then((res) => {
  // this json call accumulate all the response
  // that later is returned for you to use
  return res.json()
})
로그인 후 복사
v7 - 그리고 마지막으로… 하나의 API, 다중 소스 및 스트리밍.

우리는 모든 소스를 호출하고, 데이터를 스트리밍하고, 처리한 다음, 데이터를 있는 그대로 렌더링하는 전면으로 전달하는 하나의 API를 호출합니다.

이에 사용된 코드는 기본적으로 앞면과 뒷면 모두 동일합니다.


await fetchAll();
handleAllResults(results);
로그인 후 복사
네… 바로 그거예요(가장 기본적이고 쉬운 예를 들자면).

버퍼에 들어오는 문자열을 추가하고, 구문 분석하고, 사용 가능한 청크가 있는지 확인하고, 사용하고는 잊어버립니다. 즉, 적은 양의 RAM으로도 한 번에 한 덩어리씩 TB의 데이터를 수신/소비할 수 있습니다.

네가 무슨 생각을 하는지 알겠다...그리고 멍청하고...광기이기도 하다...

무오오오오오오오 웹소켓이 필요해요!

아니요, 우리 집에는 웹소켓이 있어요!

집에서의 웹소켓: ​​다음은?

v8 - 작동하지 않으면 바보일 뿐입니다

당신은 똑똑합니다. 소스가 여전히 데이터를 생성하고 있다면… 일부 변수를 업데이트할 수 있을 것이라고 생각했을 것입니다…

이렇게 하면 하나의 연결을 사용하여 더 많은 데이터를 얻거나 생성되는 내용을 변경할 수 있습니다.

예… 그렇게 하실 수 있을 것 같은데요… 그리고 저는 여러분의 주장에 따라 예를 들었습니다. =디

그래도… 멍청한 생각인데, 실제 제작 환경에서 어디에서 쓸 수 있을지 모르겠네요. MPA와 Ajax 사이의 상호작용은 충분했지만 동일한 서버에 대한 연결이 충분하지 않았던 어색한 JS 단계로 시간을 거슬러 올라가면(일부 브라우저는 2개로 제한됩니다!) 아마도 그럴 수도 있겠죠?

그 외에는 모르겠습니다. 있다면... 알려주세요.

위의 예에서 중앙 보드, 특히 '진행 테두리'에 주목하세요. 계속 업데이트되는 것을 볼 수 있습니다. 네트워크 탭을 열면 GET 연결이 끝나기 전에 절대 닫히지 않는 것을 볼 수 있습니다. 또한 아직 살아있는 연결이 수행하는 작업을 변경하는 여러 다른 요청도 볼 수 있습니다. 이 모든 것이 바닐라 http/1을 사용합니다.

다음은 무엇입니까?

문자열 대 JSON

이 예는 제가 만들 수 있는 가장 기본적인 예입니다. 파싱이 더 쉽기 때문에 JSON 대신 간단한 문자열을 사용하기도 합니다.

JSON을 사용하려면 문자열을 축적해야 합니다(이유로 인해 백엔드 응답을 JSON.stringify해야 합니다).

그런 다음 어디를 구분할지 확인한 다음 해당 값을 구문 분석하거나 진행하면서 구문 분석하세요.

첫 번째로 NDJSON을 생각해 보세요. JSON 배열 대신 새 줄로 객체를 분리한 다음 중단할 위치를 "더 쉽게" 찾은 다음 각각 JSON.parse를 수행하고 객체를 사용할 수 있습니다.

후자의 경우 다음과 같이 구문 분석합니다. 배열에 있다는 것을 알고 이제는 객체입니다. 첫 번째 키입니다. 이제 키 값이고, 다음 키, 건너뛰고, 다음 키… 등등… 수동으로 만드는 것은 사소한 일이 아니지만, wait에서 점프한 후 렌더링으로 렌더링하는 것과 같습니다. 이 모든 것은… 제외하고… 더 작은 규모입니다.

오류 처리

사람들은 예제를 호스트하는 것을 좋아합니다. 이 예제는 직접 실행해야 합니다… 예제를 다른 곳에서 호스트하지 않는 이유가 이제 명확해지기를 바라지만, 또 다른 한 가지는 여기서는 어떤 오류도 예상하지 않는다는 것입니다. 무엇보다 네트워크 오류를 추가하세요...글쎄...

오류는 처리해야 하지만 이로 인해 복잡성이 더욱 가중됩니다.

꼭 사용해야 할까요?

어쩌면… 상황에 따라

라고 말할 수도 있습니다.

스트리밍이 답인 곳도 있지만 대부분의 경우… json을 기다리는 것으로 충분합니다(물론 더 쉬울 수도 있음).

하지만 스트림에 대해 배우면 프런트엔드든 백엔드든 일부 문제를 해결할 수 있는 방법이 열립니다.

프런트엔드에서는 언제든지 이를 사용하여 사용자를 "속일" 수 있습니다. 모든 곳에 스피너를 표시하는 대신, 시간이 걸리더라도 나타나는 대로 표시하고 추가로 표시할 수 있습니다. 사용자가 상호작용하는 것을 차단하지 않는 한... 단순히 스피너를 표시하는 것보다 "느린" 것을 무엇보다 실제로 더 빠르게 느끼는 만들 수도 있습니다. .

백엔드에서는 전면, 데이터베이스 또는 그 사이의 모든 데이터를 있는 그대로 구문 분석할 수 있으므로 RAM을 절약할 수 있습니다. 필요에 따라 데이터를 처리하고 OOM(메모리 부족) 오류를 발생시키는 전체 페이로드를 기다리지 않고 데이터를 보냅니다. GB 또는 TB 단위의 데이터… 물론이죠. 왜 안 되겠습니까?

아웃트로

React가 느린가요? 이 전체 예제 프론트엔드는 React를 사용하여 수행되었으며 모든 깜박이는 "조명"과 관련된 "주요" 작업 외에도 많은 다른 작업이 진행되고 있습니다.

예... 충분히 빠르게 진행하면 예제가 따라잡을 수 없어 정지되기 시작합니다. 하지만 분당 수천 개의 렌더링이 진행되기 때문에... 대부분의 애플리케이션에는 충분하다고 생각합니다.

그리고 언제든지 성능을 향상시킬 수 있습니다. "진행률 경계"의 경우 렌더링에서 일부를 저장해야 하는 경우 연기된 값을 사용하여 더 부드럽게 만들었습니다... "조명"에 대해 이 작업과 기타 성능 향상을 수행할 수 있었습니다. 하지만 제목에 "조명"이 깜박이는 것을 멈추게 할 뿐이고(이렇게 하면 좋은 데모가 될 수 없음) 제목에 있는 "전기" 밑줄도 그만큼 재미있지 않을 것입니다. 입니다.

이 예에서는 모든 "개선 사항"이 이상적이지는 않지만 일반 애플리케이션의 경우... 많은 양을 처리할 수 있습니다. 그리고 더 필요한 것이 있으면 이 경우 다른 솔루션을 사용하십시오.

결론

무기고에 스트림을 추가하세요... 만병통치약은 아닐 수도 있지만 언젠가는 분명 도움이 될 것입니다.

그리고 그걸로 뭔가를 하려고 하는데 도움이 필요하다면… 제게 전화해 보세요. =피

위 내용은 청크 버스터즈: 강을 건너지 마세요!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿