react 18과 Next.js 잘 쓰고 싶으면 알아야 할 개념 모음

Q&A 큐레이션

1. Next 13과 react 18 서버 컴포넌트 관련 질문 (질문이 좀 길어요)

안녕하세요, 요즘 next 13과 react 18 서버 컴포넌트에 대해서 본격적으로 파고 있는데 궁금한 점들이 여러가지 떠올라서 글 올립니다. 1. data fetching 방식의 변경 우선 기존에는 동적인 data fetching의 경우, getServersideProps를 통해서 페이지의 root에 전달해주고는 방식이 일반적이었는데 서버에서만 돌아가는 서버 컴포넌트가 나오면서 data fetching을 컴포넌트 단위로 할 수 있게되면, 기존에 사용하던 getServersideProps 같은 유틸 함수들은 사라지는건가요? 기존에는 정적 데이터면 getStaticProps, 동적 데이터면 getServersideProps, 유저 상호작용이 필요한 데이터면 client side useEffect를 많이 사용했는데 next 13부터는 이게 뭔가 뒤섞이는 것 같아서 혼란스럽네요. next 13을 위한 data fetching 패턴이나 방법론이 있나요? 2. 기존에 사용하던 상태 관리 프레임워크의 변화 위와 어느정도 연결되는 이야기입니다. 기존에 react-query를 많이 사용했는데 next 13부터 컴포넌트 레벨로 데이터를 요청할 수 있고 또 next 차원에서 요청 중복 제거를 지원하게되면 react-query 처럼 서버 상태관리와 캐싱을 강점으로 내세우는 프레임워크의 역할을 어떻게 되는건가요? 서버 상태를 컴포넌트 레벨에서 가져올 수 있다고 해도, 여전히 전역 상태 관리가 필요할 것 같은데 recoil, redux, zustand 같은 상태 관리 프레임워크도 계속 쓰게되는 것일까요? 계속 쓰게 된다고 하면 서버 컴포넌트와의 호환성은 어떻게 되는건가요? 만약 전역 상태 관리를 써야하는 컴포넌트라면 서버 컴포넌트가 될 수 없는 것인가요? 3. 서버 구성의 변경 다른 곳은 모르겠지만, 저는 next 백엔드를 단순히 요청을 전달하는 용도로만 쓰고 실제로 중요한 로직은 다른 백엔드 서버에서 처리하는 구조를 가지고 있었습니다. 하지만, next 13을 보니 서버 컴포넌트에서 DB 연결을 직접해서 데이터를 가져오는 예시들도 있더군요. 사이드 프로젝트라면 모르겠지만, 실 서비스에서도 서버 컴포넌트 - DB 직접 연결 이라는 구조가 성립할 수 있는건가요? 기존에 데이터를 취합하고 내려주던 백엔드 서버의 역할이 생략되는거라고 생각해도 되는건가요? 4. 왜 다시 20년 전으로 돌아가는거죠 제가 20년 동안 개발한 것은 아니지만, 예전에는 웹페이지를 서버에서 완전히 로드해서 내려주는 형태를 가지고 있었다고 배웠습니다. 그러다가 개개인의 기기가 스펙이 좋아지면서 서버 부하를 줄이고 클라이언트 쪽에서 역할을 분담하는 방식이 떴다고 들었어요. react도 처음에는 이런 프레임워크로 나왔다고 알고 있습니다. 그러다가 next, remix 같은 프레임워크들이 서버사이드 렌더링을 적극적으로 장려하면서 다시 회귀하고 있다고 들었습니다. 최근에는 react 마저 서버 컴포넌트를 발표했잖아요. 왜 이제와서 다시 서버 쪽에서 페이지를 로드하는 방식을 추진하고 있는건가요? 질문을 적고보니 좀 길어졌는데, 서핑을 좀 해봐도 마땅히 도움이되는 글이 별로 없어서 현직자들은 어떻게 생각하시는지 의견을 얻고자 질문 올립니다!


답변

