서버 작업이 수정되었습니다.

Linda Hamilton
풀어 주다: 2024-10-21 06:22:02
원래의
670명이 탐색했습니다.

서버 액션은 클라이언트 코드를 줄이고 서버와의 통신이 필요한 상호작용을 단순화하기 위한 아이디어로 등장했습니다. 개발자가 더 적은 양의 코드를 작성할 수 있게 해주는 탁월한 솔루션입니다. 그러나 다른 프레임워크에서의 구현과 관련하여 간과해서는 안 되는 몇 가지 과제가 있습니다.

이 기사에서는 이러한 문제에 대해 이야기하고 브리사에서 어떻게 해결책을 찾았는지 설명합니다.

서버 액션이 필요한 이유는 무엇입니까?

서버 작업이 제공하는 기능을 이해하려면 서버와의 통신 방식을 검토하는 것이 유용합니다. 아마도 서버와의 각 상호 작용에 대해 다음 작업을 수행하는 데 익숙할 것입니다.

  1. 브라우저 이벤트 캡처(클라이언트)
  2. 데이터 정규화 및 직렬화 (클라이언트)
  3. 서버에 요청(클라이언트)
  4. 엔드포인트 API에서 요청 처리(서버)
  5. 필요한 데이터로 응답(서버)
  6. 서버의 응답을 기다렸다가 처리합니다(클라이언트)
  7. 클라이언트의 데이터 업데이트 및 변경 사항 렌더링(클라이언트)

이 7가지 작업은 각 상호작용마다 반복됩니다. 예를 들어, 10개의 서로 다른 상호 작용이 있는 페이지가 있는 경우 매우 유사한 코드를 10번 반복하여 요청 유형, URL, 전송된 데이터 및 고객 상태와 같은 세부 정보만 변경합니다.

익숙한 예는 다음과 같습니다
A:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

그리고 서버에서:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});
로그인 후 복사
로그인 후 복사
로그인 후 복사

클라이언트 번들 크기 증가... 그리고 개발자들의 좌절감.

Server Actions have been fixed


좌절한 개발자

서버 작업의 작동 방식

서버 작업은 이러한 작업을 원격 프로시저 호출(RPC)으로 캡슐하여 클라이언트-서버 통신을 관리하고 클라이언트의 코드를 줄이고 서버의 논리를 중앙 집중화합니다. :

  1. 브라우저 이벤트 캡처(RPC 클라이언트)
  2. 데이터 정규화 및 직렬화(RPC 클라이언트)
  3. RPC 서버에 요청(RPC 클라이언트)
  4. 데이터를 가지고 서버에서 액션을 실행(RPC 서버)
  5. 옵션 1:
  • 서버에서 렌더링하고 스트리밍을 클라이언트로 보냅니다(RPC 서버)
  • 변경 사항이 표시되도록 스트림 덩어리를 처리합니다. (RPC 클라이언트)
  1. 옵션 2:
  • 필요한 데이터를 회신하고 서버 스토어에서 클라이언트 스토어로 속성을 전송합니다(RPC 서버)
  • 변화를 듣고 있던 신호가 매장의 변화에 ​​반응하도록 하세요(RPC 클라이언트)

여기에서는 Brisa RPC가 모든 작업을 수행합니다.

Server Actions have been fixed


원격절차 호출

이것은 서버 구성요소의 코드입니다:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

여기서 클라이언트 코드는 서버 구성 요소이므로 개발자가 작성하지 않습니다. onInput 이벤트는 디바운스 후에 수신되어 클라이언트 RPC에 의해 처리되는 반면 서버 RPC는 "작업 신호"를 사용하여 해당 상점 속성에 등록된 신호가 있는 웹 구성 요소를 트리거합니다.

보시다시피 이렇게 하면 서버 코드가 크게 줄어들고 무엇보다도 클라이언트의 코드 크기가 상호 작용할 때마다 증가하지 않습니다. RPC 클라이언트 코드는 이러한 상호 작용이 10개이든 1000개이든 상관없이 고정된 2KB를 차지합니다. 이는 클라이언트 번들 크기가 0바이트 증가 즉, 증가하지 않는다는 의미입니다.

Server Actions have been fixed


클라이언트 번들 크기에 0바이트

게다가 재렌더링이 필요한 경우 서버에서 수행되고 HTML 스트리밍으로 반환되므로 이후 클라이언트에서 이 작업을 수행해야 했던 기존 방식보다 사용자가 변경 사항을 훨씬 빨리 확인할 수 있습니다. 서버 응답입니다.

