프런트엔드 개발에 가장 많은 영향을 주는 크롬 브라우저의 버전별 변경 예정 항목을 정리 및 공유한다.
💡 각 항목은 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를 그대로 인용했다.
<iframe> 이동 시 사용자 입력 일시 제한 📌<iframe> 이동 시 사용자 입력 일시 제한 📌교차 출처의 <iframe>이 화면에서 이동한 경우, 사용자의 입력을 일정 시간 무시하도록 변경한다. 갑자기 화면을 이동해 사용자가 원치 않는 클릭을 하도록 유도하는 공격을 방지하기 위한 조치로, 기존에는 <iframe> 내부에서 IntersectionObserver의 최신 버전을 사용하는 경우에만 적용했던 기능이다.
이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
스크롤바에 대한 스타일을 설정할 수 있는 scrollbar-color와 scrollbar-width 속성의 미리 보기를 추가한다.
scrollbar-color 속성은 스크롤바의 색상을 결정하며, 첫 번째 값은 스크롤바의 thumb, 두 번째 값은 스크롤바의 track 색상으로 사용한다.
.scroll {
width: 300px;
height: 100px;
overflow-y: scroll;
scrollbar-color: lightcoral pink;
}scrollbar-width 속성은 스크롤바의 너비를 결정하며, auto | thin | none을 값으로 설정할 수 있다. 아직 숫자값은 사용이 불가능해 적극적인 사용은 어려워 보이나, none 값을 설정하면 간단하게 네이티브 스크롤바를 없앨 수 있다는 점은 장점이다.
이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
키보드, 음성 입력, 전자펜 필기 등을 입력 받아 스크립트에서 처리할 수 있는 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, <select> 요소에 showPicker() 메서드를 추가한다. <input type="color" />, <input type="date" /> 등의 일부 인풋 타입은 이미 사용가능한 메서드로, Chrome 121에서는 <select> 요소에도 해당 메서드를 추가할 예정이다.
기존에는 <select> 요소의 옵션 창을 간편하게 열 수 있는 방법이 없었으나, 업데이트 이후에는 아래처럼 메서드 호출로 직접 옵션 창을 열 수 있다.
const selectEl = document.getElementById('select');
selectEl.showPicker();이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
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)이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
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()'); // 약 100msPromise.all()이 객체의 모든 요소에 한 번에 접근하는 것과 달리, Array.fromAsync()는 이전 요소가 settled 상태여야지만 다음 요소에 순서대로 접근한다.
동기 값을 넣는다면 결과를 Promise로 반환할 뿐 Array.from()과 동일하게 동작한다.
console.log(
await Array.fromAsync(
new Map([
['valueA', 1],
['valueB', 2],
])
)
);
// [['valueA', 1], ['valueB', 2]]이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
Chrome 121은 2024년 1월 17일에 정식 배포 예정이다.
CSS의 align-content 속성은 flexbox의 교차축 또는 grid의 블록 축 정렬을 지정하는 속성이다. align-items가 축의 한 줄마다의 정렬을 지정하는 속성이라면, align-content는 여러 줄을 감싸는 컨텐츠 영역의 정렬을 지정하는 속성이다.
업데이트 이후에는 align-content를 블록 요소(display: block, display: list-item, display: table-cell 등)에 사용할 수 있어 수직 축 정렬을 좀 더 쉽게 할 수 있을 것으로 기대된다.
이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
Chrome 122은 2024년 2월 14일에 정식 배포 예정이다.
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 이벤트는 해당 문서를 떠나거나 하위 리소스를 메모리에서 해제할 때 발생하는 이벤트이다. 이 이벤트를 이용하면 사용자가 페이지를 종료하기 전에 특정 동작을 실행할 수 있다.
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의 사용자 지정 상태 문법은 사용자가 직접 요소의 상태를 지정해 가상 선택자 등으로 사용할 수 있는 기능으로, 현재 초안 상태다.
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 팀은 먼저 구형 문법을 지원 중단하기 위한 일정을 논의 중이다.
이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
제3자 쿠키(Third-Party Cookies)는 현재 도메인과 다른 도메인에서 발행한 쿠키를 말한다. 제3자 쿠키를 활용하면 사용자의 취향, 활동 정보 등을 파악할 수 있어 광고 마케팅 분야에서 자주 사용했으나, 원하지 않는 개인정보까지 유출될 수 있다는 큰 단점이 있다.
크롬은 이미 관련 법 준수를 위해 2020년 1월부터 제3자 쿠키의 중단을 예고했다. 그동안 영향이 큰 점을 고려해 지원 중단을 계속 미뤄왔으나, 2024년부터는 본격적으로 제3자 쿠키를 지원 중단할 예정이다.
구글이 대안으로 사용자의 개인정보는 보호하되, 기존의 제3자 쿠키가 하던 역할을 대체할 수 있는 Privacy Sandbox를 개발 중이니 참고하자.
이 항목에 대한 주요 브라우저 및 웹 개발자의 의견은 다음과 같다.
내부망 접근 규칙(Local Network Access) 적용의 일부로 하위 리소스(.js, .css 등)를 요청할 때 내부망(사설 IP, localhost)에 대한 접근 제한을 검토 중이다. 정식 적용 일정은 불투명하나, 미리 보기로 일부 기능을 체험할 수 있다.
공개 웹 사이트(공개 IP로 접근 가능한 사이트)에서 내부망에 하위 리소스(.js, .css 등) 요청 시 반드시 보안 컨텍스트(HTTPS)를 사용하도록 제한한다. 내부망의 하위 리소스에 접근하려면 보안 컨텍스트를 사용하도록 변경해야 한다.
Chrome 86 이상에서 실험적 웹 기능을 활성화해 접근 제한을 미리 체험할 수 있다.
내부망에 하위 리소스 요청 시 사전 요청을 보내 연결 허용 여부를 먼저 묻는다. 현재는 사전 요청 실패 시 개발자 콘솔에 경고만 노출한다.