Next.js

CSR, SSR, CORS 에러

minsun309 2024. 9. 2. 17:46

Next.js 13에서 사용할 수있는 Server-Side Rendering (SSR) 에 대해 애기 해보고자 한다.

글을 쓰게 된 이유는 Notion.api를 활용해서 블로그를 제작해봤는데 api를 불러올때 브라우저를 통하면  CORS 에러가 나 해결방안으로 SSR을 사용했기 때문이다.

 

CORS 에러

CORS(Cross-Origin Resource Sharing) 에러는 클라이언트에서 다른 도메인에 요청을 보낼 때 발생할 수 있습니다. 이 에러는 보안상의 이유로 브라우저가 동일 출처 정책(Same-Origin Policy)을 적용하기 때문입니다.

 

Notion API

CORS 에러에 대한 해결법은 서버에서 Access-Control-Allow-Origin 설정을 Header에 해서 보내주는건데, 근데 Notion API 서버를 내가 건드릴 수 있을리가 없다.

 

방법을 찾던 중 Server-Side Rendering (SSR) 을 활용하게 되었다. 

SSR에서는 CORS 에러가 발생하지 않는 이유를 설명하기 전에  CSR과 SSR에 대해 정리해보았다.

 

클라이언트 사이드 렌더링(CSR)

CSR은 "Client-Side Rendering"의 약어로, 클라이언트 측에서 페이지를 렌더링하는 방식을 말한다. CSR은 서버로부터 받아온 데이터를 클라이언트에서 JavaScript를 통해 동적으로 조작하여 렌더링한다.

클라이언트에서 데이터를 받아오고 렌더링하기 때문에 초기 로딩 속도는 느리지만, 이후에는 페이지 이동이 빠르고 사용자 경험을 향상시키는 등의 이점이 있다.

또한 CSR은 클라이언트에서 캐시를 사용하여 적은 양의 데이터만 다시 요청하여 처리하는 것이 가능하다.

 

CSR 실행과정

1. 사용자가 웹 사이트에 요청을 보낸다.

2. CDN이 HTML 파일과 JS로 접근 할 수 있는 링크를 클라이언트로 보낸다.

3. 클라이언트는 HTML과 JS를 다운로드 받는다.

4. 브라우저 (=클라이언트) 가 자바스크립트를 다운로드 받는다. (클라이언트가 파일을 전부 다운로드하기 전까지, 웹사이트를 볼 수도, 조작할 수도 없다.)

5. 다운로드가 완료된 JS가 실행이 되며 데이터를 위한 API가 호출이 된다.

6. 서버가 API로 부터의 요청에 응답한다.

7. API로부터 받아온 데이터를 사용하여 클라이언트에서 페이지를 동적으로 렌더링하고, 페이지가 상호작용이 가능해진다.

 

CSR의 장점

  • 높은 사용자 경험: CSR은 페이지 이동 시 클라이언트에서만 렌더링이 이루어지므로, 한 번 로드된 후에는 페이지 전환 속도가 매우 빠르고, 부드러운 사용자 경험을 제공한다.
  • 캐싱 가능: 클라이언트에서 데이터를 캐시하여, 이미 로드된 데이터는 다시 요청하지 않음으로써 효율적인 데이터 사용이 가능하다.
  • 적은 서버 부하: CSR에서는 대부분의 렌더링 작업이 클라이언트에서 이루어지기 때문에, 서버의 부하가 상대적으로 적다 

 

CSR의 단점

  • 느린 초기 로딩 속도: CSR은 페이지를 렌더링하기 위해 필요한 JavaScript 파일을 먼저 다운로드한 후에 데이터를 받아와야 한다. 이로 인해 초기 로딩 속도가 느리게 느껴질 수 있다.
  • SEO에 불리함: 초기 HTML에 콘텐츠가 거의 포함되지 않기 때문에, 검색 엔진이 페이지를 크롤링할 때 콘텐츠를 인식하지 못할 가능성이 있다 
  • 낮은 보안성: 클라이언트에서 데이터를 처리하기 때문에, 데이터 조작이나 해킹 같은 보안 위협에 더 취약할 수 있다. 하지만 보안성은 일반적으로 클라이언트 측에서의 구현 방법에 따라 달라질 수 있다