이런 식으로:

  • 개선 사용자 경험(UX)
  • 향상 개발 경험(DX)

Server Actions have been fixed


행복한 개발자

Brisa Server Actions와 다른 프레임워크의 차이점

1. 캡처할 이벤트 수

React와 같은 다른 프레임워크에서는 이벤트 대신 form onSubmit의 일부인 오직 작업에만 집중했습니다.

클라이언트 코드를 추가하지 않고 서버 구성 요소에서도 처리해야 하는 비형식 이벤트가 많기 때문에 이것이 문제가 됩니다. 예를 들어 자동 제안을 수행하기 위한 입력의 onInput, 무한 스크롤을 로드하기 위한 onScroll, onMouseOver 호버 등을 수행합니다.

Server Actions have been fixed


애플리케이션이 예상보다 대화형입니다

2. 서버 작업에 대한 더 많은 HTML 제어 기능 보유

또한 많은 프레임워크에서는 HTMX 라이브러리를 서버 액션에 대한 매우 다른 대안으로 여겼습니다. 그러나 실제로는 HTML에 추가 속성을 추가함으로써 더 많은 잠재력을 가질 수 있도록 서버 액션과 결합할 수 있는 아주 좋은 아이디어를 가져왔습니다. RPC 클라이언트는 이전에 본 debounceInput과 같은 것을 고려할 수 있습니다. 또한 요청하는 동안 스피너를 표시하거나 RPC 클라이언트에서 오류를 처리할 수 있는 표시기와 같은 다른 HTMX 아이디어도 있습니다.

Server Actions have been fixed


HTMX 아이디어

3. 우려사항의 분리

React에 Server Actions가 도입되면서 새로운 패러다임 전환이 ​​발생하여 많은 개발자들이 작업 시 멘탈 칩을 바꿔야 했습니다.

저희는 이를 웹 플랫폼에 최대한 친숙하게 만들고 싶었습니다. 이렇게 하면 서버에서 직렬화된 이벤트를 캡처하고 해당 속성을 사용할 수 있습니다. 약간 다른 유일한 이벤트는 이미 FormData를 전송하고 e.formData 속성을 갖는 onSubmit이지만 그럼에도 불구하고 나머지 이벤트 속성은 상호 작용 가능합니다. 다음은 양식 재설정의 예입니다.

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

이 예에는 클라이언트 코드가 전혀 없으며 서버 작업 중에 CSS를 사용하여 표시기로 제출 버튼을 비활성화하여 양식을 두 번 제출할 수 없도록 할 수 있습니다. 서버에서 작업을 수행한 후 e.formData를 사용하여 양식 데이터에 액세스한 다음 동일한 이벤트 API를 사용하여 양식을 재설정합니다.

정신적으로 웹 플랫폼 작업과 유사합니다. 유일한 차이점은 모든 서버 구성 요소의 모든 이벤트가 서버 작업이라는 점입니다.

이렇게 하면 "사용자 서버" 또는 "클라이언트 사용"을 넣을 필요가 필요하지 않습니다. 구성요소 더 이상.

모든 것이 서버에서만 실행됩니다. 유일한 예외클라이언트에서 실행되는 src/web-comComponents 폴더에 대한 것이며 이벤트는 정상입니다.

Server Actions have been fixed


두 개의 다른 세계, 그러나 일치

4. 이벤트 전파

Brisa에서 서버 액션은 마치 DOM 이벤트인 것처럼 서버 구성 요소 간에 전파됩니다. 즉, 서버 액션에서 서버 컴포넌트 소품의 이벤트를 호출한 다음 상위 서버 컴포넌트의 서버 액션이 실행되는 등의 작업을 할 수 있습니다.

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

이 경우 상위 컴포넌트에서 onAfterMyAction 이벤트가 실행되고 서버에서 액션을 수행할 수 있습니다. 이는 여러 서버 구성요소에 영향을 미치는 서버 작업을 수행하는 데 매우 유용합니다.

Server Actions have been fixed


전파작업

4. 두 세계의 소통

