--- title: renderToPipeableStream --- `renderToPipeableStream`은 React 트리를 파이프 가능한 [Node.js 스트림](https://nodejs.org/api/stream.html)으로 렌더링합니다. ```js const { pipe, abort } = renderToPipeableStream(reactNode, options?) ``` 이 API는 Node.js 전용입니다. Deno 및 최신 엣지 런타임과 같은 [Web 스트림](https://developer.mozilla.org/ko/docs/Web/API/Streams_API)이 있는 환경에서는 [`renderToReadableStream`](/reference/react-dom/server/renderToReadableStream)을 대신 사용하세요. --- ## 레퍼런스 {/*reference*/} ### `renderToPipeableStream(reactNode, options?)` {/*rendertopipeablestream*/} `renderToPipeableStream`을 호출하여 React 트리를 HTML로 [Node.js 스트림](https://nodejs.org/api/stream.html#writable-streams)에 렌더링합니다. ```js import { renderToPipeableStream } from 'react-dom/server'; const { pipe } = renderToPipeableStream(, { bootstrapScripts: ['/main.js'], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } }); ``` 클라이언트에서 [`hydrateRoot`](/reference/react-dom/client/hydrateRoot)를 호출하여 서버에서 생성된 HTML을 상호작용할 수 있도록 만듭니다. [아래에서 더 많은 예시를 확인하세요.](#usage) #### 매개변수 {/*parameters*/} * `reactNode`: HTML로 렌더링하려는 React 노드. 예를 들어, ``과 같은 JSX 엘리먼트입니다. 전체 문서를 나타낼 것으로 예상되므로 `App` 컴포넌트는 `` 태그를 렌더링해야 합니다. * **선택 사항** `options`: 스트리밍 옵션이 있는 객체입니다. * **선택 사항** `bootstrapScriptContent`: 지정하면 이 문자열이 인라인 ` ``` 클라이언트에서 부트스트랩 스크립트는 [`hydrateRoot`를 호출하여 전체 `document`를 하이드레이트해야 합니다.](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) ```js [[1, 4, ""]] import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot(document, ); ``` 이렇게 하면 서버에서 생성된 HTML에 이벤트 리스너가 첨부되어 상호작용이 가능해집니다. #### 빌드 출력에서 CSS 및 JS 에셋 경로 읽기 {/*reading-css-and-js-asset-paths-from-the-build-output*/} 최종 에셋 URL(예: 자바스크립트 및 CSS 파일)은 빌드 후에 해시 처리되는 경우가 많습니다. 예를 들어 `styles.css` 대신 `styles.123456.css`로 끝날 수 있습니다. 정적 에셋 파일명을 해시하면 동일한 에셋의 모든 별개의 빌드에서 다른 파일명을 가질 수 있습니다. 이는 정적 자산에 대한 장기 캐싱을 안전하게 활성화할 수 있기 때문에 유용합니다. 특정 이름을 가진 파일은 콘텐츠가 변경되지 않습니다. 하지만 빌드가 끝날 때까지 에셋 URL을 모르는 경우 소스 코드에 넣을 방법이 없습니다. 예를 들어, 앞서처럼 `"/styles.css"`를 JSX에 하드코딩하면 작동하지 않습니다. 소스 코드에 포함되지 않도록 하려면 루트 컴포넌트가 프로퍼티로 전달된 맵에서 실제 파일명을 읽을 수 있습니다. ```js {1,6} export default function App({ assetMap }) { return ( ... ... ... ); } ``` 서버에서 ``를 렌더링하고 에셋 URL과 함께 `assetMap`을 전달합니다. ```js {1-5,8,9} // 빌드 도구에서 이 JSON을 가져와야 합니다(예: 빌드 출력에서 읽어오기). const assetMap = { 'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js' }; app.use('/', (request, response) => { const { pipe } = renderToPipeableStream(, { bootstrapScripts: [assetMap['main.js']], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } }); }); ``` 이제 서버에서 ``를 렌더링하고 있으므로 클라이언트에서도 `assetMap`을 사용하여 렌더링해야 하이드레이션 오류를 방지할 수 있습니다. 다음과 같이 `assetMap`을 직렬화하여 클라이언트에 전달할 수 있습니다. ```js {9-10} // 빌드 도구에서 이 JSON을 가져와야 합니다. const assetMap = { 'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js' }; app.use('/', (request, response) => { const { pipe } = renderToPipeableStream(, { // 조심하세요: 이 데이터는 사용자가 생성한 것이 아니므로 stringify()하는 것이 안전합니다. bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`, bootstrapScripts: [assetMap['main.js']], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } }); }); ``` 위 예시에서 `bootstrapScriptContent` 옵션은 클라이언트에서 전역 `window.assetMap` 변수를 설정하는 추가 인라인 `