강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

eddie님의 프로필 이미지
eddie

작성한 질문수

DOM에서 픽셀까지, 브라우저 렌더링과 CRP 완전 정복 - [DOM 완전 정복 Part 3]

렌더링 차단 자원 — CSS·JS 최적화 기법

렌더링 차단 리소스 관련해서 CSS 질문이 있습니다.

해결된 질문

작성

·

29

·

수정됨

0

안녕하세요? 수업 잘 듣고 있습니다.
막연하게 알고 있던 렌더링에 대해서 자세히 알 수 있어서 정말 많은 도움이 되고 있습니다.

수업을 듣다 보니 궁금한 것이 생겨서 문의 드립니다.

수업 내용중에 CSS를 <head> 태그 안에 위치 하고 최적화 전력으로 불필요한 CSS는 media속성, loadCSS, 동적으로 분리 한다고 하셨는데요.

CSS는 media속성 즉 media query를 말씀 하신 걸까요?
loadCSS와 동적으로 분리 한다고 하셨는데 이 부분들이 감이 잡히지 않아 질문 드립니다.

감사합니다.

퀴즈

DOMContentLoaded 이벤트는 언제 발생할까요?

모든 리소스 로드 후

DOM 구조 구축 완료 시

페이지가 닫히기 직전

스크립트 실행 직전

답변 2

1

nhcodingstudio님의 프로필 이미지
nhcodingstudio
지식공유자

안녕하세요 eddie님!

수업 내용 중 프론트엔드 성능 최적화의 핵심인 렌더링 차단 리소스에 대해 깊이 고민하시고 질문을 남겨주셔서 정말 반갑습니다. 막연했던 개념을 확실히 잡아가고 계신 것 같아 훌륭합니다. 브라우저가 화면을 그리는 원리와 함께 질문해주신 3가지 최적화 기법인 media 속성, loadCSS, 동적 분리에 대해 상세한 예시 코드와 함께 하나씩 확실하게 짚어드리겠습니다.

먼저 CSS가 왜 렌더링을 차단하는지 그 원리를 이해하는 것이 중요합니다. 브라우저는 HTML을 읽다가 외부 스타일시트를 불러오는 link 태그를 만나면, 이 CSS를 모두 다운로드하고 해석하여 트리를 구성하기 전까지는 화면에 아무것도 그리지 말아야겠다고 판단합니다. 이는 스타일이 적용되지 않은 날것의 HTML이 잠깐 보였다가 스타일이 입혀지는 현상을 막기 위해서입니다. 하지만 당장 첫 화면에 필요 없는 CSS까지 다운로드하느라 빈 하얀 화면만 오래 보여주는 것은 성능에 치명적이므로, 이를 해결하기 위해 질문해주신 기법들을 사용하게 됩니다.

첫 번째로 media 속성을 통한 렌더링 차단 방지 기법에 대해 설명해 드리겠습니다. eddie님이 질문하신 media 속성이 CSS 파일 내부에서 쓰는 media query를 말씀하신 것이 맞는지에 대한 대답은, 개념은 같지만 적용 위치가 다르다는 것입니다. 파일 내부의 구문이 아니라 HTML의 link 태그 자체에 media 속성을 부여하는 것을 의미합니다. 브라우저는 이 속성값을 보고 해당 CSS가 지금 당장 렌더링하는 데 필요한지를 판단하게 되는데, 아래의 실무적인 예시 코드를 보며 설명해 드리겠습니다.

<link rel="stylesheet" href="all-styles.css">

<link rel="stylesheet" href="print.css" media="print">

<link rel="stylesheet" href="desktop.css" media="(min-width: 768px)">

코드에서 보시는 것처럼, link 태그에 단순히 href로 모든 스타일을 연결해두면 무조건 다운로드가 완료될 때까지 렌더링이 멈추는 차단 현상이 발생합니다. 하지만 파일 경로 뒤에 media 속성으로 특정 조건을 달아주면, 조건에 맞지 않는 CSS는 다운로드는 하되 렌더링을 가로막지 않게 됩니다. 즉, 파일 자체를 기기나 상황에 맞게 쪼개어 최적화하는 원리입니다.

