'use client'가 CSR이라고 알고 있는 거 아니죠? Next.js 면접질문 정복

타락한스벨트전도사·2024년 12월 6일
165
post-thumbnail

Next.js를 사용해본 주니어 개발자라면 기술 면접에서 한 번쯤 이런 질문을 받았을 겁니다.

"use client는 클라이언트 사이드 렌더링(CSR) 전용인가요?"

이 질문에 바로 확신 있게 "아니요, use client도 SSR(Server-Side Rendering)이 가능합니다!"라고 답할 수 있다면, 면접관에게 깊은 인상을 남길 수 있습니다.

이번 글에서는 SSR과 서버 컴포넌트(Server Component)를 중심으로, use client가 실제로 어떤 의미를 갖는지, 그리고 하이드레이션(Hydration) 과정이 무엇인지 명확히 정리해보겠습니다. 또한 서버 컴포넌트가 등장하기 전 '기존 리액트 컴포넌트 = 클라이언트 컴포넌트'였다는 점, 그리고 서버 컴포넌트로 인해 얻을 수 있는 퍼포먼스 이점을 살펴보며, Next.js 면접 대비에 확실한 감을 잡아보겠습니다.


SSR과 CSR, 그리고 하이드레이션 이해하기

기존의 React 앱은 CSR(Client-Side Rendering)으로 동작하는 경우가 많았습니다. 브라우저는 서버로부터 기본 HTML과 JS 번들을 받아오지만, 초기 화면에는 비어있는 <div id="root"></div>만 들어있어 사용자는 JS가 로드되고 렌더링이 끝날 때까지 빈 화면을 보게 됩니다. 이는 초기 로딩 속도를 늦추고, SEO에도 좋지 않은 영향을 줍니다.

이 문제를 해결하기 위한 방식 중 하나가 바로 SSR(Server-Side Rendering)입니다. SSR을 사용하면 서버에서 리액트 컴포넌트를 HTML로 렌더링한 뒤 클라이언트로 전송하므로, 사용자는 첫 화면 로딩 시 텅 빈 화면 대신 실제 콘텐츠가 담긴 HTML을 받을 수 있습니다. 다만, 이 HTML은 아직 인터랙션이 불가능한 "마른(Markup-only)" 상태이고, 브라우저가 자바스크립트를 로드하고 React의 하이드레이션을 거쳐 이벤트 핸들러를 등록해야 비로소 대화형 인터페이스가 완성됩니다.

하이드레이션(Hydration)이란?

하이드레이션은 서버에서 렌더링된 정적 HTML을 클라이언트 측에서 리액트의 가상 DOM과 매칭하고, 이벤트 핸들러를 연결하여 대화형 UI로 되살리는 과정입니다. 즉, SSR을 통해 미리 "형태만 있는" HTML을 받아온 뒤, 자바스크립트가 로드되고 hydrate()가 실행되면 이 HTML 구조 위에 이벤트와 상태 관리 로직이 활성화되는 것입니다.

[Server: SSR] --(HTML)--> [Browser: 초기화면 표시] 
                                      | 
                                      v 
                          (JS 로드, hydrate()) 
                                      |
                                      v
                    [Browser: 이벤트 핸들러 부착, VDOM Sync]

이제 사용자는 페이지를 로드하자마자 뭔가 볼 수 있으며, JS가 준비되면 즉시 인터랙션이 가능합니다.


서버 컴포넌트와 클라이언트 컴포넌트의 구분

React 18 이후 등장한 서버 컴포넌트는 "서버에서만 동작하는 컴포넌트"라는 새로운 패러다임을 제시했습니다. Next.js의 모든 컴포넌트는 기본적으로 서버 컴포넌트이며, 클라이언트에서 동작해야 하는 컴포넌트만 use client를 명시적으로 선언합니다.

서버 컴포넌트는 HTML 스니펫 형태로 클라이언트에 전달되며, 하이드레이션 대상에서 제외됩니다. 즉, 서버 컴포넌트가 반환하는 HTML은 "그대로" 브라우저에 삽입될 뿐, 클라이언트에서 이벤트 핸들러나 state를 주입하지 않습니다. 때문에 서버 컴포넌트는 자바스크립트 번들을 거의 소비하지 않고, 성능 최적화에 큰 도움이 됩니다.