1번은 next.js 13버전 app에 대해서 공식문서(베타)를 보시면 없어짐을 아실 수 있습니다. 사실상 컴포넌트가 렌더링 되는 방식이 12에선 페이지 단위였다면 13에선 컴포넌트 단위로 변경되다보니 getStaticProps -> ISR or SSG, getServersideProps -> SSR로 페이지단위 렌더링 방식이 고정되는걸 서버컴포넌트와 클라이언트 컴포넌트로 컴포넌트 단위로 렌더링되는 방식이 변경되었다고 이해하시는게 더 나을거 같아요. 2번은 next.js13부터는 컴포넌트가 만약 상태라는걸 갖고 싶다면 클라이언트 컴포넌트를 사용하도록 강제화하고 있습니다. 서버컴포넌트에서 상태는 결국 디비라고 보시는게 더 편할거 같고 전역상태관리도 결국 top down이 아닌 bottom up 방식으로 변경되어감으로써 리덕스나 주스탄스 같이 정말 어플리케이션 전반에 걸치 상태라는 것은 이제 안쓰고 그 역할을 리액트쿼리 같은 캐싱기반으로 대체될것으로 전 생각하고 잇습니다. 3번은 아시다 싶이 가능이 한다는 것뿐이니 작은 서비스가 아닌 이상 백엔드 서버와 프론트엔드 서버는 분리되어야 관리도 용이하며 대용량 서비스에도 더 적합하기 때문에 next.js에 직접 디비를 연결할 일은 잘 없을것으로 보입니다. 4번은 아래의 deno 블로그에 올라온 글을 읽어보심이 더 좋을거 같습니다. https://deno.com/blog/the-future-and-past-is-server-side-rendering 제가 아는 지식선에서 설명을 드리자면 CSR에서 문제가 되었던 부분은 결국 프론트엔드에서 만드는 어플리케이션이 커짐에 따라서 한 화면을 이루는 번들 자체가 커져서 문제가 되었것으로 기억합니다. 추가적으로 모든 코드를 클라이언트에 돌리다보니 보안적인 문제도 있는것으로 알고 있습니다. 결국 SSR로 돌아온 것을 맞습니다만 jsp시절보다 낫다하는 면은 jsp시절에서는 클라이언트에서 렌더링하는 것 한벌, 서버에서 렌더링하는 것 한벌 짜야했던 점이 이제는 next.js와서 한벌로 가능해졌다는 점이 있고 위에서 설명드린 것처럼 한화면 모두 SSR인 것이 SSR과 SSG의 혼합 등으로 조금 더 나은 렌더링방식을 가져가는 것으로 보입니다.

외 5개 답변 보러 가기

2. react 18에서 use 가 뭔가요?

안녕하세요~ react 18을 사용하고 있는데 use() 라는 함수를 많이 사용하더라구요. 주로 외부 API 조회할때 조회하는 함수를 use로 넣어서 사용하는데, 이게 뭐하는 용도인지 궁금합니다.


답변

안녕하세요. 생각보다 관련 자료를 찾기 힘들어서 직접 소스코드를 확인해봤는데요. (use라는 단어가 너무 흔해서 검색 결과가 좋지가 않네요ㅠㅠ) https://github.dev/facebook/react/blob/1e3e30dae2bcfbeb0abc686f2a37aec208eedb39/packages/react-reconciler/src/ReactFiberHooks.new.js#L891 이 파일을 참고해보시면 use 함수가 어떤 동작을 하는지 알 수 있습니다. 로직을 조금 살펴보면 Promise 객체인 경우, trackUsedThenable 함수가 작동하는 걸 알 수 있습니다. https://github.dev/facebook/react/blob/1e3e30dae2bcfbeb0abc686f2a37aec208eedb39/packages/react-reconciler/src/ReactFiberThenable.new.js#L98 trackUsedThenable을 또 파보시면, promise의 결과 값을 unwrap하는 것을 보실 수 있습니다. 이것 외에도 다른 작업을 하는 것 같긴하지만 전체를 깊이 있게 확인하지는 않았습니다. 결론은 use() 함수의 경우 Promise 객체를 받게되면 react의 연산 과정 (render, commit) 속에서 여러가지 일을 수행하는데, 그 중 하나가 promise의 결과 값을 unwrap하는 것인 것 같습니다. (물론 제가 틀렸을수도 있습니다 ㅎㅎ) 그래서 단순 await으로 결과 값을 꺼내는 것과 비교했을때, use()를 사용하시면 react 팀이 의도한대로 react의 사이클안에서 작동하게끔 할 수 있는게 다른점인것 같네요.