특히 지난 몇 주 동안 X(이전의 Twitter)에 대한 여러 토론 이후 웹 구성 요소에 대한 눈살을 찌푸리게 되었습니다. 그러나 HTML의 일부이기 때문에 다음과 같은 여러 가지 이유로 Server Actions와 상호작용하는 가장 좋은 방법입니다.

  1. 서버에서 모든 웹 구성 요소 이벤트캡처하고 클라이언트-서버 통신을 생성할 수 있습니다. 예 <웹 구성요소 onEvent={serverAction} />. 웹 구성 요소 내부의 모든 이벤트는 서버 논리를 넣지 않고 클라이언트 논리만 있기 때문에 매우 강력합니다. 웹 구성 요소를 사용할 때 서버에서 간단히 서버 작업을 수행할 수 있습니다.
  2. HTTP 프로토콜스트리밍에서 하이퍼텍스트 전송(HTML)을 위해 설계된 용도로 사용할 수 있습니다. 서버 작업에서 렌더링하면 웹 구성 요소의 모든 속성이 업데이트되고 RPC 클라이언트의 비교 알고리즘을 사용하면 많은 노력 없이 웹 구성 요소가 업데이트됩니다. Brisa의 속성신호 웹 구성 요소의 내부 부분을 다시 렌더링하지 않고도 반응하게 만드는 것입니다. 다른 프레임워크의 이 프로세스는 매우 복잡해져서 RPC 서버가 HTML 대신 유선을 통해 JSON 또는 JS를 처리해야 하므로 스트리밍 구현이 더욱 복잡해집니다.

웹 구성 요소에서 속성을 사용하려면 웹 구성 요소를 사용하지 않고 서버에서 클라이언트로 데이터를 전송하는 것과 같은 방식으로 직렬화가 필요하므로 두 가지를 모두 사용하면 관리할 추가 직렬화가 없습니다.

참고: HTML을 스트리밍하고 diffing 알고리즘으로 처리하는 방법은 관심이 있으시면 다른 기사에서 설명한 내용입니다.

Server Actions have been fixed


유선 스트리밍의 하이퍼텍스트

5. 새로운 개념: 동작 신호

브리사에서는 서버 액션에 더욱 강력한 기능을 부여하기 위해 새로운 개념을 추가했는데, 이 개념을 "액션 시그널"이라고 합니다. "Action Signals"의 아이디어는 2개의 매장이 있고, 하나는 서버에 있고 다른 하나는 클라이언트에 있다는 것입니다.

왜 매장이 2개인가요?

기본 서버 스토어 라이브요청 수준에서만 가능합니다. 그리고 클라이언트에게 표시되지 않는 데이터를 공유할 수 있습니다. 예를 들어 미들웨어가 사용자를 설정하고 모든 서버 구성 요소의 민감한 사용자 데이터에 액세스하도록 할 수 있습니다. 요청 수준에 따라 생활하면 각 요청자체 저장소가 있고 어떤 데이터베이스에도 저장되지 않습니다. 요청이 완료되면 기본적으로 종료됩니다.

한편, 클라이언트 스토어에서는 소비 시 각 속성신호인 스토어입니다. 업데이트되면 해당 신호를 듣고 있던 웹 구성 요소가 반응합니다.

그러나 "액션 시그널"의 새로운 개념은 요청 이상으로 서버 스토어의 수명을 연장할 수 있다는 것입니다. 이렇게 하려면 다음 코드를 사용해야 합니다:

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

이 transferToClient 메소드는 서버 데이터를 공유하여 클라이언트 스토어에 신호로 변환됩니다. 이런 방식으로 서버에서 재렌더링을 수행할 필요가 없는 경우가 많으며, 간단히 서버 작업을 통해 해당 신호를 듣고 있던 웹 구성 요소의 신호에 반응할 수 있습니다.

이번 매장 이전으로 서버 스토어의 수명이 바뀌었습니다.

초기 서버 컴포넌트 → 클라이언트 → 서버 액션 → 클라이언트 → 서버 액션 렌더링...

그래서 요청 수준에서만 생활하는 것에서 영구적으로 생활하고, 페이지 간 탐색과 호환됩니다.

Server Actions have been fixed


두 월드(서버/클라이언트) 간 데이터 공유

예:

app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});
로그인 후 복사
로그인 후 복사
로그인 후 복사