반면 use client를 선언한 클라이언트 컴포넌트는 기존 리액트 컴포넌트처럼 동작합니다. SSR을 통해 초기 HTML을 생성하고, 이후 하이드레이션 과정을 거쳐 인터랙션을 활성화하는 방식입니다. 따라서 use client 컴포넌트도 SSR이 가능하며, SSR + CSR을 연계한 하이드레이션 프로세스를 지원합니다.


서버 컴포넌트가 등장하기 전: 모든 컴포넌트는 클라이언트 컴포넌트였다

서버 컴포넌트가 없던 시절, 리액트 컴포넌트는 모두 클라이언트에서 하이드레이션 과정을 거치는 존재였습니다. SSR을 하더라도 결국 클라이언트에선 모든 컴포넌트가 자바스크립트로 다시 로직을 주입받아야 했습니다. 이 때문에 대규모 앱에서는 번들 사이즈가 커지고, 초기 로딩 시간이 길어질 수밖에 없었죠.

서버 컴포넌트 도입 이후, "화면에 표시만 하면 되는 정적 부분"은 별도의 선언 없이 서버 컴포넌트로 처리하고, 상호작용이 필요한 부분만 use client로 선언하여 클라이언트 컴포넌트로 만들 수 있게 되었습니다. 예를 들어 마크다운을 HTML로 렌더링하거나, 파일 시스템이나 DB 접근을 통해 결과를 HTML로 만든 뒤 클라이언트에 넘기는 작업은 서버 컴포넌트가 담당하고, 사용자 이벤트 처리나 상태 관리 같은 상호작용 부분은 클라이언트 컴포넌트(use client)에 맡기는 식입니다.

이렇게 역할을 분리하면 성능 최적화가 용이해집니다.


서버 컴포넌트 동작 원리: 슬롯 삽입과 HTML 결합

서버 컴포넌트는 서버에서 렌더링된 HTML 스니펫을 제공하고, 리액트 렌더 트리는 이 위치를 "구멍(hole)"으로 남겨두었다가 해당 HTML 스니펫을 삽입하는 형태로 페이지를 완성합니다. 아래 아스키 다이어그램으로 간단히 표현해볼까요?

[Server: RSC(Render)] --> [HTML snippet] 
                                | 
                                v 
                [React Render Tree]: "구멍" 위치 마련
                                | 
                                v 
                    합친 결과 HTML --> 클라이언트 전송 
                    (서버컴포넌트는 하이드레이션 대상에서 제외)

이 과정에서 서버 컴포넌트 부분은 따로 자바스크립트 번들이 딸려가지 않습니다. 따라서 이벤트 핸들러 등록 같은 작업을 할 수 없지만, 순수 HTML만으로 충분한 부분이라면 이는 오히려 장점입니다. JS 번들 사이즈가 줄어들고, 초기 화면 표시가 더욱 빨라집니다.


면접에서 활용하기: "use client도 SSR이 가능하나요?"에 대한 자신감 있는 답변

예를 들어 면접에서 이런 질문이 나올 수 있습니다.

면접관: "use client 컴포넌트는 CSR만 하는 건가요?"

모범 답변:
"많은 분들이 오해하시는 부분인데, Next.js에서는 모든 컴포넌트가 기본적으로 서버 컴포넌트이며, use client를 명시적으로 선언한 컴포넌트만 클라이언트 컴포넌트가 됩니다. 이 클라이언트 컴포넌트들은 SSR을 통해 초기 HTML을 서버에서 렌더링한 뒤, 클라이언트에서 하이드레이션 과정을 거쳐 상태 관리나 이벤트 핸들링 기능이 활성화됩니다. 즉, use client 컴포넌트도 SSR이 가능합니다. 반면 서버 컴포넌트는 하이드레이션 과정을 거치지 않고, 순수 HTML 형태로만 제공되어 JS 번들 사이즈를 줄여주는 역할을 합니다."

이처럼 깔끔하게 설명할 수 있다면, 면접관은 지원자가 서버 컴포넌트와 SSR, 하이드레이션 개념을 명확히 이해하고 있다고 판단할 것입니다.


서버사이드 렌더링과 서버 컴포넌트는 대체 관계가 아니다