=> 서버에서 처리 없이 클라이언트로 보내주기 때문에 자바스립트가 모두 다운로드 되고 실행이 끝나기 전까지 사용자는 볼 수 있는게 없다.

 

서버 사이드 렌더링(SSR)

SSR은 "Server-Side Rendering"의 약어로, 서버 측에서 페이지를 렌더링하여 완성된 HTML을 클라이언트에게 전달하는 방식입니다. 사용자는 서버에서 렌더링된 HTML을 즉시 볼 수 있어 초기 로딩 속도가 빠르고, SEO에 유리합니다. 또한, 서버에서 데이터를 처리하기 때문에 보안성 측면에서 유리할 수 있습니다. 그러나 SSR에서는 페이지 이동 시마다 서버에서 새로운 HTML을 생성해야 하므로 페이지 이동이 느릴 수 있으며, 서버 부하가 증가할 수 있습니다. 클라이언트에서는 사용자와의 상호작용(예: 버튼 클릭, 폼 제출, 동적 콘텐츠 업데이트 등)을 위해 JavaScript를 추가로 로드하여 페이지의 동적 기능을 활성화해야 합니다. 하이드레이션(Hydration) 과정을 통해 서버에서 렌더링된 HTML이 동적 기능을 가지게 되어, 완전히 상호작용이 가능한 페이지로 변환됩니다.

 

SSR 실행과정

1. 사용자가 웹 사이트에 요청을 보낸다.

2. Server는 ‘Ready to Render’ 즉시 렌더링 가능한 완성된 HTML 파일을 만든다.

3. 클라이언트에 전달하는 순간 이미 렌더링 준비가 되었기 때문에 HTML이 즉시 렌더링이 된다. 하지만 사이트에서 조작은 불가능하다.(JavaScript가 읽히기 전)

4. 브라우저(=클라이언트)가 자바스크립트를 다운 받는다. 

5. 다운로드가 이루어지고 있는 상태에서 사용자는 컨텐츠를 볼 수 있지만 사이트를 조작할 수 없다. 이때 사용자의 조작을 기억하고 있다.

6. 브라우저가 JavaScript FrameWork를 실행한다.

7. JS까지 성공적으로 컴파일되었기 때문에, 아까 기억하고 있던 사용자의 조작이 실행되고 웹 페이지는 상호작용이 가능해진다.

 

=> 서버에서 이미 '렌더 가능한' 상태로 클라이언트에 전달되기 때문에, JS가 다운로드 되는 동안 사용자는 무언가를 보고 있을 수 있다.

 

SSR의 장점

  • 빠른 초기 로딩 속도: 서버에서 완성된 HTML을 제공하기 때문에 사용자는 빠른 초기 화면을 볼 수 있다.
  • 초기 페이지 로드: 서버에서 HTML을 즉시 생성하여 클라이언트에 전달하므로, 사용자 경험이 향상된다.
  • SEO에 최적화: 서버에서 완성된 HTML을 제공하므로, 검색 엔진이 쉽게 페이지 내용을 크롤링할 수 있다. 이는 검색 엔진 최적화(SEO)에 매우 유리하며, 검색 엔진이 페이지 콘텐츠를 빠르게 인덱싱할 수 있다.
  • 보안성: 데이터 처리가 서버 측에서 이루어지므로, 클라이언트 측보다 보안 위협이 적을 수 있습니다. 하지만 보안성은 SSR 자체보다 서버의 보안 구현에 의존한다.

 

SSR의 단점

  • 느린 페이지 이동 속도: SSR에서는 페이지 이동 시마다 서버에서 새로운 HTML을 생성하여 클라이언트에 전달하기 때문에, 클라이언트 측에서 처리하는 CSR(Client-Side Rendering)보다 페이지 이동 속도가 느릴 수 있다. 
  • 낮은 사용자 경험: SR에서 페이지 이동 속도가 느릴 경우, 사용자 경험이 떨어질 수 있습니다. 하지만 SSR이 항상 낮은 사용자 경험을 제공하는 것은 아니며, 상황에 따라 SSR이 제공하는 빠른 초기 로딩 속도는 사용자 경험을 오히려 개선할 수 있습니다. 특히 초기 로드가 중요한 상황에서는 SSR이 유리할 수 있다
  • 캐싱의 복잡성: SSR에서는 매번 서버에서 HTML을 생성하기 때문에 캐싱이 필요하며, 적절한 캐싱 전략을 사용하지 않으면 서버 부하가 증가할 수 있습니다. 그러나 SSR에서도 캐싱을 효과적으로 구현할 수 있습니다. 예를 들어, CDN(Content Delivery Network)이나 서버 캐싱을 사용하여 캐싱 문제를 해결할 수 있습니다. 따라서 캐싱이 어렵다기보다는 잘 설계해야 하는 부분이다.
  • 느린 인터랙션: 초기 로딩 이후의 인터랙션이 느릴 수 있습니다. 특히, 추가 데이터를 가져와야 하는 경우에는 클라이언트 사이드에서 데이터를 처리해야 하므로, 클라이언트 측에서 추가적인 렌더링 시간이 필요할 수 있습니다. SPA(Single Page Application) 방식의 CSR에 비해 느릴 수 있다

 

SSR과 CSR의 선택 기준

SSR과 CSR 중 어떤 방식을 선택할지는 프로젝트의 요구 사항과 목표에 따라 달라진다. SEO가 중요하거나 초기 페이지 로딩 속도가 중요한 프로젝트의 경우 SSR을, 사용자 경험과 상호작용이 중요한 웹 애플리케이션의 경우 CSR을 선택하는 것이 좋다.

 

=> 이 두 방식은 상호 배타적인 것이 아니며, Next.js와 같은 프레임워크는 SSR과 CSR을 혼합한 하이브리드 접근을 제공합니다. 페이지에 따라 SSR이나 CSR을 선택적으로 사용하여 장점만을 극대화할 수 있다.

 

CSR과 SSR 비교 정리

  CSR SSR
초기 로딩 속도 느림 빠름
페이지 이동 속도 빠름 느림
SEO 불리함 유리함
보안성 낮음 높음
사용자 경험 높음 낮음
서버 부하 낮음 높음
개발 난이도 높음(복잡한 SPA 구현) 낮음(일반적인 웹 개발 )
캐싱 가능 불가능

 


 

CORS 에러와의 관계

다시 돌아와서 CORS 에러와의 관계에 대하 알아보았다.

클라이언트 사이드 렌더링(Client-Side Rendering, CSR)과 CORS

클라이언트 사이드에서 API를 호출할 때, 브라우저는 API 요청을 직접 실행한다. 이 경우 요청을 보내는 출처(도메인, 포트, 프로토콜)가 API 서버의 출처와 다르면 브라우저는 CORS 정책에 따라 요청을 차단할 수 있다. 예를 들어, example.com에서 api.notion.com으로 API 요청을 보내면 CORS 에러가 발생할 수 있다.

 

서버사이드 렌더링(Server-Side Rendering, SSR)과 CORS

서버사이드 렌더링에서는 API 호출이 사용자의 브라우저가 아닌 Next.js 서버(예: Node.js)에서 발생한다. 이 경우 CORS는 적용되지 않는다. 서버에서 다른 도메인으로 요청을 보낼 때는 브라우저의 동일 출처 정책이 적용되지 않기 때문에, CORS 에러 없이 API 요청을 정상적으로 보낼 수 있다.

 

왜 SSR에서는 CORS 에러가 발생하지 않나요?

  1. 서버 대 서버 요청: SSR에서 API 요청은 Next.js 서버에서 실행되며, 브라우저가 관여하지 않으므로 CORS 정책이 적용되지 않는다.
  2. 출처가 다르지 않음: 서버는 클라이언트가 아니므로 출처 제한이 없습니다. API 서버가 허용하지 않는 경우를 제외하고, 자유롭게 다른 도메인으로 요청을 보낼 수 있다.

결론

클라이언트에서 직접 API를 호출하면 CORS 에러가 발생할 수 있지만, SSR을 사용하면 Next.js 서버에서 API를 호출하게 되므로 CORS 문제 없이 데이터를 가져올 수 있다. 이러한 이유로, 민감한 API 호출이나 CORS 문제가 있는 경우 서버사이드 렌더링을 활용한다.