이 질문 바로 가기

3. next.js getServerSideProps와 서버 컴포넌트

next.js에서 새롭게 선보인 서버 컴포넌트를 공부하다가 생긴 질문 남겨봅니다! 기존에는 SSR을 구현할때 getServerSideProps를 통해서 페이지에 필요한 정보를 내려주고 있었는데요. 이렇게 getServerSideProps에 구현된 로직을 서버 컴포넌트로 바꿔야하는 것인지 궁금합니다. 서버 컴포넌트도 서버에서만 돌아가는 코드니까 getServerSideProps가 하던 역할을 쪼개서 하는건가 싶어서요. (https://beta.nextjs.org/docs/rendering/server-and-client-components)


답변

안녕하세요! 아직 새로 나온 next.js를 많이 써보지는 않았지만 질문자님이 이해하신 개념과 비슷해 보이기는 합니다! 기존 getServerSideProps 방식은 페이지 단위로 데이터를 가져온거라면 서버 컴포넌트는 그걸 컴포넌트 단위로 할 수 있게끔 바꿔준 것 같네요. 전자의 방식은 props drilling 문제가 있어서 react-query 같은 걸 사용해서 context api에 캐싱하고 썼었습니다. 서버 컴포넌트를 사용한다면 굳이 그럴 필요는 없는 것 같네요. 베타 공식 문서를 좀 읽다보면 흥미로운 주제들이 많이 보이는데요. - deduping requests: 페이지를 렌더할때 여러 컴포넌트에서 동일한 요청을 보낼 수 있는데, 중복 요청은 제거하고 하나만 보내게끔 하는 기능 - caching - useTransition 훅을 사용한 UI blocking 하지 않는 요청 보내기 - Streaming 과 Suspense: 기존 SSR은 페이지에 필요한 데이터 페칭이 모두 끝날때까지 기다렸다가 한번에 html을 보내주는 반면, streaming과 suspense를 사용하면 데이터 페칭이 필요한 부분만 나중에 보내주는 방식 요런것들 복합적으로 잘 조합해서 기존에 사용하던 getServerSideProps 보다 더 성능이 좋은 서버사이드 렌더링을 구현할 수 있지 않을까 싶네요. 좀 더 자세한건 공식문서를 한번 쭉 훑어보시는 것을 추천드립니다! 예시 코드도 있네요 :) https://beta.nextjs.org/docs/data-fetching/fetching

이 질문 바로 가기

4. next 13 공식 문서를 읽고 있는데 이해가 잘 안되는 부분이 있어서 질문드립니다.

https://beta.nextjs.org/docs/data-fetching/fundamentals#component-level-data-fetching 이 부분에서 "Behind the scenes, React and Next.js will cache and dedupe requests to avoid the same data being fetched more than once." 라는 문구가 있는데, 이게 무슨 말인지 이해가 잘 안되어서 궁금합니다. dedupe가 무슨 뜻인가요? 중복 제거라고 자동으로 중복 요청을 다 제거해준다는 뜻인가요?


답변

안녕하세요! dedupe는 deduplication의 줄임말입니다. 중복 제거라는 의미로 쓰이는거 맞아요. 해당 문서에 링크된 상세 문서 들어가보면, 컴포넌트 레벨에서 데이터 요청을 할수 있게 되니까 같은 요청이 여러번 될 수 있는데, 이때 중복 요청이 생기면 next에서 제거해준다는 내용이네요. 기본으로 제공되는 `fetch` 를 사용할때만 별다른 설정없이 사용가능한 것 같아요. https://beta.nextjs.org/docs/data-fetching/fundamentals#automatic-fetch-request-deduping `fetch`대신 직접 요청 관리를 할 경우, react에서 제공하는 `cache` 함수를 사용해서 동일하게 구현이 가능하다고 합니다. 문서 첨부할테니 참고해보시면 좋을 것 같아요 :) https://beta.nextjs.org/docs/data-fetching/caching

외 1개 답변 보러 가기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!