두 번째로 말씀하신 loadCSS와 관련된 비동기 CSS 로딩 기법입니다. loadCSS는 원래 특정 그룹에서 만든 자바스크립트 기반의 비동기 CSS 로더 라이브러리의 이름으로, 과거에는 CSS가 렌더링을 차단하는 것을 막기 위해 실무에서 많이 사용했습니다. 하지만 현재 모던 웹 환경에서는 이 라이브러리를 직접 가져다 쓰기보다는 HTML5 표준인 preload 속성을 활용한 패턴으로 진화했으며, 이 패턴 자체를 관용적으로 loadCSS 기법이라고 부르기도 합니다. 이 기법은 푸터 영역의 스타일이나 나중에 클릭 시 열릴 모달 창 스타일처럼 당장 첫 화면에 필요 없는 비핵심 CSS를 화면 렌더링과 동시에 뒷단에서 몰래 다운로드하는 최적화 방식입니다. 모던 loadCSS 패턴의 적용 예시 코드를 살펴보겠습니다.

<link 
  rel="preload" 
  href="non-critical.css" 
  as="style" 
  onload="this.onload=null;this.rel='stylesheet'"
>

<noscript>
  <link rel="stylesheet" href="non-critical.css">
</noscript>

코드를 보시면, 처음에는 preload 설정 덕분에 렌더링을 차단하지 않고 파일만 빠르게 다운로드하며, 완료되는 순간 자바스크립트를 이용해 실제 스타일을 화면에 적용하게 됩니다. 여기에 추가로, 사용자의 브라우저 환경에서 자바스크립트가 꺼져있을 경우를 대비한 안전장치로서 noscript 태그 안에 기존 방식의 일반적인 link 태그를 하나 더 넣어주는 방식으로 완벽하게 구현할 수 있습니다.

세 번째로 언급된 동적으로 분리하는 방식은 처음부터 HTML 문서에 link 태그를 모두 적어두는 것이 아니라, 자바스크립트를 이용해 특정 상황이 되었을 때만 필요한 CSS를 문서에 주입하는 방식입니다. React나 Next.js 같은 모던 프레임워크 환경에서 개발을 하시다 보면 번들러가 이 과정을 알아서 처리해 주는 것을 보실 수 있는데, 이를 보통 코드 스플리팅이라고 칭합니다. 바닐라 자바스크립트를 활용하여 구현하는 구체적인 예시 코드를 통해 흐름을 설명해 드리겠습니다.

// 결제하기 버튼 요소를 찾습니다.
const paymentButton = document.querySelector('#pay-btn');

// 버튼에 클릭 이벤트 리스너를 달아줍니다.
paymentButton.addEventListener('click', () => {
    // 1. 버튼을 누르는 순간 동적으로 link 태그 요소를 생성합니다.
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = '/css/payment-modal.css'; // 결제창 전용 CSS 경로
    
    // 2. 문서의 head 태그 안에 주입하여 그제야 브라우저가 다운로드하고 렌더링에 반영하게 합니다.
    document.head.appendChild(link);
    
    // 3. 이후 결제 모달창을 띄우는 로직을 실행합니다.
    openPaymentModal();
});

이 코드처럼 사용자가 결제하기 버튼을 눌렀을 때만 결제 모달창의 CSS를 로드하도록 구현할 수 있습니다. 사용자가 버튼을 누르는 순간 내부 로직에서 동적으로 새로운 link 태그 요소를 생성하고 문서에 주입하는 것입니다. 이렇게 구현하면 초기 로딩 시 무조건 다운로드해야 할 CSS 파일의 전체 크기가 확연히 줄어들기 때문에, 첫 화면이 뜨는 속도가 비약적으로 상승하는 이점을 얻을 수 있습니다.

요약하자면, 가장 첫 화면을 그리는 데 필수적인 핵심 CSS 요소들만 태그 내부에 인라인으로 삽입하거나 기본 배치로 두고, 그 외의 나머지 스타일들은 기기별로 쪼개어 media 속성을 활용하거나, preload를 이용해 뒷단에서 비동기로 몰래 받아오거나, 특정 컴포넌트가 화면에 나타날 때 자바스크립트를 통해 동적으로 분리하여 가져오도록 설계하는 것이 프론트엔드 렌더링 최적화의 핵심 전략입니다.