마지막으로 강조할 점은, 서버 컴포넌트가 SSR을 대체하는 것이 아니라는 사실입니다. SSR은 초기 로딩 시 사용자에게 즉시 콘텐츠를 보여주는 데 초점을 맞추는 기술이고, 서버 컴포넌트는 번들 사이즈 절감과 데이터 fetching 최적화를 위한 또 다른 레이어입니다. 둘은 상호 보완관계에 있으며, 함께 사용할 때 더욱 뛰어난 사용자 경험과 퍼포먼스를 구현할 수 있습니다.


번외: 'use server'는 무엇인가?

'use server'는 서버 컴포넌트와는 다른 개념으로, 서버 액션(Server Action)을 정의하는 데 사용됩니다. 서버 액션은 클라이언트에서 직접 서버의 함수를 호출할 수 있게 해주는 기능으로, 폼 제출이나 데이터 수정 같은 서버 사이드 작업을 처리할 때 유용합니다.


정리

  • Next.js의 모든 컴포넌트는 기본적으로 서버 컴포넌트
  • 클라이언트 컴포넌트는 use client 선언 필요
  • 클라이언트 컴포넌트도 SSR 가능: 서버에서 HTML 렌더링 후 하이드레이션
  • 서버 컴포넌트: 하이드레이션 없이 HTML만 전달 → JS 번들 감소, 성능 개선
  • 'use server'는 서버 액션을 위한 별도의 기능
  • 서버 컴포넌트는 SSR의 대체재가 아닌 보완재: 함께 사용해 최적의 사용자 경험 제공

이해한 내용을 바탕으로 실제 면접 상황에서 당당히 답변해보세요. "use client도 SSR을 한다"는 점을 분명히 하고, 서버 컴포넌트가 어떤 식으로 번들 최적화와 퍼포먼스 개선을 이끌어내는지 설명할 수 있다면, Next.js 관련 면접 질문 정복도 그리 어려운 일이 아닐 것입니다. 특히 모든 컴포넌트가 기본적으로 서버 컴포넌트이며 클라이언트 컴포넌트만 'use client'로 명시한다는 점을 강조한다면, 더욱 깊이 있는 이해를 보여줄 수 있을 것입니다.

profile
스벨트쓰고요. 오픈소스 운영합니다

18개의 댓글

comment-user-thumbnail
2024년 12월 7일

너무 깔끔하게 정리해주셔서 감사합니다 :) 사내 인턴분에게 설명을 잘하고 싶었는데, 이 링크로 대체해야 겠어요 ㅎㅎ

2개의 답글
comment-user-thumbnail
2024년 12월 10일

너무 잘 읽었습니다 :)

클라이언트 컴포넌트도 SSR 가능: 서버에서 HTML 렌더링 후 하이드레이션

이 부분에 대한 정보는 어디서 얻으셨는지 알 수 있을까요??

제가 문서에서는 해당 내용을 찾아보지 못한 것 같아서요!

1개의 답글
comment-user-thumbnail
2024년 12월 11일

use hydration 으로 바꿔서 이해하면 안 헷갈리더라고요
깔끔한 정리 감사합니다 👍

2개의 답글
comment-user-thumbnail
2024년 12월 17일

좋은내용 감사드립니다! 프론트 공부가 많이되었어요!! 혹시 개인 공부용 기술블로그에도 정리해주신 내용 남겨놓고 싶은데 혹시 출처남겨서 기재해도될까요?

1개의 답글
comment-user-thumbnail
2024년 12월 18일

잘보고갑니다!

답글 달기
comment-user-thumbnail
2024년 12월 19일

좋은 내용 감사드립니다
덕분에 공부 되었습니다 :)

답글 달기
comment-user-thumbnail
2024년 12월 20일

use client 디렉티브를 사용해도 CSR이 아니라 여전히 서버에서 렌더링됩니다.
Dynamic Import (next/dynamic) 로 동적으로 가져오는게 아니라면 NextJS 의 모든 컴포넌트는 기본적 서버에서 렌더링됩니다.
단지 상호작용이 필요한 부분 (사이드이펙트나 이벤트핸들러 등) 만 클라이언트에서 하이드레이션 될 뿐이죠.

답글 달기
comment-user-thumbnail
2024년 12월 20일

Thank you for share this information.

답글 달기
comment-user-thumbnail
2024년 12월 21일

Thank you for sharing this information.

https://mybalancenow.fun/

답글 달기