이 예에서는 오류 저장소 속성의 수명을 연장하여 클라이언트에서 사용하지 않고 서버 작업에서 재사용한 다음 마지막으로 서버 작업을 다시 렌더링합니다. 이 경우에는 민감하지 않은 데이터이므로 암호화할 필요가 없습니다. 이 예제 코드는 모두 서버에서 발생합니다. 심지어 다시 렌더링하는 경우에도 사용자는 서버 RPC가 스트리밍으로 HTML 청크를 보내고 클라이언트 RPC가 이를 처리하여 비교하고 표시하는 서버에서 이 렌더링 후에 오류를 보게 됩니다. 사용자에게 피드백을 주기 위해 오류가 발생했습니다.

6. 민감한 데이터만 암호화

서버 작업 내에서 렌더링 수준에 존재했던 일부 변수가 사용되는 경우 보안 수준에서 Next.js 14와 같은 많은 프레임워크는 이 데이터를 암호화하여 다음에서 사용되는 데이터의 스냅샷을 생성합니다. 렌더링 시간. 어느 정도 괜찮지만 항상 데이터를 암호화하면 계산 비용이 발생하며 항상 민감한 데이터는 아닙니다.

Brisa에서는 이 문제를 해결하기 위해 다양한 요청이 있습니다. 초기 렌더링에서는 값이 있고, 서버 작업에서는 이 요청에 있는 값을 캡처할 수 있습니다.

<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>
로그인 후 복사
로그인 후 복사

이는 어떤 경우에는 유용하지만 항상 그런 것은 아닙니다. 예를 들어 Math.random을 수행하는 경우 초기 렌더링과 서버 작업 실행 간에는 확실히 다릅니다.

<input
  onInput={(e) => {
    // debounce
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fetch("/api/search", {
        method: "POST",
        body: JSON.stringify({ query: e.target.value }),
      })
        .then((res) => res.json())
        .then((data) => {
          setState({ data });
        });
    }, 300);
  }}
/>
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

이것이 우리가 서버 스토어에서 클라이언트 스토어데이터를 전송하기 위해 "액션 시그널"이라는 개념을 만든 이유입니다. > 개발자암호화할지 암호화할지결정결정

할 수 있습니다.

때때로 서버 작업에서 데이터베이스를 쿼리하는 대신 관련 암호화가 필요한 경우에도 초기 렌더링에 이미 존재하는 데이터를 전송하고 싶을 수도 있습니다. 이렇게 하려면 다음을 사용하면 됩니다.
app.post("/api/search", async (req, res) => {
  const { query } = req.body;
  const data = await search(query);
  res.json(data);
});
로그인 후 복사
로그인 후 복사
로그인 후 복사


이때:
<input
  debounceInput={300}
  onInput={async (e) => {
    // All this code only runs on the server
    const data = await search(e.target.value);
    store.set("query", data);
    store.transferToClient(["query"]);
  }}
/>
로그인 후 복사
로그인 후 복사

웹 구성 요소(클라이언트) 내부는 항상 암호화되지만 서버에서는 항상 해독됩니다. 참고

: Brisa는 OpenSSL에서 권장하는 정보를 안전하게 암호화하는 데 사용되는 암호화 알고리즘의 조합인 aes-256-cbc를 암호화에 사용합니다. 암호화 키는 프로젝트 빌드 중에 생성됩니다.

Server Actions have been fixed


양 세계(서버/클라이언트) 간 암호화된 데이터 공유

결론

Brisa에서는 쉽게 웹 구성 요소 작성을 지원하고 싶지만 클라이언트 코드 없이 SPA를 만들고 순수 클라이언트 상호 작용이거나 웹 API를 터치해야 하는 경우에만 웹 구성 요소를 사용할 수 있도록 하는 것이 목표입니다. 그렇기 때문에 클라이언트 코드를 작성하지 않고도 서버와 상호 작용할 수 있도록 하는 서버 작업이 매우 중요합니다.

Brisa를 사용해 보시기 바랍니다. 터미널에서 bun create brisa 명령을 실행하거나 몇 가지 예제를 시도하여 작동 방식을 확인하기만 하면 됩니다.

    참고자료
  • 서버 액션 컨벤션
  • 서버 작업 동작
  • 서버 작업이 포함된 양식
  • 중첩 작업
  • 서버측 유효성 검사 및 오류 처리
  • 서버 작업 디바운스
  • 낙관적인 업데이트
  • 다시 렌더링 실행
  • 서버 작업을 사용하여 다른 페이지로 이동
  • 쿠키 접근
  • 서버 액션의 보안
  • 행동 신호
  • 민감한 데이터 전송
  • 서버 액션의 속성
역방향 프록시에서 서버 작업 사용

위 내용은 서버 작업이 수정되었습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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