Skip to content
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

[서버 사이드 렌더링 - 2단계] 에프이(박철민) 미션 제출합니다. #68

Merged
merged 10 commits into from
Oct 24, 2024

Conversation

chysis
Copy link
Member

@chysis chysis commented Oct 21, 2024

안녕하세요 소하~ 우테코의 마지막 미션이네요!
마지막까지 리뷰 잘 부탁드려요😊

라우팅 라이브러리

라우팅 라이브러리는 react-router-dom을 사용했습니다.

👀 리뷰를 통한 생각 나눔

1. SSR 환경에서 웹 브라우저는 어떤 과정으로 하이드레이션(hydration)을 진행하는지 상세히 서술하시오.

하이드레이션은 서버가 내려준 HTML을 클라이언트 측에서 React로 활성화시키는 작업입니다. 정적 HTML만 받은 상황에서는 이벤트 핸들러나 상태가 동작하지 않기 때문에 이 과정이 필요합니다.

<하이드레이션 과정>

  1. 서버는 완성된 html을 브라우저에게 내려줍니다.
  2. 클라이언트는 자바스크립트 파일을 다운로드하고, React와 함께 브라우저에서 실행됩니다.
  3. 클라이언트의 React는 서버에서 내려준 HTML을 파싱한 후, 만든 DOM과 서버에서 생성한 React 트리를 일치시킵니다.
  4. HTML은 다시 렌더링되지 않고, 이벤트 등 클라이언트에서 필요한 동작들이 활성화됩니다.

<서버와 클라이언트에서 발생할 수 있는 차이점>

  • 클라이언트에서 Date와 같이 동적으로 변화하는 데이터를 사용하는 경우에도 불일치가 발생합니다. 이때 React는 DOM을 조정해서 불일치를 수정합니다.
  • 서버의 상태는 정적이기 때문에 한 번 내려준 것은 바뀌지 않지만, 클라이언트는 동적으로 상태가 변화할 수 있습니다. 클라이언트가 상태를 가지고 있는 경우 실제로 사용하게 되는 상태 값이 달라질 수 있어요.

2. 다음 두 가지 상황의 동작 과정을 비교해 설명하시오.

사용자가 처음 영화 목록 페이지에 접속할 때

서버는 영화 목록 API 요청을 통해 받은 데이터로 HTML을 만들어서 클라이언트에 내려줍니다. 클라이언트는 받은 HTML을 파싱해서 화면에 그립니다. 다음으로 하이드레이션 과정을 거쳐 상호작용 가능한 페이지가 됩니다. 서버와 클라이언트 간 데이터 불일치를 막기 위해 서버는 전역 객체에 데이터를 담아 클라이언트에 보내줍니다.

하이드레이션 후, 사용자가 영화 목록에서 특정 영화를 클릭하여 상세 페이지로 이동할 때

첫 화면이 SSR로 처리된 이후 상호작용은 클라이언트 단에서 CSR로 처리됩니다. 특정 영화를 클릭하면 라우팅이 일어납니다. 서버로부터 새로운 HTML을 받아오는 것이 아니라, 클라이언트에서 상세 영화 데이터를 요청해서 JSON 형식의 파일을 받은 뒤 모달을 보여줍니다.

3. 다음 두 가지 상황의 동작 과정에서 라우팅의 차이점이 무엇인지 서술하시오.

사용자가 https://주소/detail/12345와 같이 브라우저에 직접 입력한 뒤 페이지로 이동할 때

서버 사이드 라우팅이 일어납니다. URL에 맞는 컨텐츠를 서버가 반환해줍니다.

  1. 브라우저는 서버에 detail/:id 경로로 요청을 보냅니다.
  2. 서버는 해당 경로에 대한 라우팅 로직이 있기 때문에 그에 맞는 HTML을 만들어서 클라이언트에게 내려줍니다. 이때 서버가 상세 영화 정보 API를 요청해서 HTML을 만듭니다.
  3. 클라이언트는 받은 HTML을 파싱하여 화면에 그린 다음, 하이드레이션을 진행합니다.

하이드레이션 후, 사용자가 영화 목록에서 특정 영화를 클릭하여 상세 페이지로 이동할 때

이 경우에는 클라이언트 사이드 라우팅이 일어납니다. 서버에 새로운 HTML을 요청하지 않고 React가 페이지를 전환합니다.

  1. 영화 목록에서 특정 영화를 클릭하면 React Router가 동작하여 페이지가 전환됩니다.
  2. 클라이언트가 상세 영화 정보 API를 요청하여 모달이 그려집니다.

@chysis chysis self-assigned this Oct 21, 2024
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API 요청 로직 파일 위치

기존에는 API 요청 로직이 서버에 있었는데, 첫 페이지만 SSR로 처리되고 이후 상호작용은 모두 CSR로 처리되고 있기 때문에 클라이언트가 요청의 주체가 되는 경우가 더 많을 것이라 판단했어요. 때문에 모든 API 요청 로직들을 클라이언트 폴더 내부로 옮겼습니다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오~ 파일구조 변경해주신 거 좋은 것 같아요!
파일 구조까지 생각하시다니... 깊게 고민하신게 느껴져요!

