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


들어가며

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

💡 각 항목은 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 121

    • ⚠️ 교차 출처 <iframe> 이동 시 사용자 입력 일시 제한 📌
    • ✅ 스크롤바 스타일 속성
    • ✅ EditContext API
    • ✅ DOM 변경 시 포인터 이벤트 발생 동작 통일
    • ✅ Array.fromAsync
    • 🗓️ 배포 예정일
  2. Chrome 122

    • ✅ CSS 블록 요소에서 align-content 지원
    • 🗓️ 배포 예정일
  3. Chrome NEXT

    • 🚫 [Chrome 127] Mutation 이벤트 제거 📌
    • ⚠️ unload 이벤트 지원 중단 📌
    • ⚠️ CSS 구형 사용자 지정 상태 문법 지원 중단
    • ⚠️ 제3자 쿠키 지원 중단 📌
    • ✅ 내부망에 대한 하위 리소스 요청 규칙 적용

1. Chrome 121

⚠️ 교차 출처 <iframe> 이동 시 사용자 입력 일시 제한 📌

교차 출처의 <iframe>이 화면에서 이동한 경우, 사용자의 입력을 일정 시간 무시하도록 변경한다. 갑자기 화면을 이동해 사용자가 원치 않는 클릭을 하도록 유도하는 공격을 방지하기 위한 조치로, 기존에는 <iframe> 내부에서 IntersectionObserver최신 버전을 사용하는 경우에만 적용했던 기능이다.

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

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

참조


✅ 스크롤바 스타일 속성

스크롤바에 대한 스타일을 설정할 수 있는 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

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

참조


✅ EditContext API

키보드, 음성 입력, 전자펜 필기 등을 입력 받아 스크립트에서 처리할 수 있는 EditContext API를 추가한다. 지금도 contenteditable 속성을 활용해 DOM을 직접 편집할 수 있는 기능이 있으나, contenteditable은 DOM을 직접 편집하는 것에 초점을 맞춘 기능이어서 API가 깔끔하지 않다. 특히 한글과 같은 조합 문자를 입력할 때 조합 모드를 제어할 수 없는 등 기능도 제한적이다.

EditContext을 활성화하면 contenteditable처럼 해당 요소를 편집할 수 있게 변한다. 하지만 목적이 다른 API인 만큼 개발자가 직접 어떻게 입력을 처리할지는 코드로 직접 작성해야 한다.

const canvas = document.getElementById('canvas');
const editContext = new EditContext();

editContext.addEventListener('textupdate', (event) => {
  console.log(event.text);
});

canvas.editContext = editContext;
canvas.focus();

contenteditable은 HTML 컨텐츠를 가질 수 있는 요소에만 적용할 수 있으나, EditContext<canvas> 등의 요소에도 적용할 수 있다. 예시처럼 요소의 editContext 속성에 EditContext의 인스턴스를 할당해 기능을 활성화할 수 있으며, 문서의 초점이 해당 요소에 있는 동안은 EditContext에서 사용자 입력을 처리한다. 이때 해당 요소에는 input 이벤트가 발생하지 않는다.

EditContext는 DOM을 편집하는 것이 목적이 아니기에 해당 DOM을 자동으로 업데이트하지 않는다. 위 예시는 콘솔에 로그만 남길 뿐, 화면상에는 아무런 변화가 없다. 화면에 입력한 텍스트를 노출하려면 개발자가 직접 코드를 작성해야 한다.

const canvas = document.getElementById('canvas');
const editContext = new EditContext();

editContext.addEventListener('textupdate', (event) => {
  const context2d = canvas.getContext('2d');

  context2d.font = '24px Pretendard';
  context2d.strokeText(event.text);
});

canvas.editContext = editContext;
canvas.focus();

EditContext초안 문서에 따르면 현재 textupdate 이벤트 말고도 조합 모드에서 글자 형식이 변했을 때 발생하는 textformatupdate, 사용자 선택 범위가 변했을 때 발생하는 characterboundsupdate 이벤트를 추가로 사용할 수 있다.

EditContext는 아직 초안으로 세부 스펙이 바뀔 수 있음에 유의하자.

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

참조


✅ HTMLSelectElement.showPicker() 메서드 추가

HTMLSelectElement, <select> 요소에 showPicker() 메서드를 추가한다. <input type="color" />, <input type="date" /> 등의 일부 인풋 타입은 이미 사용가능한 메서드로, Chrome 121에서는 <select> 요소에도 해당 메서드를 추가할 예정이다.

기존에는 <select> 요소의 옵션 창을 간편하게 열 수 있는 방법이 없었으나, 업데이트 이후에는 아래처럼 메서드 호출로 직접 옵션 창을 열 수 있다.

const selectEl = document.getElementById('select');

selectEl.showPicker();

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

참조


✅ DOM 변경 시 포인터 이벤트 발생 동작 통일

DOM 변경으로 인해 포인터(PointerEvent) 또는 마우스 이벤트(MouseEvent) 발생 시, 브라우저 별로 동작이 다른 현상을 통일한다.

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

<div id="parentOfA">
  <span>Parent Of A</span>
  <div id="a">A</div>
</div>
<div id="b">B</div>

스크린샷

A 요소는 Parent Of A의 자식이나 화면 상에서 B 요소의 위에 위치한다. 이때 A 요소를 클릭했을 때 A 요소를 사라지게 하면 포인터 이벤트(또는 상응하는 마우스 이벤트)는 현재 크롬에서 다음과 같은 순서로 발생한다(쉬운 이해를 위해 pointerover, pointerout 이벤트는 생략했다).

pointerenter(parentOfA) -> pointerenter(A) -> pointerdown(A) -> pointerup(A) -> A 제거 -> pointerenter(B)

현재 이 동작은 크롬, 파이어폭스, 사파리가 모두 차이가 있다. 사파리는 pointerleave 이벤트를 제거된 A 요소에 발생시키며, 크롬은 포인터가 A에서 B로 이동했음을 표현하기 위해 일정 조건 동안 A 요소를 메모리에서 제거하지 않는다.

주요 브라우저는 논의를 통해 이 상황에 대한 브라우저의 동작을 통일하기로 결정했으며, 업데이트 이후에는 포인터가 제거된 A 요소의 부모에서 B 요소로 이동했음을 표현하도록 변경할 예정이다.

A 제거 -> pointerleave(parentOfA) -> pointerenter(B)

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

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

참조


✅ Array.fromAsync

Array.from()의 비동기 버전인 Array.fromAsync() 메서드를 추가한다. 열거 가능한 Promise 객체를 받아 결과를 하나의 배열 Promise로 반환한다는 점은 Promise.all()과 같으나, 다음 값을 가져오는 부분에서 차이가 있다.

const createAsyncIterable = async function* () {
  for (let i = 0; i < 5; i++) {
    await new Promise((resolve) => {
      setTimeout(resolve, 100);
    });

    yield i;
  }
};

console.time('Array.fromAsync()');
await Array.fromAsync(createAsyncIterable());
console.timeEnd('Array.fromAsync()'); // 약 500ms

console.time('Promise.all()');
await Promise.all(createAsyncIterable());
console.timeEnd('Promise.all()'); // 약 100ms

Promise.all()이 객체의 모든 요소에 한 번에 접근하는 것과 달리, Array.fromAsync()는 이전 요소가 settled 상태여야지만 다음 요소에 순서대로 접근한다.

동기 값을 넣는다면 결과를 Promise로 반환할 뿐 Array.from()과 동일하게 동작한다.

console.log(
  await Array.fromAsync(
    new Map([
      ['valueA', 1],
      ['valueB', 2],
    ])
  )
);
// [['valueA', 1], ['valueB', 2]]

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

  • Firefox: 긍정적
  • Safari: 긍정적
  • 웹 개발자: 긍정적

참조


🗓️ 배포 예정일

Chrome 1212024년 1월 17일에 정식 배포 예정이다.


2. Chrome 122

✅ CSS 블록 요소에서 align-content 지원

CSS의 align-content 속성은 flexbox의 교차축 또는 grid의 블록 축 정렬을 지정하는 속성이다. align-items가 축의 한 줄마다의 정렬을 지정하는 속성이라면, align-content는 여러 줄을 감싸는 컨텐츠 영역의 정렬을 지정하는 속성이다.

좌 - align-items, 우 - align-content

업데이트 이후에는 align-content를 블록 요소(display: block, display: list-item, display: table-cell 등)에 사용할 수 있어 수직 축 정렬을 좀 더 쉽게 할 수 있을 것으로 기대된다.

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

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

참조


🗓️ 배포 예정일

Chrome 1222024년 2월 14일에 정식 배포 예정이다.


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 이벤트 사용 시 좀 더 강력한 경고를 노출하며, 2024년 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의 미리 보기를 추가했으니 참고하자.

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

참조


⚠️ CSS 구형 사용자 지정 상태 문법 지원 중단

CSS의 사용자 지정 상태 문법은 사용자가 직접 요소의 상태를 지정해 가상 선택자 등으로 사용할 수 있는 기능으로, 현재 초안 상태다.

class MyCustomElement extends HTMLElement {
  set checked(flag) {
    if (flag) {
      this._internals.states.add('--foo');
    } else {
      this._internals.states.delete('--foo');
    }

    console.log(this._internals.states.has('--foo'));
  }
}
.custom:--foo {
  color: red;
}

기존에는 예시처럼 --foo와 같은 문법을 사용했으나, 이 문법이 현재 제안 중인 @custom-selectors 문법과 겹쳐 :state(foo)로 문법을 변경하였다.

.custom:state(foo) {
  color: red;
}

현재 Chrome 90에서 구현한 구형 문법을 사용하는 사이트는 약 0.03%로 Chrome 팀은 먼저 구형 문법을 지원 중단하기 위한 일정을 논의 중이다.

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

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

참조


⚠️ 제3자 쿠키 지원 중단 📌

제3자 쿠키(Third-Party Cookies)는 현재 도메인과 다른 도메인에서 발행한 쿠키를 말한다. 제3자 쿠키를 활용하면 사용자의 취향, 활동 정보 등을 파악할 수 있어 광고 마케팅 분야에서 자주 사용했으나, 원하지 않는 개인정보까지 유출될 수 있다는 큰 단점이 있다.

크롬은 이미 관련 법 준수를 위해 2020년 1월부터 제3자 쿠키의 중단을 예고했다. 그동안 영향이 큰 점을 고려해 지원 중단을 계속 미뤄왔으나, 2024년부터는 본격적으로 제3자 쿠키를 지원 중단할 예정이다.

구글이 대안으로 사용자의 개인정보는 보호하되, 기존의 제3자 쿠키가 하던 역할을 대체할 수 있는 Privacy Sandbox를 개발 중이니 참고하자.

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

  • Firefox: 배포 완료
  • Safari: 배포 완료
  • 웹 개발자: 복합적

참조


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

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

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

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

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

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

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

참조


이원표2023.12.20
Back to list