[실전 서버리스 05] 프론트와 백엔드를 한 배포로, Static Assets 통합

전통적인 웹 개발에서는 프론트엔드와 백엔드가 따로였다. 프론트는 이 서버, 백엔드는 저 서버, 배포도 각각 했다. 그런데 워커스의 최근 방향은 이 둘을 하나로 합치는 것이다. 한 워커가 정적 파일도 서빙하고 동적 API도 처리한다. 이번 편은 이 정적 자산 통합이 무엇이고 왜 편한지를 다룬다.


이 통합은 개인 개발자에게 특히 반갑다. 관리할 배포가 하나로 줄고, 프론트와 백엔드가 한 곳에 있어 연결이 매끄럽기 때문이다.

1. 정적 자산 서빙이란

정적 자산은 서버가 코드로 만들어내지 않고 그냥 그대로 내주는 파일이다. HTML, CSS, 자바스크립트, 이미지, 폰트 같은 것들이다. 이것들은 요청이 올 때마다 새로 만들 필요가 없으니, 저장해뒀다가 그대로 돌려주면 된다.


워커스는 이 정적 자산을 함께 올려두고 서빙하는 기능을 제공한다. 정적 파일 요청이 오면 코드를 거치지 않고 바로 그 파일을 내준다. 이러면 빠르고 효율적이다. 코드 실행 없이 파일만 돌려주니 CPU 시간도 거의 안 쓴다.


동시에 같은 워커가 동적 요청도 처리한다. 정적 파일에 없는 주소로 요청이 오면 코드가 그걸 받아 처리한다. 즉 하나의 워커가 파일 서버이자 애플리케이션 서버 역할을 겸한다. 요청의 성격에 따라 정적으로 응답할지 코드로 응답할지가 갈린다.


정적 자산 서빙이 CPU 시간을 거의 안 쓴다는 게 비용 면에서 중요하다. 앞서 CPU 시간 과금을 다뤘는데, 정적 파일을 그대로 내주는 건 연산이 거의 없어 비용이 미미하다. 사이트의 많은 요청이 정적 자산인 걸 생각하면, 이 부분이 저렴한 건 전체 비용에 큰 도움이 된다.


조금 더 짚으면, 정적과 동적을 한 워커가 다룬다는 게 아키텍처를 근본적으로 단순화한다. 예전의 정적 서버 더하기 앱 서버 더하기 그 사이 연결이라는 3단 구조가, 워커 하나로 압축된다. 관리할 구성 요소가 줄면 장애 지점도 줄고, 이해하기도 쉽다. 단순한 아키텍처가 곧 튼튼한 아키텍처다.


한 가지 더, 정적 자산을 워커가 서빙하면 배포와 함께 자산이 전 세계 엣지로 퍼진다. 그래서 이미지나 스크립트 같은 자산도 사용자 가까이서 빠르게 전달된다. 별도의 콘텐츠 전송망을 붙이지 않아도, 자산이 자연히 엣지에 캐시되어 빠르게 나간다. 통합이 성능까지 함께 챙겨주는 셈이다.

2. 왜 한 배포가 좋은가

프론트와 백엔드를 한 배포로 묶으면 여러 이점이 있다. 첫째, 관리가 단순해진다. 두 개의 배포를 각각 신경 쓸 필요 없이 하나만 관리하면 된다. 개인 개발자에게 관리 대상이 반으로 주는 건 큰 이점이다.


둘째, 프론트와 백엔드 사이 연결이 매끄럽다. 따로 배포하면 프론트가 백엔드 주소를 알아야 하고, 도메인이 다르면 교차 출처 문제도 생긴다. 한 배포에 있으면 같은 도메인 안에서 프론트가 백엔드 API를 부르니 이런 문제가 없다. 설정이 단순해진다.


셋째, 배포가 원자적이다. 프론트와 백엔드를 따로 배포하면 한쪽만 업데이트돼 서로 안 맞는 순간이 생길 수 있다. 한 배포로 묶으면 둘이 항상 같이 올라가니 그런 불일치가 없다. 배포 중 어정쩡한 상태가 사라지는 것이다.


한 배포의 이점 중 원자성을 조금 더 짚으면, 이건 사고를 줄인다. 프론트와 백엔드를 따로 배포하다 보면 한쪽만 올라가 잠깐 서로 안 맞는 순간이 생기고, 그 틈에 사용자가 이상한 상태를 겪는다. 한 배포는 이 틈을 없앤다. 배포 중 어정쩡한 상태가 없으니 그만큼 안정적이다.

3. 라우팅 우선순위

한 워커가 정적 파일과 동적 요청을 함께 다루니, 어떤 요청을 어느 쪽으로 보낼지 순서를 정해야 한다. 보통은 정적 자산을 먼저 확인하고, 거기 없으면 코드로 넘긴다. 요청 주소에 해당하는 정적 파일이 있으면 그걸 내주고, 없으면 동적 라우팅이 처리하는 식이다.


이 순서를 잘 정하는 게 중요하다. 예를 들어 글 상세 페이지 같은 동적 주소는 정적 파일이 없으니 코드로 넘어가야 하고, 스타일시트 같은 건 정적 파일로 바로 나가야 한다. 이 분기를 명확히 해두면 정적은 빠르게, 동적은 코드로 깔끔하게 처리된다.


내 커뮤니티에서도 이 구조를 쓴다. 페이지의 기본 골격과 스타일, 스크립트는 정적 자산으로 두고, 글 데이터나 API 응답은 코드가 만든다. 사용자가 페이지를 열면 정적 골격이 빠르게 뜨고, 그 안의 데이터는 동적으로 채워진다. 정적과 동적의 장점을 함께 취하는 것이다.


