웹 개발 데일리 브리핑 — 2026-10-09
Soshy·

기준 시점: 2026-10-09 06:00 KST
조사 범위: 2026-10-08 06:00 ~ 2026-10-09 06:00 KST
추천 글 범위: 기준 시점 당시 최근 7일
1️⃣ 프론트엔드
Vercel, Routing Middleware에 Request Body 전달 생략 지원 — 대용량 요청의 전송 비용과 TTFB 개선
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- 적용 대상: Vercel Routing Middleware
- 원문: https://vercel.com/changelog/skip-sending-request-bodies-to-routing-middleware
Vercel이 Routing Middleware에 클라이언트의 Request Body를 전달하지 않도록 설정하는 skipMiddlewareRequestBody 옵션을 추가했다.
Routing Middleware는 HTTP 요청이 실제 애플리케이션 로직에 도달하기 전에 실행되는 코드다. 인증 상태 확인, URL 재작성, 리다이렉트, 국가별 라우팅, 접근 제어 등 여러 작업에 사용된다.
이러한 작업 가운데 상당수는 요청 본문을 읽을 필요가 없다.
예를 들어 사용자가 100MB 파일을 업로드하는 상황을 생각해 보자. Middleware가 확인해야 하는 정보가 세션 쿠키와 요청 경로뿐이라면 파일 데이터 자체는 필요하지 않다.
하지만 기존 구조에서는 Middleware를 실행하기 위해 Request Body가 함께 전달될 수 있었다. 파일 데이터가 클수록 실제로 사용하지 않는 데이터를 전송하는 비용이 발생한다.
이번 업데이트는 Middleware가 Request Body를 읽지 않는 애플리케이션에서 불필요한 데이터 전달을 생략할 수 있도록 한다.
vercel.json에서는 다음 설정을 사용한다.
"skipMiddlewareRequestBody": true
TypeScript 기반 프로젝트 설정인 vercel.ts에서도 동일한 이름의 속성을 사용할 수 있다.
옵션을 활성화하면 Routing Middleware에는 Request Body가 전달되지 않는다. 그러나 최종 Vercel Function이나 rewrite 대상에는 기존과 동일하게 Request Body가 전달된다.
즉 파일 업로드나 JSON 요청을 처리하는 실제 API endpoint에서 본문을 읽는 기능은 유지된다. 변경되는 것은 요청이 Middleware를 거칠 때의 데이터 전달 방식이다.
이 차이는 중요한 제약이기도 하다.
Middleware가 Request Body를 읽어야 하는 애플리케이션에서 옵션을 활성화하면 기존 코드가 필요로 하는 데이터를 사용할 수 없게 된다. 따라서 Body를 검사하거나 변환하는 Middleware에는 적용해서는 안 된다.
Vercel은 이번 변경으로 Fast Origin Transfer 사용량을 줄이고 TTFB(Time to First Byte)를 개선할 수 있다고 설명한다.
Fast Origin Transfer는 Vercel의 네트워크와 실행 환경 사이에서 데이터를 전송할 때 발생하는 트래픽과 관련된다. Middleware에서 사용하지 않는 큰 Request Body를 전달하지 않으면 그만큼 불필요한 전송을 줄일 수 있다.
특히 파일 업로드, 대용량 JSON, 이미지·동영상 처리처럼 요청 본문이 큰 서비스에서 효과를 기대할 수 있다.
다만 Vercel은 이번 발표에서 구체적인 성능 개선 수치를 제공하지 않았다. 따라서 어느 정도의 TTFB 개선이 발생하는지는 요청 크기, Middleware 실행 환경, 네트워크 구성에 따라 달라진다.
기본값은 false 다. 기존 프로젝트는 자동으로 동작이 바뀌지 않으며 옵션을 활성화한 뒤 프로젝트를 다시 배포해야 적용된다.
이번 기능은 Next.js 자체의 렌더링 방식이나 Middleware API 문법을 변경한 것은 아니다. Vercel 배포 환경에서 Middleware에 전달되는 데이터의 범위를 조정하는 플랫폼 기능이다.
2️⃣ 웹 플랫폼·브라우저·접근성
W3C, Verifiable Credentials 보안 위협 모델 5종 초안 공개 — 전자증명서 검증 과정의 신뢰 경계와 개인정보 위험 분석
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- 문서 단계: W3C Working Group Note Draft
- 원문: https://www.w3.org/news/2026/first-draft-notes-verifiable-credential-threat-models/
W3C의 Verifiable Credentials Working Group이 검증 가능한 디지털 자격 증명(Verifiable Credentials, VC) 생태계의 보안과 개인정보 보호 문제를 분석하는 위협 모델 5종을 공개했다.
Verifiable Credential은 대학 졸업증명서, 자격증, 신원 확인 정보처럼 특정 발급자가 어떤 사실을 증명하고, 이를 받은 사용자가 다른 서비스에 제출해 진위를 검증받을 수 있도록 설계된 데이터 모델이다.
일반적으로 발급자(Issuer), 보유자(Holder), 검증자(Verifier)가 서로 다른 역할을 수행한다.
예를 들어 대학이 학위 증명서를 발급하고 사용자가 이를 디지털 지갑에 저장한 뒤 채용 서비스에 제출할 수 있다. 채용 서비스는 대학이 발급한 증명서가 맞는지, 발급 이후 내용이 변조되지 않았는지 검증한다.
이때 전자서명으로 데이터의 무결성을 확인하는 것만으로 모든 보안 문제가 해결되는 것은 아니다.
증명서의 발급자를 신뢰할 수 있는지, 폐기된 증명서를 계속 사용할 수 있는지, 검증 과정에서 사용자의 활동이 추적되는지, 화면에 표시되는 정보와 실제 서명된 정보가 일치하는지 등 여러 문제가 남는다.
이번에 공개된 문서는 이러한 위협을 규격별로 나눠 분석한다.
첫 번째는 Recognized Entities Threat Model v1.0이다.
이 문서는 어떤 기관이 자격 증명을 발급하거나 검증할 권한을 가진 기관으로 인정받는지를 표현하는 체계를 다룬다.
예를 들어 검증자가 발급 기관의 전자서명을 확인했다고 해도, 그 기관이 실제로 해당 종류의 자격증을 발급할 권한을 갖고 있다는 의미는 아니다.
위협 모델은 권한 없는 발급자의 사칭, 인정 기관 목록의 변조, 목록 제공자의 사칭, 오래된 인정 상태의 사용, 지나치게 긴 신뢰 관계의 무조건적인 수용 등을 다룬다.
목록을 조회하는 행위 자체가 사용자의 활동을 노출할 수 있다는 개인정보 문제도 포함된다.
두 번째는 Data Integrity Threat Model v1.1이다.
서명된 JSON·JSON-LD 문서를 변조하거나 전자서명 검증에 사용되는 처리 과정을 공격하는 시나리오를 분석한다.
대표적인 위험은 데이터 변조, 문서 정규화 과정에서 과도한 컴퓨팅 자원을 사용하게 만드는 공격, 개인키 관리 실패에 따른 서명키 유출이다.
같은 증명서를 여러 서비스에 제출할 때 서명에 포함된 고유한 정보가 사용자를 서로 다른 서비스 사이에서 연결하는 식별자로 사용될 가능성도 다룬다.
세 번째는 Verifiable Credential Barcodes Threat Model v1.0이다.
QR코드나 바코드 형태로 제공되는 증명서를 대상으로 한다.
이 문서에서는 바코드 위조뿐 아니라 서명되지 않은 필드를 바꿔치기하는 공격, 이미 폐기된 증명서의 수용, 검증 소프트웨어 자체의 신뢰성 문제 등을 분석한다.
특히 화면에 표시된 정보 가운데 어느 부분이 실제 전자서명으로 보호되는지 사용자에게 명확히 전달하지 못하는 상황을 별도의 위험으로 다룬다.
악성 URL이 들어 있는 QR코드를 정상적인 증명서처럼 제시하는 공격과 바코드 상태 조회를 통한 사용자 추적도 포함된다.
네 번째는 Verifiable Credentials Render Method Threat Model v1.0이다.
증명서의 내용을 사용자에게 시각적으로 표시하는 과정에 초점을 맞춘다.
증명서에 포함된 데이터를 안전하게 렌더링하지 않으면 신뢰할 수 없는 콘텐츠가 실행되거나 사용자를 오도하는 화면을 만들 수 있다.
외부 템플릿이나 이미지를 가져오는 과정에서 사용자의 IP 주소와 증명서 열람 사실이 제3자에게 노출될 가능성도 분석한다.
이는 일반적인 웹 애플리케이션의 XSS 방어와 외부 리소스 접근 관리 문제와도 연결된다.
다섯 번째는 VCALM Threat Model v1.0이다.
VCALM은 자격 증명의 발급, 검증, 제출, 상태 관리 등 전체 수명주기를 HTTP API로 관리하는 모델이다.
이 문서는 발급·검증 과정에서 사용하는 URL의 유출, 인증 토큰 탈취, 잘못된 권한 범위, 상태 조회 과정의 개인정보 유출, 과도한 요청으로 인한 서비스 거부 공격 등을 분석한다.
특히 QR코드에서 읽은 URL이 예상하지 못한 애플리케이션에서 열리거나, 사용자를 공격자가 운영하는 사이트로 이동시키는 시나리오도 고려한다.
이번 발표는 새로운 브라우저 API의 출시가 아니다.
5개 문서 모두 보안·개인정보 위험을 식별하기 위한 Working Group Note Draft 단계다. W3C의 최종 권고안이나 회원사들의 공식 승인을 받은 규격이 아니며, 이후 수정되거나 대체될 수 있다.
각 문서의 GitHub 저장소를 통해 의견을 제출할 수 있다.
이번 초안은 디지털 신원 확인이나 전자증명서 서비스를 구축할 때 데이터 형식과 전자서명뿐 아니라 발급자 신뢰, 검증자의 권한, 상태 조회, 사용자 추적, UI 렌더링까지 하나의 보안 모델로 검토해야 한다는 점을 구체화한 작업이다.
GitHub, 스크린 리더의 Issue·PR 타임라인 탐색 개선 — 목록 구조와 동적 추가 항목을 음성으로 안내
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- 적용 대상: github.com, GitHub Enterprise Server 3.23
- 원문: https://github.blog/changelog/2026-10-08-screen-readers-can-navigate-timelines-as-lists/
GitHub가 Issue와 PR 타임라인을 스크린 리더에서 의미 있는 목록으로 탐색할 수 있도록 접근성을 개선했다.
GitHub의 Issue와 PR 페이지에는 댓글뿐 아니라 label 변경, 담당자 지정, milestone 변경, commit, review 등 다양한 활동 기록이 시간순으로 표시된다.
화면을 직접 보는 사용자는 이러한 기록을 스크롤하면서 필요한 내용을 찾을 수 있다. 그러나 스크린 리더 사용자에게는 단순히 여러 요소가 연속해서 존재하는 화면보다 각 요소가 어떤 목록에 속하고 현재 어디에 위치하는지 알려주는 구조가 중요하다.
이번 변경으로 스크린 리더는 타임라인을 하나의 목록으로 인식하고 전체 항목 수와 현재 위치를 안내할 수 있다.
예를 들어 53개의 활동 기록이 있는 타임라인이라면 전체 항목 수를 알 수 있고, 현재 탐색 중인 항목이 목록의 어디에 있는지 확인할 수 있다.
사용자는 VoiceOver, NVDA, JAWS 같은 보조 기술을 이용해 목록의 구조를 파악하고 항목 사이를 탐색할 수 있다.
동적으로 콘텐츠를 추가하는 상황도 개선됐다.
기존에는 긴 타임라인에서 Load more나 Load all을 선택해 활동 기록을 추가로 불러와도 스크린 리더가 새로운 항목이 나타났다는 사실을 명확하게 알려주지 않았다.
이번 변경 이후에는 콘텐츠가 추가되고 초점이 새로운 항목으로 이동하면 몇 개의 항목이 새로 불러와졌는지 음성으로 안내한다.
예를 들어 11개의 새로운 항목이 추가됐다면 해당 수를 사용자에게 전달한다.
이는 단순히 aria-label을 추가하는 문제와는 다르다.
동적으로 변하는 UI에서는 새로운 콘텐츠가 DOM에 추가됐다는 사실만으로 사용자가 그 변화를 인식할 수 있다고 가정해서는 안 된다. 새로 추가된 콘텐츠의 수와 탐색 위치를 보조 기술에 전달해야 사용자가 화면 상태를 이해할 수 있다.
이번 변경은 GitHub의 시각적 디자인이나 기존 타임라인의 일반적인 동작을 바꾸지 않는다.
적용 범위에는 Issue와 PR뿐 아니라 commit, secret scanning alert, license compliance alert의 타임라인도 포함된다.
GitHub는 github.com과 GitHub Enterprise Server 3.23에서 해당 기능을 제공한다.
3️⃣ 백엔드·인프라
Vercel Sandbox, 생성 완료 시 실행 준비까지 보장 — Snapshot 복원과 초기 명령 실행의 책임 경계 변경
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- 적용 대상: Vercel Sandbox
- 원문: https://vercel.com/changelog/sandbox-create-waits-until-ready
Vercel이 Sandbox 생성 API인 Sandbox.create()의 완료 조건을 변경했다.
Vercel Sandbox는 격리된 환경에서 코드를 실행하거나 파일을 읽고 수정할 수 있도록 제공되는 실행 환경이다.
AI coding agent가 생성한 코드를 실행하거나, 사용자가 제출한 프로그램을 검사하거나, 일시적인 개발·테스트 환경을 만드는 작업에 사용할 수 있다.
이러한 환경에서는 Sandbox 생성 직후 명령을 실행하는 경우가 많다.
기존에는 Sandbox.create()가 성공적으로 반환됐더라도 실제 실행 환경의 Snapshot 복원이 아직 완료되지 않았을 수 있었다.
따라서 개발자는 Sandbox 생성이 끝났다고 생각해도 첫 번째 명령이나 파일 작업에서 추가 대기 시간이 발생할 수 있었다.
이번 변경 이후에는 Snapshot 복원이 완료돼 명령 실행과 파일 읽기·쓰기가 가능한 상태가 되어야 Sandbox.create()가 완료된다.
즉 생성 API가 반환하는 Sandbox는 이미 실행 준비가 끝난 상태다.
이로 인해 초기화 과정에서 발생한 오류를 처리하는 위치도 달라졌다.
기존에는 Snapshot 복원에 문제가 생겼을 때 첫 번째 파일 작업이나 명령 실행 과정에서 오류가 발생할 수 있었다.
이제는 초기화에 실패하면 Sandbox.create() 자체가 오류를 반환한다.
애플리케이션은 Sandbox 생성 실패와 실제 사용자 코드 실행 실패를 보다 명확하게 구분할 수 있다.
예를 들어 생성된 코드를 테스트하는 서비스에서 Sandbox 초기화 실패를 코드 실행 실패로 잘못 기록하면 사용자가 작성한 코드에 문제가 있다고 판단할 수 있다.
두 종류의 오류를 구분하면 실행 환경 자체의 장애와 코드의 동작 오류를 분리해 관리하기 쉬워진다.
성능 측면에서는 한 가지 차이가 발생한다.
Snapshot 복원에 소요되는 시간이 첫 번째 명령 실행 단계에서 Sandbox 생성 단계로 이동했기 때문에 Sandbox.create()의 소요 시간은 오히려 조금 늘어난다.
Vercel 자체 측정에서는 생성 시간의 중앙값(P50)이 약 50ms 증가했다.
Cache되지 않은 Snapshot을 복원하는 경우에는 증가 폭이 더 클 수 있다.
그러나 Sandbox를 생성하고 첫 번째 명령을 완료하기까지의 전체 시간은 기존과 동일한 수준이라고 설명한다.
이는 실제 처리 과정이 추가됐다기보다 API가 작업 완료를 판단하는 시점이 변경됐기 때문이다.
이번 변경은 기존 Sandbox 사용자에게 자동으로 적용되며 SDK 업데이트나 별도 설정이 필요하지 않다.
새로운 실행 기능이나 성능 가속 기능보다는 Sandbox의 생성·실행 lifecycle을 더 명확하게 정의한 API 동작 변경이다.
4️⃣ 개발 도구 및 보안
Azure DevOps Wiki, Monaco Editor 기반 편집 환경 공개 — Markdown 편집과 개발 아티팩트 자동완성 개선
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- 안정화 단계: Public Preview
- 원문: https://devblogs.microsoft.com/devops/new-wiki-editor-experience/
Microsoft가 Azure DevOps Wiki의 새로운 편집 환경을 Public Preview로 공개했다.
새 편집기는 Visual Studio Code에서 사용하는 것과 같은 Monaco Editor를 기반으로 만들어졌다.
기존 Wiki 편집기는 프로젝트 문서와 Markdown 콘텐츠를 수정하는 데 필요한 기본 기능을 제공했지만, 코드 편집기에서 익숙하게 사용하는 탐색이나 자동완성 경험과는 차이가 있었다.
새 편집 환경에서는 Markdown 문서에 대한 syntax highlighting과 줄 번호가 제공된다.
문서 안에서 특정 문자열을 검색하고 변경하는 Find & Replace 기능도 Monaco Editor의 기능을 이용한다.
Undo와 Redo는 단순한 텍스트 입력뿐 아니라 문서 서식, 붙여넣기, 첨부파일과 자동완성 동작에서도 개선됐다.
개발 프로젝트와 연결된 문서를 작성할 때 사용할 수 있는 자동완성도 강화됐다.
다음과 같은 입력을 통해 관련 정보를 참조할 수 있다.
!: PR 참조@: 사용자 참조#: Work Item 참조
Wiki 문서 사이의 링크와 템플릿도 자동완성 대상에 포함된다.
단순한 Markdown 편집 기능뿐 아니라 개발 작업과 문서를 연결하는 흐름을 편집기 안에서 지원하는 방식이다.
편집 환경의 개인 설정도 유지할 수 있다.
줄바꿈 설정인 word wrap과 편집 화면·미리보기 사이의 synchronized scrolling 같은 옵션이 지속적으로 적용된다.
이번 변경의 중요한 점은 Azure DevOps Wiki를 별도의 문서 플랫폼으로 교체하지 않았다는 것이다.
기존 Wiki의 기능을 유지하면서 편집 인터페이스만 Monaco 기반으로 변경했다.
현재는 Public Preview 단계이므로 모든 사용자에게 자동으로 적용되는 정식 기능은 아니다.
Azure DevOps의 Preview features에서 개별 사용자 또는 조직 전체를 대상으로 활성화할 수 있다.
Microsoft는 새로운 편집 환경에 대한 피드백을 수집하고 있으며 일부 사용성 문제가 남아 있을 수 있다.
GitHub, PR 운영 정책 변경 — Draft PR 제한 적용과 Triage 권한의 아카이브 기능 확대
- 발표일: 2026-10-08 — 정확한 게시 시각 미확인
- Draft PR 제한 원문: https://github.blog/changelog/2026-10-08-draft-pull-requests-count-toward-pull-request-limits/
- PR 아카이브 권한 원문: https://github.blog/changelog/2026-10-08-triage-role-users-or-higher-can-now-archive-pull-requests/
GitHub가 repository maintainer의 PR 관리 부담을 줄이기 위한 두 가지 변경 사항을 공개했다.
첫 번째는 Draft PR을 repository의 PR 생성 제한에 포함할 수 있도록 한 것이다.
GitHub에서는 repository 운영자가 사용자가 생성할 수 있는 PR 수를 제한할 수 있다.
그러나 기존에는 Draft PR이 이 제한에 포함되지 않았다.
따라서 일반 PR의 생성 수를 제한했더라도 Draft 상태의 PR은 제한 없이 생성할 수 있었다.
Draft PR은 아직 review를 받을 준비가 되지 않은 변경 사항을 공유하는 데 유용하지만, 이 동작을 악용하면 대량의 Draft PR을 생성할 수 있다.
이런 PR은 repository의 목록을 복잡하게 만들고 알림이나 CI 실행을 유발할 수도 있다.
새 옵션을 사용하면 Draft PR도 일반 PR과 함께 설정된 PR 수 제한에 포함된다.
GitHub는 이를 통해 maintainer가 원하지 않는 대량의 기여 요청이나 repository spam을 관리하기 쉬워질 것으로 설명한다.
이번 변경은 모든 Draft PR의 생성을 일괄적으로 제한하는 것이 아니다.
Repository에서 PR 제한 정책을 구성할 때 Draft PR을 해당 제한에 포함할 수 있도록 선택지를 확대한 것이다.
두 번째 변경은 PR 아카이브 권한의 확대다.
기존에는 repository administrator만 PR을 아카이브할 수 있었다.
그러나 오픈소스 프로젝트나 규모가 큰 repository에서는 코드 수정 권한이 없는 Triage 담당자가 Issue와 PR을 정리하는 경우가 많다.
Spam, 중복 PR, 더 이상 진행되지 않는 PR을 정리할 때마다 관리자에게 요청해야 한다면 일상적인 유지보수 업무가 불필요하게 복잡해진다.
이번 업데이트부터는 다음 권한을 가진 사용자가 PR을 아카이브하거나 아카이브를 해제할 수 있다.
- Triage
- Write
- Maintain
- Admin
Triage 권한을 가진 사용자에게 코드 수정 권한까지 부여하지 않고도 PR 정리 업무를 맡길 수 있게 됐다.
아카이브의 동작도 더 엄격하게 변경됐다.
PR을 아카이브하면 해당 PR은 자동으로 닫히고 대화 내용이 읽기 전용 상태가 된다.
이 상태에서는 새로운 댓글이나 reaction을 추가할 수 없으며, 자동화된 도구가 작성하는 댓글도 차단된다.
기존에는 아카이브된 PR이라도 관리자에게 댓글 작성이 허용되는 경우가 있었지만, 이제는 아카이브된 대화에 새로운 활동을 추가할 수 없도록 동작을 통일했다.
아카이브된 PR은 일반 사용자에게 공개적으로 표시되지 않으며 repository administrator는 계속 확인할 수 있다.
아카이브를 해제하면 댓글과 reaction을 다시 추가할 수 있지만 PR이 자동으로 다시 열리지는 않는다.
이번 두 변경은 코드 리뷰 방식이나 PR의 병합 알고리즘을 바꾸는 기능은 아니다.
다수의 기여자가 참여하는 repository에서 PR 생성량과 정리 권한을 더 세밀하게 관리하도록 한 업데이트다.
📚 추천 글
Why I rebuilt my own website as a static site — and what changed
- 저자: Spencer Taylor
- 게시일: 2026-10-07
- 원문: https://spencer-taylor.com/static-website-case-study/
WordPress와 Divi를 사용하던 개인 웹사이트를 순수 HTML·CSS 중심의 정적 사이트로 다시 구축하면서 실제 성능과 유지보수 비용이 어떻게 달라졌는지 설명한 사례 연구다.
저자는 WordPress 전문 개발자로, 기존 사이트에서 Divi 3부터 Divi 5까지 여러 버전을 사용해 왔다.
하지만 자신의 사이트에는 시간이 지나면서 24개의 플러그인이 설치됐고, 페이지 빌더가 생성하는 CSS와 여러 extension script, 동적 렌더링 과정이 누적됐다.
실제로 사이트가 필요로 하는 기능은 복잡하지 않았다.
서비스와 포트폴리오를 소개하고, 블로그 글을 게시하며, 사용자가 문의 양식을 제출할 수 있으면 충분했다.
로그인한 사용자별로 다른 콘텐츠를 제공하거나 전자상거래와 같은 복잡한 기능을 처리할 필요도 없었다.
저자는 이 조건을 검토한 뒤 WordPress의 기능 가운데 실제로 필요한 부분보다 유지보수해야 하는 부분이 더 많다고 판단했다.
그래서 기존 URL과 콘텐츠를 유지하면서 정적 파일 기반 구조로 재구축했다.
새로운 사이트는 37개 페이지로 구성된다.
디자인 시스템은 하나의 CSS 파일에 정의하고, Python으로 작성한 약 150줄의 빌드 스크립트가 공통 header, footer, head 요소를 조립해 각 HTML 파일을 생성한다.
빌드 과정에서는 sitemap을 만들고, 정적 자산 이름에 content hash를 추가해 장기간 캐싱할 수 있도록 구성했다.
기존 URL 대부분은 그대로 유지하고 변경된 두 개의 URL에는 301 redirect를 적용했다.
프론트엔드 구성도 단순해졌다.
전체 CSS는 약 51KB이며 압축 후에는 약 10KB다.
자체 JavaScript는 약 6KB, 압축 후에는 약 2KB다. JavaScript는 테마 변경, 모바일 메뉴, 문의 양식, 블로그 필터링에 사용된다.
서버 측 처리는 문의 양식에 필요한 약 170줄의 PHP 파일 하나가 담당한다.
기존 WordPress에서 사용하던 MySQL, 관리자 로그인, XML-RPC, 여러 플러그인의 업데이트와 관리 작업은 더 이상 필요하지 않다.
저자가 공개한 Google PageSpeed Insights의 모바일 측정 결과도 흥미롭다.
| 지표 | 기존 Divi 5 사이트 | 정적 사이트 |
|---|---|---|
| 홈페이지 Performance | 78 | 98~100 |
| 홈페이지 CLS | 약 0.67 | 0 |
| 홈페이지 전송 크기 | 약 1.3MB | 약 140KB |
| 홈페이지 요청 수 | 수십 개 | 8개 |
| 관리할 플러그인 | 24개 | 0개 |
정적 사이트의 홈페이지 LCP는 약 1.35~1.4초로 측정됐다.
이 값은 저자가 자신의 사이트에서 측정한 결과이며 독립적인 통제 실험은 아니다.
기존 사이트의 성능 기록은 2026년 4월에 수집됐고 정적 사이트는 10월 6일에 측정됐다.
또한 CMS 제거뿐 아니라 디자인 재구축, 리소스 정리, 이미지 크기 지정, JavaScript 축소 등 여러 변경이 동시에 적용됐다.
따라서 모든 성능 개선을 단순히 WordPress에서 정적 HTML로 이동한 효과라고 해석해서는 안 된다.
특히 CLS 개선은 정적 렌더링 자체보다 이미지와 SVG의 크기를 명시하고 초기 레이아웃이 변경되지 않도록 설계한 영향도 크다.
저자가 실제로 강조하는 것은 성능 수치만이 아니다.
WordPress 환경에서는 최적화 이후 cache를 비우면 잠시 CLS가 개선됐다가 CSS cache가 재생성되면서 레이아웃 이동이 다시 나타나는 문제가 있었다.
새로운 구조에서는 동적으로 레이아웃을 조립하거나 많은 plugin script를 실행하는 작업 자체가 사라지면서 관리해야 하는 상태가 줄었다.
보안 측면에서도 로그인 페이지, 플러그인, XML-RPC와 같은 공격 표면이 제거됐다.
물론 정적 사이트가 모든 유형의 프로젝트에 적합한 것은 아니다.
저자는 여러 사람이 동시에 콘텐츠를 작성하고 승인해야 하는 뉴스 사이트, 사용자가 직접 페이지를 수정해야 하는 기업 홈페이지, 전자상거래나 회원 기능을 가진 서비스에는 CMS가 더 적합할 수 있다고 명확하게 설명한다.
정적 사이트에서는 콘텐츠 변경이 코드 수정과 배포 과정에 의존하기 때문이다.
이 글은 단순히 정적 사이트가 더 빠르다고 주장하는 것이 아니라 프로젝트의 실제 요구사항과 운영 주체를 기준으로 CMS의 기능성과 정적 사이트의 단순성을 비교한 사례라는 점에서 참고할 만하다.
Bridging technical depth and usability: The story behind Radar’s redesign
- 저자: Sophia Alfred, Lai Yi Ohlsen / Cloudflare
- 게시일: 2026-10-08
- 원문: https://blog.cloudflare.com/radar-redesign/
Cloudflare가 인터넷 트래픽과 장애, 보안 및 네트워크 현황을 보여주는 Cloudflare Radar를 다시 설계하면서 기술적 정보의 깊이와 일반 사용자의 이해 가능성을 어떻게 조정했는지 설명한 글이다.
Cloudflare Radar는 2020년 출시 이후 네트워크 운영자, 연구자, 보안 전문가처럼 기술적 배경이 있는 사용자들에게 활용돼 왔다.
하지만 Cloudflare는 기자, 정책 담당자, 인권 활동가, 일반 사용자도 인터넷의 상태를 이해할 수 있는 서비스로 확장하고자 했다.
이 과정에서 기존 Dashboard의 정보 구조가 문제가 됐다.
기존 첫 화면은 여러 데이터를 카드 형태로 배치하는 Bento Grid 구조를 사용했다.
인터넷 트래픽, 장애, 각종 지표를 한눈에 보여줄 수 있다는 장점이 있었지만 대부분의 카드가 비슷한 시각적 중요도를 갖고 있었다.
사용자는 어디부터 읽어야 할지 판단하기 어려웠고, 세로 방향 카드와 여러 시각화 요소가 일반적인 읽기 흐름을 방해했다.
기술적인 데이터가 많다는 점을 강조하려던 디자인이 오히려 처음 서비스를 접하는 사용자의 이해를 어렵게 만든 것이다.
Cloudflare가 선택한 해결 방식은 모든 데이터를 더 단순한 차트로 바꾸는 것이 아니었다.
대신 정보의 우선순위를 새로 정의하고 사용자가 데이터를 탐색하는 흐름을 설계했다.
새로운 첫 화면에서 가장 중요한 요소는 세계 지도다.
인터넷은 국가의 경계와 무관하게 동작하는 부분이 많지만 일반 사용자는 인터넷 활동을 지리적인 관점에서 이해하기 쉽다.
Cloudflare는 이 점을 활용해 세계 지도를 중심으로 트래픽과 인터넷 장애 정보를 배치했다.
특히 인터넷 장애를 첫 화면에서 우선적으로 보여주도록 설계했다.
장애는 일반 사용자도 즉시 이해할 수 있는 구체적인 사건이고, 특정 지역에서 인터넷이 정상적으로 작동하지 않는 상황은 뉴스나 정책 문제와도 연결되기 때문이다.
반면 트래픽 정보는 Cloudflare가 관측할 수 있는 데이터의 규모와 범위를 설명하는 역할을 맡는다.
지도 아래의 데이터 시각화 영역도 변경했다.
기존처럼 여러 차트를 한꺼번에 나열하는 대신 탭 기반의 탐색 구조로 정리했다.
사용자는 요약 통계를 먼저 확인한 뒤 관심 있는 영역을 선택해 더 구체적인 데이터로 이동할 수 있다.
이 방식은 데이터 자체를 제거하지 않으면서 첫 화면에서 사용자가 처리해야 할 정보량을 줄인다.
디자인 시스템에서도 중요한 선택이 있었다.
Cloudflare의 공개 서비스에는 크게 세 가지 형태의 인터페이스가 존재한다.
첫 번째는 브랜드와 제품을 소개하는 마케팅 페이지다.
두 번째는 블로그와 개발자 문서처럼 많은 정보를 읽고 탐색하는 콘텐츠 중심 페이지다.
세 번째는 Dashboard와 같은 실제 제품 인터페이스다.
Radar는 세 유형의 성격을 모두 가지고 있다.
일반 사용자가 접근하기 쉬워야 하지만 기술적으로 정확한 정보를 제공해야 하고, 많은 데이터를 탐색하는 기능도 유지해야 한다.
Cloudflare는 이 세 가지 특성을 조합했다.
마케팅 페이지의 접근성과 시각적 친숙함, 콘텐츠 페이지의 명확한 정보 구조, 제품 인터페이스의 유지보수성과 재사용성을 함께 적용했다.
구현에서는 Cloudflare가 사용하는 Kumo 컴포넌트 시스템으로 이전하는 방향을 선택했다.
이 과정을 통해 Radar만을 위한 독립적인 컴포넌트를 계속 만드는 대신 조직의 공통 UI 체계와 연결하려 했다.
디자인 과정에서 실패한 시도도 공개했다.
초기의 지도 시안은 지나치게 많은 데이터를 담고 있었다.
기술적인 정보를 충분히 보여주면 서비스의 신뢰성이 높아질 것이라고 판단했지만 실제로는 읽기 어려운 화면이 됐다.
반대로 이후의 시안은 마케팅 페이지처럼 시각적으로 단순하고 친숙했지만 실시간 데이터를 보여주는 서비스가 아니라 정적인 홍보 페이지처럼 느껴지는 문제가 있었다.
최종 디자인은 두 접근의 중간을 선택했다.
실시간 데이터의 특성을 유지하면서도 처음 방문한 사용자가 무엇을 보고 있는지 이해할 수 있도록 조정한 것이다.
다만 이 글에는 사용성 테스트의 구체적인 수치나 재설계 전후의 실제 사용자 성과를 비교한 정량 데이터가 없다.
따라서 새 디자인이 모든 사용자 집단에서 객관적으로 더 우수하다고 단정할 수는 없다.
그럼에도 복잡한 데이터를 제공하는 웹 애플리케이션에서 정보의 깊이를 유지하면서 탐색 부담을 줄이는 설계 과정을 실제 사례로 설명한다.
분석 Dashboard, 모니터링 서비스, 관리자 페이지처럼 한 화면에서 많은 데이터를 다루는 프론트엔드 애플리케이션을 설계할 때 참고할 만한 글이다.
Reading and Writing ZIP Files in Node Without a Library
- 저자: OpenReplay Team
- 게시일: 2026-10-07
- 원문: https://blog.openreplay.com/zip-files-node/
Node.js 26.8.0부터 제공되는 내장 ZIP 처리 API를 이용해 외부 라이브러리 없이 압축 파일을 읽고 생성하는 방법을 설명한 글이다.
Node.js에는 오랫동안 node:zlib이 존재했지만 일반적인 ZIP archive를 읽고 생성하려면 yauzl, archiver, adm-zip 같은 외부 패키지를 사용하는 경우가 많았다.
이 패키지들은 각각 streaming read, archive generation, 메모리 기반 처리 등 서로 다른 기능을 제공한다.
하지만 파일 업로드를 처리하거나 배포 artifact를 생성하는 서비스에서는 압축 파일을 처리하기 위해 여러 dependency를 유지해야 한다는 부담이 있었다.
Node.js 26.8.0은 node:zlib에 새로운 ZIP 처리 API를 추가했다.
주요 API는 다음과 같다.
ZipFile: 파일시스템에 존재하는 ZIP archive를 읽는 인터페이스ZipBuffer: 메모리에 올라온 ZIP 데이터를 처리하는 인터페이스ZipEntry: ZIP archive 안의 개별 파일이나 디렉터리를 표현하는 객체createZipArchive(): 여러 entry를 ZIP archive로 생성하는 함수
새로운 API를 사용하면 파일 내용을 메모리에 모두 올리는 방식뿐 아니라 stream을 이용해 큰 압축 파일을 순차적으로 처리하는 방식도 사용할 수 있다.
예를 들어 ZipFile.open()으로 압축 파일을 연 뒤 각 entry를 순회할 수 있다.
ZipEntry.content()는 압축이 해제된 데이터를 하나의 Buffer로 반환한다.
작은 파일에서는 편리하지만 파일의 크기가 크면 그만큼 메모리를 사용해야 한다.
반면 contentIterator()는 데이터를 여러 Buffer chunk로 나눠 반환한다.
따라서 전체 파일을 메모리에 올리지 않고 Node.js의 pipeline()을 이용해 디스크에 순차적으로 기록할 수 있다.
문제는 stream을 사용한다고 해서 압축 파일의 모든 보안 문제가 자동으로 해결되지는 않는다는 점이다.
대표적인 위험은 ZIP Bomb이다.
ZIP Bomb은 압축된 크기는 작지만 압축을 해제하면 매우 큰 데이터가 생성되도록 구성된 파일이다.
이를 제한 없이 처리하면 서버의 메모리나 디스크 공간이 고갈될 수 있다.
Node.js는 setMaxZipContentSize()를 이용해 content()처럼 Buffer로 읽는 작업에 기본 크기 제한을 설정할 수 있다.
그러나 contentIterator()는 데이터를 작은 단위로 읽기 때문에 이 전역 설정의 영향을 받지 않는다.
Streaming API에서는 별도의 maxSize 옵션과 entry 크기 검사를 적용해야 한다.
또 다른 중요한 위험은 Zip Slip이다.
악성 ZIP archive에는 다음과 같은 파일 경로가 포함될 수 있다.
../../etc/passwd
이 경로를 검증하지 않고 지정된 출력 디렉터리에 연결하면 공격자가 의도한 위치에 파일을 기록할 수 있다.
Node.js의 새로운 내장 ZIP API는 이런 경로를 자동으로 거부하지 않는다.
따라서 개발자는 archive 안의 각 entry 이름을 절대경로로 변환한 뒤 최종 경로가 허용된 출력 디렉터리 안에 존재하는지 확인해야 한다.
Symbolic link 역시 주의해야 한다.
압축 파일 안의 symbolic link를 그대로 복원하면 허용된 디렉터리 밖을 가리키는 파일을 생성할 수 있다.
글에서는 신뢰할 수 없는 archive를 처리할 때 symbolic link entry를 건너뛰는 방식을 소개한다.
ZIP 생성 과정에서는 ZipEntry.create()와 ZipEntry.createStream()을 구분한다.
전자는 개별 파일 내용을 메모리 기반으로 처리할 수 있고, 후자는 큰 파일을 stream으로 압축할 때 사용할 수 있다.
다만 Streaming entry는 한 번 소비하면 동일한 stream을 다시 읽을 수 없다는 제약이 있다.
또한 ZIP archive에는 같은 이름을 가진 entry가 여러 개 들어갈 수 있다.
createZipArchive()는 중복된 이름을 자동으로 제거하지 않기 때문에 archive를 생성하는 애플리케이션에서 entry 이름의 중복 여부를 직접 관리해야 한다.
호환성도 중요한 문제다.
이 기능은 Node.js 26.8.0에서 도입된 Experimental API다.
글 작성 시점의 Node.js 24 LTS에는 포함되지 않았으며, Stable API로 확정된 것도 아니다.
따라서 production 환경에서 사용하려면 Node.js 버전을 고정하고 향후 API 변경 가능성을 고려해야 한다.
현재 LTS 환경을 사용하는 서비스에서는 yauzl이나 archiver 같은 기존 라이브러리를 계속 사용하는 편이 현실적일 수 있다.
이 글은 새로운 내장 API의 사용법에 그치지 않고 메모리 사용량, streaming, 파일 경로 검증, 압축 해제 크기 제한, 기존 LTS와의 호환성까지 연결해 설명한다.
서버에서 파일 업로드를 처리하거나 ZIP 형태의 결과물을 다운로드하도록 제공하는 웹 서비스를 개발한다면 참고할 만한 내용이다.