컨테이너 쿼리는 개발자가 반응형 디자인에 접근하는 방식을 혁신했으며 Netflix팀은 개발 간소화, 유연성 개선, 성능 향상에 미치는 큰 영향을 직접 경험했습니다. 이 게시물에서는 컨테이너 쿼리를 사용하는 주요 이점을 분석하고 이전 방법, 특히 레이아웃 제어에 JavaScript를 사용하는 방법과 비교합니다. 각 요점을 설명하는 코드 예시가 포함되어 있으며 컨테이너 쿼리를 사용하면 개발자의 작업이 훨씬 쉬워질 수 있음을 보여줍니다.
1. 단순화된 구성요소 설계, '하향식'과 '상향식'
Netflix팀이 겪은 가장 중요한 변화 중 하나는 '하향식' 설계 접근 방식에서 '상향식' 접근 방식으로 전환한 것입니다. 컨테이너 쿼리 이전에는 상위 컨테이너가 하위 컨테이너의 레이아웃 요구사항을 완전히 인식해야 했습니다. 컨테이너 쿼리를 사용하면 이 로직이 반전되어 하위 구성요소가 자체 컨테이너의 크기를 기반으로 레이아웃을 제어할 수 있습니다. 이렇게 하면 상위 요소의 역할이 간소화되고 코드의 레이아웃 로직 양이 줄어듭니다.
예: 컨테이너 쿼리와 미디어 쿼리 및 JavaScript 비교
이전 (JavaScript 필요):
/* Layout with media queries */
.card {
width: 100%;
}
@media (min-width: 600px) {
.card {
width: 50%;
}
}
@media (min-width: 900px) {
.card {
width: 33.33%;
}
}
// JavaScript to detect parent container size
const container = document.querySelector('.container');
const card = document.querySelector('.card');
function adjustLayout() {
if (window.innerWidth >= 900) {
card.style.width = '33.33%';
} else if (window.innerWidth >= 600) {
card.style.width = '50%';
} else {
card.style.width = '100%';
}
}
window.addEventListener('resize', adjustLayout);
adjustLayout();
변경 후:
/* Container Query */
.container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
이 예에서는 상위 컨테이너가 더 이상 하위 레이아웃을 관리할 필요가 없는 방법을 보여줍니다. @container
규칙을 사용하면 .card
가 즉시 컨테이너의 크기에 반응하여 레이아웃 로직을 간소화하고 JavaScript가 전혀 필요하지 않게 됩니다.
2. 복잡한 미디어 쿼리 없이 반응성
Netflix팀은 컨테이너 쿼리가 특히 모바일 중심 디자인에서 반응성을 단순화하는 방법을 발견했습니다. 복잡한 미디어 쿼리를 작성하는 대신 컨테이너 크기에 따라 조정되는 재사용 가능한 구성요소를 만들면 다양한 화면 크기와 기기에서 동적 레이아웃을 사용할 수 있습니다. 이는 모바일 트래픽이 많은 Netflix와 같은 앱에 특히 유용합니다.
예: 컨테이너 쿼리를 사용한 구성요소 응답성
변경 전:
/* Desktop versus Mobile
this only works if.sidebar is directly contained by a viewport-width element */
.sidebar {
width: 300px;
}
@media (max-width: 768px) {
.sidebar {
width: 100%;
}
}
변경 후:
/* Responsive sidebar based on container,
.sidebar can be placed in any element of any width */
.container {
container-type: inline-size;
}
.sidebar {
width: 100%;
}
@container (min-width: 768px) {
.sidebar {
width: 300px;
}
}
이제 .sidebar
는 표시 영역 기반 미디어 쿼리에 의존하는 대신 컨테이너 크기에 응답하므로 표시 영역 또는 상위 컨테이너의 크기를 알 필요 없이 동적 레이아웃에 더 자연스럽게 적응할 수 있습니다.
3. 레이아웃 관리를 위한 JavaScript 종속 항목 감소
컨테이너 쿼리 이전에는 Netflix를 비롯한 많은 팀에서 동적 레이아웃을 위해 JavaScript를 사용해야 했습니다. 창 크기를 쿼리하면 JavaScript가 레이아웃 변경을 트리거하여 복잡성과 버그 가능성을 모두 증가시킵니다. 컨테이너 쿼리는 CSS가 컨테이너 크기를 기반으로 레이아웃 반응성을 처리하도록 허용하여 이러한 필요성을 없애줍니다.
예: JavaScript 기반 레이아웃 로직 삭제
변경 전:
const cardContainer = document.querySelector('.card-container');
const cards = cardContainer.children;
function adjustLayout() {
if (cardContainer.offsetWidth > 900) {
cards.forEach(card => card.style.width = '33.33%');
} else if (cardContainer.offsetWidth > 600) {
cards.forEach(card => card.style.width = '50%');
} else {
cards.forEach(card => card.style.width = '100%');
}
}
window.addEventListener('resize', adjustLayout);
adjustLayout();
변경 후:
.card-container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
이 접근 방식은 필요한 JavaScript의 양을 줄이는 것뿐만 아니라 런타임 계산을 방지하여 성능을 개선합니다.
4. 코드가 줄고 버그가 적음
Netflix팀은 컨테이너 쿼리를 사용하면 코드 줄 수가 줄고 레이아웃 관련 버그가 줄어든다는 사실을 발견했습니다. 레이아웃 로직을 JavaScript에서 CSS로 이동하고 복잡한 미디어 쿼리의 필요성을 없애면 개발자는 유지보수가 더 쉬운 코드를 작성할 수 있습니다.
예: 레이아웃 코드 줄이기
Netflix팀은 컨테이너 쿼리를 채택한 후 CSS 코드가 크게 줄어들었음을 확인했습니다. 특정 구성요소의 경우 최대 30% 까지 줄었습니다. 동시에 하위 구성요소를 제어하는 로직을 제거하여 복잡하고 때로는 충돌이 발생하기 쉬운 여러 미디어 쿼리를 단순화하고 더 높은 수준의 관심사 분리를 달성할 수 있었습니다. 이렇게 하면 개발 속도가 빨라질 뿐만 아니라 잠재적인 장애 지점이 최소화되어 버그가 줄어듭니다.
변경 전:
/* Before with complex media queries */
.card {
width: 100%;
}
@media (min-width: 600px) {
.card {
width: 50%;
}
}
@media (min-width: 900px) {
.card {
width: 33.33%;
}
}
후
.container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
5. 개발자 환경 개선
bq. "이 덕분에 내 삶이 100배나 편해졌습니다."
컨테이너 쿼리의 가장 과소평가된 이점 중 하나는 향상된 개발자 환경일 수 있습니다. CSS가 구성요소 중심의 더 직관적인 방식으로 작동하도록 하면 개발자는 가능한 모든 레이아웃 시나리오에서 구성요소가 어떻게 작동할지 걱정하지 않고 재사용 가능한 유연한 구성요소를 빌드하는 데 집중할 수 있습니다.
Netflix팀의 한 구성원은 '이렇게 CSS가 처음부터 작동했어야 했습니다.'라고 말했습니다.
6. 폴리필 대체
이제 모든 주요 브라우저에서 컨테이너 쿼리를 사용할 수 있지만 이전 버전의 브라우저가 여전히 사용되고 있다는 우려가 있습니다. 대체는 매우 중요합니다. Netflix팀은 웹 커뮤니티 참여자가 만든 이 JavaScript 폴리필을 사용합니다. 기능 감지를 사용하면 구현이 간단합니다.
if (! CSS.supports("container-type:size")) {
/*use polyfill from
https://www.npmjs.com/package/container-query-polyfill */
}
결론
컨테이너 쿼리는 CSS의 큰 발전을 나타내며, 이를 통해 개발자는 사이트의 여러 부분에서 재사용할 수 있는 유연하고 반응형 구성요소를 더 쉽게 빌드할 수 있습니다. 레이아웃에 JavaScript를 사용하는 것을 줄이고 복잡한 미디어 쿼리를 제거하며 개발 속도를 높여 성능과 유지보수성 모두에서 상당한 이점을 제공합니다. 현재 대부분의 사용 사례는 Netflix의 Tudum 페이지에 있으며 Netflix의 다른 부분에서 컨테이너 쿼리를 사용할 계획이 있습니다. Netflix팀은 컨테이너 쿼리를 개발자 도구 상자의 퍼스트 클래스 도구로 간주하며, 더 많은 개발자가 컨테이너 쿼리의 유연성과 기능을 수용함에 따라 사용이 확대될 것입니다. 기존 구성요소를 개조하거나 완전히 새로운 구성요소를 설계할 때 컨테이너 쿼리는 반응형 디자인을 위한 더 간단하고 깔끔한 방법을 제공합니다.
아직 사용해 보지 않았다면 컨테이너 쿼리를 사용해 보세요. 예상치 못한 방식으로 워크플로가 간소화되는 것을 확인할 수 있습니다.