@woowahan-cron woowahan-cron added the 🥎 크론 확인 크론이 확인한 경우 레이블을 지정합니다. label Oct 21, 2024
Copy link

@soi-ha soi-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에프이와 저의 코드가 react-router-dom을 사용하는 방법이 조금 다른 것 말고는 유사하네요! 그래서 코드에 관해서는 크게 질문드릴건 없네용.

대신 에프이가 미션을 진행하면서 하이드레이션이 되지 않아서 겪었던 문제가 있었는지 궁금하네요!
저 같은 경우는 2,3번 질문과 연관이 있는데요~ 저는 미션을 진행하면서 onClick이 작동하지 않는 문제가 발생했었어요. 이 말은 즉, 하이드레이션이 되지 않아서 event가 작동하지 않았던 거죠... 하이드레이션 에러가 발생하지 않는데 왜 안되는 걸까? 고민을 많이하고 주변 크루들의 도움을 받아서 해결했습니다.. (dotenv를 설치하지 않았던...)
그래서 onClick이 작동하지 않아서 Link를 사용하여 페이지를 이동하도록 했었어요. 이렇게 하니까 navigate를 활용해서 페이지를 이동할때와 다르더라구요. Link를 활용하여 Modal을 열었을 때는 Main 페이지 스크롤했던 것이 초기화되었던..

저는 미션을 진행하면서 이런 문제들이 발생했었어요! 에프이는 어떤 문제가 발생했었는지 궁금합니다 :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오~ 파일구조 변경해주신 거 좋은 것 같아요!
파일 구조까지 생각하시다니... 깊게 고민하신게 느껴져요!

);
const initialData = window.__INITIAL_DATA__;

const router = createBrowserRouter([
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 react-router-dom을 사용했지만, 사용방법이 다르네요!
같은 것을 사용해도 사람마다 다르게 하는 점이 재밌는 것 같아요!

}, []);

if (!detailData) {
return <div className='modal-background active'>Loading ...</div>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로딩까지 고려하시다니... 👍

Copy link

@soi-ha soi-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요, 에프이!
드디어 마지막 미션이네요~!

남겨주신 PR 내용 잘 확인했습니다~ 에프이 PR을 보면서 저번도 그렇고 이번에도 저에게 많은 도움이 됩니다!
딱 필요한 내용만 작성해주시는데, 그 내용들이 머릿속에 쉽게 그려지네요...! 많은 도움 받고 갑니당ㅎㅎ

리뷰는 개선점에 대해서 질문드릴 건 없고 간단한 질문하나 남겼습니다! 천천히 답 남겨주세요 :)

@chysis
Copy link
Member Author

chysis commented Oct 24, 2024

안녕하세요 소하!
저는 하이드레이션 오류는 마주치지 못했는데, 다른 시행착오들을 여러 번 거쳤어요.

process is not defined 문제

api 요청 시 환경 변수를 사용하게 되는데, 데이터는 제대로 가져오고 있지만 콘솔에 process is not defined 오류가 발생했어요. webpack 설정 파일에 DefinePlugin을 추가해서 해결했습니다!

클라이언트와 서버의 라우터 설정

서버에서 html을 만들 때 클라이언트 컴포넌트를 import해서 renderToString 과정을 거치고 있어요. SSR 렌더링 과정은 node.js 서버에서 이루어지기 때문에 window와 document 객체에 접근할 수 없어요. 전역 객체(window.INITIAL_DATA)에 접근하는 코드를 포함한 컴포넌트를 renderToString했더니 window is not defined 오류가 발생했어요. 전역 객체를 어느 시점에 접근하는 게 좋을지 여러번 시도해 보다가 지금의 코드가 되었어요 :)

그리고 클라이언트에서 사용하고 있는 createBrowserRouter는 내부적으로 document 객체에 접근하는데, 처음에 이것을 모르고 계속 오류가 발생해서 한참 디버깅 했던 기억이 나네요!


소하는 navigate가 아닌 Link를 사용해서 구현했다고 하셨는데, 지금은 어떻게 해결하셨는지 궁금하네요 :)

@soi-ha
Copy link

soi-ha commented Oct 24, 2024

다행이 하이드레이션이 잘 적용되어 Link에서 navigate로 이동하는 것으로 수정했어요!
에프이도 미션을 진행하면서 문제가 있으셨군요~ 저와는 다른 문제가 발생했어서 신기하고 재밌네요!
덕분에 다른 문제들도 간접적으로 접하게 되어서 좋네요! 알려주셔서 고마워요 에프이~

Copy link

@soi-ha soi-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

남겨주신 코멘트 잘 봤어요! 에프이~!
이제 진짜 우테코 미션이 끝이 났네요..🥲
내일 데모데이와 남은 우테코 level5 건강하게 잘 보내시길 바라요! :) 화이팅~!

@soi-ha soi-ha merged commit 2394d72 into woowacourse:chysis Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🥎 크론 확인 크론이 확인한 경우 레이블을 지정합니다.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants