마케팅팀이 "랜딩 페이지가 구글에 안 떠요"라고 항의합니다. 개발자는 "저희 앱이 CSR이라 그래요, SSR로 바꾸거나 정적 생성해야 해요"라고 답합니다. 한편 인프라 담당은 "그럼 서버를 더 띄워야 하나요, 아니면 CDN만으로 되나요?"가 궁금합니다. 프론트엔드/백엔드의 경계와 렌더링 방식이 SEO·서버 부하·배포 형태에 어떻게 연결되는지 모르면, 이 대화의 결정을 내릴 수 없습니다.
- 1프론트엔드·백엔드·풀스택의 경계를 "어디서 실행되고 무엇을 책임지는가"로 설명할 수 있다
- 2CSR·SSR·SSG를 "HTML을 누가 언제 만드는가"로 구분할 수 있다
- 3렌더링 방식이 SEO와 초기 로딩 체감에 주는 영향을 설명할 수 있다
- 4렌더링 방식에 따라 배포 형태(CDN vs 런타임 서버)가 달라짐을 판단할 수 있다
프론트엔드 · 백엔드 · 풀스택
확대
위 그림처럼 브라우저(FE)는 UI를 담당하고 백엔드 서버(BE)는 데이터·로직·인증을 담당하며 API로 연결된다. 렌더링 방식에 따라 CDN 단독 서빙(SPA/SSG)과 런타임 서버(SSR) 중 하나를 선택한다.
실행 위치와 책임으로 나누는 경계
"프론트는 디자인, 백은 코딩"은 흔한 오해입니다. 진짜 경계는 어디서 실행되고 무엇을 책임지는가입니다.
- 프론트엔드(Frontend): 사용자의 브라우저/앱에서 실행. 화면 렌더링, 입력 처리, API 호출. (React, Vue, iOS/Android 앱)
- 백엔드(Backend): 서버에서 실행. 데이터 저장·조회, 비즈니스 로직, 인증/권한, 외부 연동, 보안. (Spring, Django, Express)
- 둘의 연결: API와 계약에서 다루는 API(주로 HTTP/REST)로 데이터를 주고받습니다.
- 풀스택(Full-stack): 한 사람/한 구성이 프론트와 백을 모두 다루는 것.
PM 관점: 하나의 기능도 "화면(FE) + 서버 로직(BE) + 둘을 잇는 API"로 쪼개집니다. 추정·일정에서 이 세 갈래를 따로 보면 누락이 줄어듭니다.
렌더링 — HTML을 누가, 언제 만드는가
확대
위 그림처럼 CSR은 브라우저가 JS로 화면을 그리고, SSR은 서버가 매 요청마다 HTML을 만들어 보내며, SSG는 빌드 시점에 완성된 HTML을 CDN에 올린다.
CSR · SSR · SSG: 화면이 그려지는 시점과 장소
같은 화면도 "HTML을 누가 언제 만드느냐"에 따라 SEO·속도·배포가 달라집니다.
- CSR(Client-Side Rendering): 서버는 거의 빈 HTML+JS를 보내고, 브라우저가 JS를 실행해 화면을 그림. 앱처럼 인터랙션이 풍부. 단, 첫 응답엔 콘텐츠가 비어 SEO·초기 체감에 불리할 수 있음.
- SSR(Server-Side Rendering): 요청 시점에 서버가 완성된 HTML을 만들어 전송 → 브라우저는 바로 콘텐츠를 보고, 이후 JS가 상호작용을 붙임(hydration). SEO·초기 체감 유리, 서버 연산 증가.
- SSG(Static Site Generation): 빌드 시점에 미리 HTML을 생성해 정적 파일로 둠. 가장 빠르고 CDN 친화적. 단, 내용이 자주 바뀌면 재빌드 필요.
| 방식 | 렌더링 시점 | 특징 |
|---|---|---|
| CSR | 서버는 빈 HTML+JS 전달, 브라우저가 그림 | 서버 연산 적음 / SEO 약함 |
| SSR | 요청마다 서버가 HTML 생성해 전송 | 서버 연산 큼 / SEO 강함 |
| SSG | 빌드 때 HTML 미리 생성, CDN이 전달 | 가장 빠름 / 갱신 시 재빌드 |
렌더링 방식과 배포 형태 — 직접 확인
확대
위 그림처럼 SEO 필요 여부·콘텐츠 변경 빈도·서버 운영 여건·초기 로딩 속도 요건을 기준으로 CSR/SSR/SSG를 결정하고, 실무에서는 Next.js로 페이지별로 혼합한다.
서버가 주는 첫 HTML에 실제 콘텐츠(텍스트·제목)가 들어 있으면 SSR/SSG, 거의 비어 있고 <div id=\"root\"></div> 같은 빈 컨테이너 + 큰 JS 번들만 있으면 CSR입니다. 인프라 준비(서버 vs CDN)를 가늠하는 단서입니다.
# 첫 응답 HTML 확인 (JS 실행 전 상태)
curl -s https://example.com/ | head -40
# 본문 텍스트가 응답에 실제로 들어있는지 검색
curl -s https://example.com/ | grep -o "기대하는 본문 키워드" | head
<!-- SSR/SSG인 경우: 콘텐츠가 그대로 보임 -->
<h1>서비스 소개</h1><p>저희는 ...</p>
<!-- CSR인 경우: 빈 컨테이너 + 번들만 -->
<div id="root"></div>
<script src="/static/js/main.8f3a.js"></script>
curl -s https://example.com/ | head -40- 첫 응답 HTML에 본문 텍스트가 보이면 SSR/SSG → 크롤러가 콘텐츠를 본다(SEO 양호). 인프라는 SSR이면 런타임 서버, SSG면 CDN으로 준비
- <div id="root"></div>만 있고 본문이 없으면 CSR → JS 실행 후에야 콘텐츠가 생김. SEO가 중요하면 렌더링 전략 변경을 개발팀과 논의
- curl 응답 크기가 작은데(빈 HTML) JS 번들이 수 MB면 CSR 특징 — 초기 로딩 체감이 느릴 수 있어 코드 분할/캐싱 검토 신호
- SSR로 판단되면 배포 시 상시 실행 서버의 헬스체크·오토스케일·메모리 한도가 필요하다(정적 CDN만으론 부족)
상황: CSR 기반 SPA(React 등)를 정적 파일로 Nginx에 배포했는데, 첫 진입은 되지만 /dashboard에서 새로고침하거나 URL을 직접 치면 404가 납니다.
원인: SPA의 라우팅은 브라우저(JS)가 처리합니다. 서버에는 /dashboard라는 실제 파일이 없어, Nginx가 그 경로의 파일을 찾다 404를 반환합니다. 첫 진입은 /로 들어와 JS가 라우팅했기에 됐던 것입니다.
진단:
curl -I https://example.com/dashboard # 404 Not Found 확인
ls dist/ # index.html만 있고 dashboard 파일은 없음
해결: 알 수 없는 경로를 모두 index.html로 보내(SPA fallback) JS 라우터가 처리하게 합니다.
location / {
try_files $uri $uri/ /index.html; # 파일 없으면 index.html로
}
SSR 앱이라면 이 문제가 없습니다(서버가 각 경로를 렌더하므로) — 이것이 렌더링 방식이 인프라 설정까지 바꾸는 예입니다.
심화 — SSR은 왜 '빠른데 느린가'
심화: 하이드레이션의 공백과 서버 렌더의 숨은 청구서
"SSR은 초기 로딩에 유리하다"까지 이해하면 다음 질문이 생깁니다 — 그런데 왜 SSR 페이지에서 화면은 떴는데 버튼이 안 눌리는 순간이 있을까요?
- 빨리 '보이는 것'과 빨리 '동작하는 것'은 다릅니다: SSR은 완성된 HTML을 먼저 보내 첫 화면은 빨리 뜨지만, 상호작용은 JS 번들이 로드되고 하이드레이션(정적 HTML에 이벤트를 연결하는 과정)이 끝나야 가능합니다. 그 사이가 "보이는데 안 눌리는" 공백입니다. JS 번들이 크면 SSR을 해도 이 공백이 길어져, 체감 개선이 기대보다 작을 수 있습니다.
- SSR 서버의 응답 시간은 백엔드 지연의 합입니다: 서버가 HTML을 만들려면 렌더에 필요한 데이터 API를 그 자리에서 기다려야 합니다. CSR이라면 껍데기 화면이라도 떴을 백엔드 지연·장애가, SSR에선 페이지 전체가 안 열리는 사고가 됩니다. 렌더 중 API 호출에는 타임아웃과 폴백이 필요합니다.
- 그래서 실무 SSR엔 캐시가 사실상 필수입니다: 로그인 전 사용자에게 같은 HTML을 준다면 몇 초짜리 페이지 캐시만으로도 렌더 부하가 급감합니다. SSG와 SSR의 중간인 ISR(미리 만들어 두고 주기적으로 재생성)은 "자주는 아니지만 가끔 바뀌는" 페이지의 절충안입니다.
- 렌더 서버는 스케일 특성이 다릅니다: HTML 조립은 CPU를 태우는 작업이라, 트래픽이 몰리면 일반 API 서버보다 먼저 포화됩니다. 오토스케일이 반응하기까지의 몇 분이 사고 구간입니다.
상황: 마케팅 푸시로 트래픽이 10배로 뛰자 SSR 랜딩 페이지가 열리지 않습니다. CDN이 주는 이미지·JS 응답은 정상인데, HTML 문서 요청만 응답이 수 초에서 타임아웃까지 늘어집니다.
원인: 모든 요청이 렌더 서버에서 HTML을 새로 만들고 있었고, 렌더마다 백엔드 API 3개를 기다렸습니다. 페이지 캐시가 없어 같은 익명 사용자용 페이지를 초당 수천 번 다시 렌더한 것입니다. 렌더 서버 CPU가 포화되며 응답이 밀리고, 오토스케일은 몇 분 늦게 반응해 그 사이 유입이 대부분 이탈했습니다.
진단:
# 정적 자산 vs HTML 문서의 응답 시간을 분리해 비교
curl -o /dev/null -s -w "%{time_starttransfer}\n" https://example.com/ # HTML: 느림
curl -o /dev/null -s -w "%{time_starttransfer}\n" https://example.com/main.js # 정적: 정상
# → HTML만 느리면 렌더 서버(또는 그 뒤 API) 병목. 렌더 서버 CPU와 백엔드 API 지연을 본다
해결: (1) 익명 트래픽에 같은 HTML을 준다면 CDN/페이지 캐시를 겁니다 — 프로모션 랜딩은 몇 초의 캐시로도 렌더 횟수가 수백분의 일로 줄어듭니다. (2) 개인화가 필요한 부분(장바구니 개수 등)만 클라이언트에서 따로 불러오는 혼합 구조로 바꿔, 문서 자체는 캐시 가능하게 유지합니다. (3) 거의 안 바뀌는 페이지는 ISR/SSG로 내려 렌더 서버 경로에서 아예 제거합니다. (4) 렌더 중 API 호출에 타임아웃·폴백을 넣어 백엔드 지연이 페이지 전면 장애로 번지지 않게 합니다. "이 페이지는 정말 요청마다 새로 만들어야 하는가"가 SSR 운영의 첫 질문입니다.
인프라 엔지니어로서 "프론트엔드 배포해 주세요" 요청을 받으면, 가장 먼저 렌더링 방식을 묻습니다. **정적 번들(CSR/SSG)**이면 S3+CDN 또는 Nginx로 끝나고 서버 비용이 거의 없습니다. SSR이면 Node 런타임 서버를 상시 띄우고 오토스케일·헬스체크·메모리 한도를 잡아야 하며, 트래픽에 비례해 비용이 듭니다. 이 한 번의 질문이 아키텍처와 클라우드 청구서를 가릅니다.
다음 모듈에서는 이런 FE/BE·렌더링 용어가 실제 채용공고·기술스택 문서에서 어떻게 나열되는지, 그 목록을 층위로 읽는 법을 다룹니다.
실전 랩으로 손에 익히기: 프론트·백엔드·렌더링 실습 — FE/BE 경계와 CSR/SSR/SSG 렌더링을 요청 흐름으로 읽습니다.
관련 모듈로 더 깊이:
- 모놀리식 vs 마이크로서비스 — FE/BE가 어떻게 나뉘고 결합되는 아키텍처 구조
- API와 계약 — 프론트와 백엔드가 주고받는 API 계약
- 기술스택 읽기 — 채용공고·기술스택 문서를 층위로 읽는 법