이러한 개념들을 직접 실습해 보시려면, 현재 작업 중이신 프로젝트나 간단한 HTML 파일을 열고 브라우저의 개발자 도구(F12)에 있는 '네트워크(Network)' 탭을 적극적으로 활용해 보시는 것을 추천해 드립니다. 처음에는 모든 CSS를 기본 link 태그로 불러올 때의 로딩 속도와 자원 다운로드 순서를 확인해 보시고, 그다음에는 오늘 설명해 드린 media 속성이나 preload, 그리고 자바스크립트를 활용한 동적 분리 기법을 코드에 하나씩 적용해 보시기 바랍니다. 네트워크 탭에서 불필요한 스타일 자원이 언제 다운로드되는지, 그리고 화면이 그려지는 시점이 어떻게 앞당겨지는지 눈으로 직접 비교해 보시면 훨씬 더 깊고 확실하게 체득하실 수 있을 것입니다.

이렇게 깊이 고민하시고 좋은 질문을 남겨주셔서 정말 감사합니다. eddie님처럼 열정적인 수강생분들이 남겨주시는 예리한 질문들은 제가 앞으로 더 좋은 강의를 제작하고 커리큘럼을 발전시키는 데 정말 큰 도움이 됩니다.

감사의 마음을 담아, 저희 우리 동네 코딩 스튜디오에서 제공하는 강의 중 추가로 필요하거나 수강하고 싶으신 강의가 있다면

확인 후 원하시는 강의의 수강 쿠폰을 기쁜 마음으로 전달해 드리겠습니다. 앞으로도 학습하시면서 궁금한 점이 생기시면 언제든 질문 남겨주세요. eddie님의 프론트엔드 학습을 항상 응원합니다!

eddie님의 프로필 이미지
eddie
질문자

답글 감사합니다.
이제 이해가 되었습니다.

말씀 주신 내용은 추후에 실험으로 적용해보겠습니다!

이 강의와 다음 강의들을 통해서 리소스를 효율적으로 다운받아서 빠르게 브라우저에 표시하는 방법들에 대해 많은 것들을 얻어 갑니다. (link tag활용, speculative parsing, script, @font-face, loading property(이미지, 오디오, iframe, video))

다시한번 답글 감사드립니다.

0

안녕하세요, 인프런 AI 인턴입니다. eddie님.

브라우저 렌더링 과정에서 CSS가 웹 페이지의 로딩 성능에 미치는 영향은 매우 중요합니다. 여러분이 질문하신 CSS 최적화 및 관련 기법들에 대해서 간단히 설명드리겠습니다.

CSS 최적화의 중요성

CSS는 브라우저가 HTML을 파싱하는 동안 스타일을 적용하기 때문에, 잘못된 위치나 방식으로 사용될 경우 렌더링을 차단할 수 있습니다. 이를 효율적으로 관리하는 것이 CRP(Critical Rendering Path)를 최적화하는 데 핵심입니다.

미디어 속성과 최적화 기법

  1. 미디어 속성 (Media Attributes):

    • ‘미디어 속성’은 <link> 태그의 media 속성을 활용하여 특정 조건에서만 CSS를 적용하게 하는 방식입니다. 예를 들어, 모바일 디바이스에서만 특정 CSS를 적용하는 media="screen and (max-width: 600px)" 같은 Media Query를 사용할 수 있습니다. 이를 통해 필요 없는 CSS 로딩을 지연시켜 렌더링 성능을 개선할 수 있습니다.
  2. LoadCSS 기법:

    • loadCSS는 CSS 파일을 비동기적으로 로드하기 위한 방법으로, 페이지가 로드될 때 CSS가 동기적으로 추가되는 것을 방지합니다. 이는 스타일시트가 렌더링을 차단하는 것을 피하게 도와줍니다. 일반적으로는 웹 성능 최적화를 위한 비동기 CSS 로딩 방식을 명시할 때 사용됩니다.
  3. 동적 분리:

    • 동적으로 CSS를 분리하는 방식은 자바스크립트를 활용하여 필요할 때만 CSS를 로드하는 방법입니다. 특정 이벤트 혹은 사용자 인터랙션 시에만 필요한 CSS를 로드하여 불필요한 CSS 로딩을 최소화하는 기법입니다.

추가 자료

위 기법들을 더 잘 이해하기 위해서는 실제 코드 예제를 참고하거나, 이를 다룬 강좌의 후속자료를 찾아보시는 것이 도움이 됩니다. 다음과 같은 관련 자료가 도움이 될 수 있습니다:
- 렌더 차단 리소스: CSS와 그 최적화 방안

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

eddie님의 프로필 이미지
eddie

작성한 질문수

질문하기