-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[서버 사이드 렌더링 - 1단계] 마루(박규한) 미션 제출합니다. #10
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요 마루!
정말 열심히 코드를 읽어봤는데 군더더기 없이 깔끔해서 지적할 부분이 없네요.. ㅎㅎ
단순히 의견을 물어보기 위해 RC 날려봅니다~
SSR 속도
SSR 방식으로 렌더링할 경우 DOM을 찾아 이벤트를 등록하는 작업과 사용자의 네트워크 환경에 따라 API 응답 속도에 영향을 받는 작업을 줄였다고 생각합니다. HTML을 그린 후 수행하기 때문에 초기 렌더링 성능에 유리하다고 할 수 있습니다.
1
여기서 사용자의 네트워크 환경에 따라 API 응답 속도에 영향을 받는 작업을 줄였다
고 말해줬는데, 자체 서버의 응답을 처리한게 아닌 TMDB 라는 외부 서버에 데이터를 요청하여 응답값을 기반으로 HTML 파싱을 하기에 API 응답 속도 차이가 없을거라는 생각도 드는데 요 부분에 대해서 조금 더 자세히 설명해줄 수 있을까요 ?.?
2
서버에서 브라우저로 HTML을 넘길 때 window 객체를 사용했는데, 뭔가 사용하면서도 전역 객체로 데이터를 전달하는 게 어색하더라구요! 그래서 이거에 대해서 어떻게 생각했는지도 궁금합니다!
저도 처음에는 완성된 HTML을 반환한다면 그대로 사용하면 되는데 왜 window 객체에 값을 초기화하며 넘기는지 이해를 못했었는데, 제가 미션을 진행하며 느낀점은
- 서버에서 전송한 HTML 과 React의 SPA 로 그려내는 DOM 이 일치한 DOM TREE 를 가지고 있는지 검증하기 위해
- 서버에서 패칭한 데이터를 클라이언트 사이드에서 다시 패칭하여 렌더링이 할때
개인적으로 이번 미션을 Nextjs 의 동작과 비교하면서 진행해보니 재밌는게 많더라구요!
|
||
hydrateRoot( | ||
document.getElementById("root"), | ||
<App popularMovies={data.movies} bestMovieItem={data.movies[0]} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개인적으론 App 컴포넌트에 prop 을 넘겨주는 흐름이 일반적이진 않는거 같은데 App 의 prop 으로 값을 넘겨준 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
서버측 코드에서 renderToString을 수행할 때를 생각하면, 주입할 리액트 컴포넌트의 최상단 컴포넌트를 넣는 게 유지보수 관점에서 더 적절하다고 생각했어요!
페이지단의 코드가 바뀌는 경우가 종종 있는데, App 내부의 페이지 코드가 renderToString 인자로 들어가게 되면 SSR서버 코드도 변경이 필요하다는 점에서 불편하다고 느꼈습니다.
next에서 SSR로 데이터를 정확히 어떻게 가져오는지는 모르겠지만, 제가 이해한 것으론 App에 주입하는 것과 같이 페이지단에 데이터를 주입한다고 생각했어요!
이에 대한 다르의 생각도 궁금하네용
https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
페이지단의 코드가 바뀌는 경우가 종종 있는데, App 내부의 페이지 코드가 renderToString 인자로 들어가게 되면 SSR서버 코드도 변경이 필요하다는 점에서 불편하다고 느꼈습니다.
오호 그렇군용. 저는 개인적으로 App에서부터 데이터가 필요한 곳까지 props drilling 하는게 불필요하고, 흐름이 어색하다고 생각하여 App에 데이터를 넣는게 아닌 필요한 컴포넌트에 데이터를 넣어서 서버에서 렌더링 한 후 완성된 html 파일을 클라이언트에게 반환하도록 했어요!
개인적으로 next 프레임워크와 비교를 해봤을 때, (page router 기준) next에서 _app.tsx 파일과 React의 App 이랑 비슷하다는 생각을 했고
next에서 서버 데이터를 주입하는 위치는 라우팅 페이지의 최상위 컴포넌트였기에(page 디렉토리 하위의 컴포넌트) 여기서 아이디어를 얻어서 App이 아닌 컴포넌트에서 데이터를 주입하도록 했어요
물론 굳이 next를 따라하는게 좋은건 아니지만 위에서 언급한대로 App 에서부터 데이터를 내려주는 흐름이 개인적으론 어색하기도 하고 불필요한 props drilling 인것 같다는 개인적인 의견이에요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오 실험까지 해보느라 고생하셨네요! 💪
해당 실험을 보니 확실히 클라이언트의 요청과 서버의 요청을 본다면 서버의 요청이 훨씬 빠르다는것을 알 수 있네요!
클라이언트에서 보내는 요청과 서버에서 보내는 요청의 차이는 브라우저에 의한 헤더, 쿠키의 데이터가 추가되기에 패킷의 크기가 조금은 클 수 있지만 매우 미비할거다라는 생각을 했는데 생각보다는 차이가 있어서 신기하게 결과를 봤습니다
확실히 클라이언트의 네트워크 환경이 불안정할 수 있으니 서버의 리소스를 사용하는게 더 괜찮을 수 있겠군요 ㅎㅎ (서버가 바쁘지 않는 이상)
이번 미션 고생하셨습니다 다음 미션도 화이팅이이에요 🔥
안녕하세요 다르~! 서버에서 리액트 앱을 다룬다는 게 어색해서 조금 어려웠습니다!! 다르의 가감없는 피드백 주면 적극적으로 소통하겠습니다 🔥🔥🔥🔥
👀 리뷰를 통한 생각 나눔
초기 렌더링 성능은 유의미한 컨텐츠 페이지가 얼마나 빨리 뜨는지를 기준으로 하였습니다.
CSR : 빈 HTML을 불러온 후, 자바스크립트를 실행하여 API를 호출하고 이벤트 리스너가 다 달린 DOM 트리를 그림
SSR : API 서버에서 받은 데이터가 HTML에 채워져서 불러와진 후 자바스크립트를 실행하여 컴포넌트 로직 수행
따라서, SSR 방식으로 렌더링할 경우 DOM을 찾아 이벤트를 등록하는 작업과 사용자의 네트워크 환경에 따라 API 응답 속도에 영향을 받는 작업을 줄였다고 생각합니다. HTML을 그린 후 수행하기 때문에 초기 렌더링 성능에 유리하다고 할 수 있습니다.
요청과 응답의 흐름 파악
서버 측에서 클라이언트 측 컴포넌트 코드를 불러올 때는
renderToString
함수를 통해 React 트리를 HTML 문자열로 렌더링합니다.그리고 서버에서와 클라이언트에서 같은 DOM 계층 구조를 가져가기 위해 API 응답값을 최상단 리액트 컴포넌트에 주입합니다.
브라우저가 서버로부터 HTML을 받은 후, 리액트 앱이 로드되면 트리를 비교하며 이벤트 리스너들을 추가하여 동적인 웹이 완성됩니다.
SSR 서버에서 렌더링된 HTML과 브라우저에서 렌더링된 가상돔 트리 간에 차이가 있어 에러가 발생합니다.
두 트리가 같은 트리를 그리기 위해 스크립트 태그로 전역 객체에 데이터를 주입합니다.
전역 객체를 초기화하여 데이터를 넘기는 이유는 HTML을 불러오고 리액트 앱을 처음 그릴 때부터 데이터에 접근할 수 있어야하기 때문이라고 생각합니다.
질문
서버에서 브라우저로 HTML을 넘길 때 window 객체를 사용했는데, 뭔가 사용하면서도 전역 객체로 데이터를 전달하는 게 어색하더라구요! 그래서 이거에 대해서 어떻게 생각했는지도 궁금합니다!
+추가
hydration이 제대로 적용되는 줄 알았는데 이전 코드에서는 클라이언트 코드를 아예 불러오지 않은 상태더라고요! 확인해보니 스크립트도 불러오지 않아서 꽤나 삽질을 했습니다 ㅎㅎ 크론이 추가해준 뼈대 코드 반영해서 hydration 적용되어 이벤트 발생하는 것까지 확인하였습니다!
default.mov