react-dom/server

Tony·2023년 2월 19일
0

react

목록 보기
64/86
post-custom-banner

TL;DR;

  • react-dom/server 의 renderToStaticMarkup() 메소드는 server side (node 위에서 동작) 환경이 아니어도 정적 HTML을 만드는데 사용할 수 있다

지난 포스팅에서 react-dom/server 를 사용해서 string으로 element를 사용하는 것 대신 react component를 사용해보았다

이번엔 react-dom/server 가 무엇인지 알아보자

Overview

These methods are only available in the environments with Node.js Streams:

  • renderToPipeableStream()
  • renderToNodeStream() (Deprecated)
  • renderToStaticNodeStream()

These methods are only available in the environments with Web Streams (this includes browsers, Deno, and some modern edge runtimes):

  • renderToReadableStream()

The following methods can be used in the environments that don’t support streams:

  • renderToString()
  • renderToStaticMarkup()
  • 첫 줄만 읽어보고, node가 있는 곳에서만 동작하는 건가? 하는 생각이 들어서아래와 같은 실험을 하게 되었다
    • 실험을 다 끝내고 이제와서 다시 보고 느낀 것이지만 공식문서를 잘 읽었다면 이런 실험도 안해도 됐을 것이다
    • 이미 문서에 rendertostaticmarkup 메소드는 그냥 사용가능하다고 overview에도 적혀있다..

ReactDOMServer.rendertostaticmarkup

  • https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup
  • renderToString과 비슷하지만 data-reactroot와 같이 React가 내부적으로 사용하는 추가 DOM 속성을 생성하지 않는다는 점이 다릅니다. 추가 속성을 제거하면 일부 바이트를 절약할 수 있으므로 React를 간단한 정적 페이지 생성기로 사용하려는 경우에 유용합니다.
    공식 문서 내용
  • ReactDOMServer 개체를 사용하면 구성 요소를 정적 마크업으로 렌더링할 수 있습니다. 일반적으로 노드 서버에서 사용됩니다.

지난 포스팅에서 swiper 라이브러리에서 커스텀 페이지네이션을 구현하는데 사용했었다

사실 개발 환경이 Next.js이었고 Next.js자체로 노드 서버이기도 하기 때문에 사용할 수 있었던 것은 아닐까 하는 생각이 들었다

그래서 react 클라이언트 환경에서 사용 후 빌드 후 nginx에서 띄워보고 실행되는지 확인해보자

근데 만약 된다면 현재 내 컴퓨터에 node가 설치돼서 되는 것일 수도 있으니 node가 없는 도커환경에서도 띄워보자

빌드 후 내 컴퓨터로 nginx 위에서 띄우기

brew info nginx를 하면 brew로 설치한 nginx에 대한 정보를 확인할 수 있다

  • 경로를 확인 : /opt/homebrew/var/www

해당 경로에 빌드파일들을 풀어서 올려놓았다

확인 결과 커스텀 ReactDOMServer를 이용한 페이지네이션 버튼(bullet)은 잘 적용되었다

아마 내 컴퓨터에 node가 설치되어 있어서 된 것 같다는 생각이든다

그런데 문제가 있었다 ReactDOMServer.renderToStaticMarkup() 으로 렌더링한 HTML은 onClick 같은 이벤트 핸들러 prop으로 전달한 콜백함수들이 동작하지 않았다

  • 메소드 이름 처럼 StaticMarkup을 렌더링하는 것이기 때문에 그런 것 같다
  • 이벤트핸들러를 붙이고 싶다면 아래와 같이 특정 클래스를 지정하고 querySelector로 접근해서 이벤트리스너를 붙여줄 수 있다
const SwiperPageButton = styled.button`
  background-color: orange;
  padding: 10px;
`;

// ...

  useEffect(() => {
    const bullets = document.querySelectorAll(".bullet-test");
    bullets.forEach((bullet) => {
      bullet.addEventListener("click", () => {
        // not working
        console.log("bullet clicked by addEventListener");
      });
    });
    return () => {
      bullets.forEach((bullet) => {
        bullet.removeEventListener("click", () => {
          // not working
          console.log("bullet clicked by addEventListener");
        });
      });
    };
  }, []);

return (
		<Swiper
          modules={[Pagination, Navigation]}
          loop
          pagination={{
            dynamicBullets: true,
            clickable: true,
            renderBullet: (index, className) => {
              return ReactDOMServer.renderToStaticMarkup(
                <SwiperPageButton
                  type="button"
                  className={`${className} bullet-test`}
                  onClick={() => {
                    // not working
                    console.log("bullet clicked", index);
                  }}
                >
                  {index}
                </SwiperPageButton>
              );
            },
          }}
     // ...
    />
  );

node가 설치되지 않은 docker위에서 띄우기

nginx만 설치된 도커 이미지를 받자

받은 이미지 확인

  • docker images

nginx 서버 띄우기

  • docker run --name nginx-server -d -p 8081:80 nginx

실행 확인

  • docker ps

브라우저에서 확인

마운팅하기(볼륨 설정)

아까 내 로컬 nginx 위치로 마운팅해보자(/opt/homebrew/var/www)
그 전에 내가 실행한 nginx 도커 컨테이너의 nginx 배포 파일 경로를 확인해보자

  • 도커 컨테이너 접속 : docker exec -it 컨테이너id /bin/bash
  • /usr/share/nginx/html

마운팅 경로 설정을 해주자 /opt/homebrew/var/www:/usr/share/nginx/html

기존 컨테이너 스탑

  • docker stop 컨테이너아이디
    기존 컨테이너 삭제
  • docker rm nginx-server

볼륨 설정 후 재실행

에러나서 빌드파일 복사하고 경로 바꿈

docker: Error response from daemon: Mounts denied: 
The path /opt/homebrew/var/www is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See https://docs.docker.com/desktop/mac for more info.

/Users/gotaehwan/projects/temp:/usr/share/nginx/html

docker run --name nginx-server -d -p 8081:80 -v /Users/gotaehwan/projects/temp:/usr/share/nginx/html nginx

  • 노드 없이도 되는 것을 확인
  • 안전하게 사용할 수 있을 것 같다
  • 단, renderToStaticMarkup이므로 onClick같은 것은 사용할 수 없고 단지 HTML 렌더링만 되는 것임에 유의하자
  • 그리고 공식 문서를 꼼꼼히 잘 읽자 !
profile
움직이는 만큼 행복해진다
post-custom-banner

0개의 댓글