라우팅 우선순위를 잘못 잡으면 생기는 문제도 있다. 동적 주소인데 정적으로 처리하려다 엉뚱한 파일이 나가거나, 정적 파일인데 코드로 넘어가 불필요한 연산이 도는 식이다. 그래서 정적과 동적의 경계를 명확히 긋는 게 중요하다. 어떤 주소가 어느 쪽인지를 분명히 정의해두면 이런 혼선이 없다.


라우팅 우선순위를 정할 때 나는 정적 우선, 없으면 동적이라는 원칙을 뒀다. 대부분의 정적 자산은 정해진 경로에 있고, 동적 처리는 그 외의 주소를 받는 식이다. 이 명확한 규칙 하나로 요청이 헤매지 않고 제 갈 길을 간다. 규칙이 단순할수록 예외 상황에서도 예측 가능하게 동작한다.

4. Pages와의 관계

클라우드플레어에는 원래 정적 사이트 배포에 특화된 페이지스라는 서비스가 따로 있었다. 프론트엔드 정적 사이트를 올리기 좋은 도구였다. 그런데 워커스가 정적 자산 서빙까지 품으면서, 이제는 새 풀스택 프로젝트라면 워커스로 통합하는 게 권장 방향이 됐다.


둘의 관계를 정리하면, 페이지스는 정적 위주 사이트에 여전히 쓸 수 있지만, 프론트와 백엔드를 함께 다루는 풀스택이라면 워커스가 상위 호환에 가깝다. 그래서 지금 새로 시작한다면 워커스 기반으로 정적 자산을 통합하는 방식을 고려하는 게 좋다. 이 이전과 선택은 마지막 편에서 더 다룬다.


내가 사이트를 만들 때는 이 두 가지가 섞인 구조로 시작했는데, 방향은 점점 워커스 통합 쪽으로 정리되는 추세다. 어느 쪽이든 핵심은 프론트와 백엔드를 한 흐름으로 다룬다는 것이다. 도구의 이름보다 이 통합의 개념을 이해하는 게 중요하다.


페이지스와 워커스의 관계가 헷갈릴 수 있는데, 실용적으로는 지금 새로 시작하면 워커스 통합을 보라는 정도로 정리하면 된다. 두 도구의 세부 차이를 다 알 필요 없이, 프론트와 백엔드를 한 흐름으로 다룬다는 개념만 잡으면 어느 쪽을 쓰든 응용된다. 도구는 바뀌어도 통합의 원리는 남는다.

5. 통합이 주는 개발 경험

프론트와 백엔드가 한 프로젝트, 한 배포에 있으면 개발 경험이 매끄럽다. 코드를 한 곳에서 관리하고, 한 번에 배포하고, 로컬에서 한꺼번에 테스트한다. 프론트를 고치고 백엔드를 고치고 각각 배포하며 맞추는 번거로움이 없다.


특히 혼자 개발하는 개인에게 이 통합은 인지 부담을 크게 줄여준다. 여러 프로젝트를 오가며 맥락을 전환할 필요 없이, 한 프로젝트 안에서 프론트와 백엔드를 오간다. 작은 사이트일수록 이 단순함의 값어치가 크다. 관리할 게 적어야 오래 유지할 수 있다.


정리하면 워커스의 정적 자산 통합은 프론트와 백엔드를 한 배포로 묶어, 관리를 단순화하고 연결을 매끄럽게 하며 배포를 원자적으로 만든다. 다음 편에서는 이 모든 걸 다루는 도구, 랭글러를 제대로 파고든다. 설정, 바인딩, 시크릿까지 서버리스 개발의 작업대를 정리한다.


통합이 개인 개발자의 인지 부담을 줄인다는 게 생각보다 큰 값어치다. 혼자 개발하면 머릿속에 담을 맥락이 한정돼 있는데, 프로젝트가 하나로 통합되면 그 맥락이 단순해진다. 프론트와 백엔드를 오가며 전환하는 비용이 줄고, 그만큼 실제 개발에 집중할 수 있다. 단순함이 곧 지속 가능성이다.


통합의 개발 경험을 한마디로 하면 맥락이 하나라는 것이다. 프론트를 고치다 백엔드로 넘어가도 같은 프로젝트, 같은 배포 안이라 흐름이 끊기지 않는다. 여러 저장소와 배포를 오가며 맥락을 전환하던 피로가 사라진다. 개인 개발자에게 이 끊김 없는 흐름은 생산성 이상의, 개발을 즐겁게 하는 요소다.


덧붙이면, 이 통합 구조는 앞서 SEO 시리즈에서 강조한 서버 사이드 렌더링과도 자연스럽게 맞물린다. 같은 워커가 봇에게는 서버에서 완성한 HTML을, 사람에게는 그 위의 동적 경험을 준다. 프론트와 백엔드가 한 곳에 있으니 이 이중 렌더링을 구현하기도 쉽다. 통합이 SEO 대응까지 매끄럽게 해주는 셈이다.


또 하나 실무적으로, 정적 자산에는 적절한 캐시 헤더를 붙이는 게 좋다. 자주 안 바뀌는 자산은 오래 캐시하고, 자주 바뀌는 건 짧게 캐시하는 식이다. 그래야 사용자가 매번 새로 받지 않고 캐시된 걸 빠르게 쓴다. 단 자산을 바꿨을 땐 캐시가 갱신되게 버전 표시를 붙여야 옛 버전이 남지 않는다.