티스토리 뷰

반응형

이 글에서는 웹 페이지 로딩 과정에서 발생하는 FOUC(Flash of Unstyled Content)와 FOUT(Flash of Unstyled Text) 현상에 대해 알아보고, 브라우저 렌더링 원리를 이해하고 이를 극복하는 최적화 전략을 소개합니다.

 

FOUC(Flash of Unstyled Content)와 FOUT(Flash of Unstyled Text)

FOUC와 FOUT은 웹 페이지 로딩 과정에서 일시적으로 스타일이 적용되지 않은 콘텐츠와 텍스트를 사용자에게 보여주는 현상입니다. 두 현상 모두 스타일 로드 및 적용 시점과 브라우저 렌더링 시점 간의 차이 때문에 발생합니다. FOUC는 일반적인 콘텐츠에, FOUT은 웹 폰트에 대한 스타일 적용 지연 때문에 발생합니다.

 

FOUC - 일반적인 콘텐츠

FOUC

브라우저가 HTML 문서를 파싱하고 DOM 트리를 구성하는 동안, 외부 CSS 파일이 아직 로드되지 않았을 때 발생합니다. 이로 인해 브라우저는 초기에 스타일이 적용되지 않은 콘텐츠를 화면에 표시하게 됩니다. 외부 CSS 파일이 로드되고 파싱되어 CSSOM 트리가 만들어지면, 렌더 트리가 업데이트되고 스타일이 적용된 콘텐츠가 표시됩니다. 이 과정에서 사용자는 잠시 스타일이 적용되지 않은 콘텐츠를 볼 수 있게 됩니다.

 

11초 짤예시 (FOUC)

 

FOUT - 웹 폰트에 대한 스타일 적용 지연

FOUT

웹 폰트를 사용하는 경우, 브라우저가 웹 폰트 파일을 다운로드하고 파싱하는데 시간이 걸릴 수 있습니다. 웹 폰트가 아직 로드되지 않았을 때, 브라우저는 시스템 기본 폰트를 사용하여 텍스트를 먼저 렌더링합니다. 웹 폰트가 로드되면, 브라우저는 렌더 트리를 업데이트하여 웹 폰트를 적용한 텍스트를 표시하게 됩니다. 이 과정에서 사용자는 잠시 웹 폰트가 적용되지 않은 텍스트를 볼 수 있게 됩니다.

 


 

FOUC, FOUT 발생 단계 (브라우저 렌더링 원리를 곁들인)

브라우저는 HTML, CSS, JavaScript 파일을 로드하여 웹 페이지를 렌더링합니다. HTML은 페이지의 구조를 정의하고, CSS는 스타일을 적용하며, JavaScript는 동작을 추가합니다. 이 과정에서 브라우저는 다음 단계를 거칩니다.

 

  1. HTML 파싱: 브라우저는 HTML 파일을 파싱하여 DOM(Document Object Model) 트리를 생성합니다.
  2. CSS 파싱: 브라우저는 CSS 파일을 파싱하여 CSSOM(CSS Object Model) 트리를 생성합니다.
  3. 렌더 트리 생성: DOM 트리와 CSSOM 트리를 합쳐서 렌더 트리를 생성합니다. 이 트리는 페이지의 시각적 요소를 나타냅니다.
  4. 레이아웃: 렌더 트리의 요소들에 대한 위치와 크기를 계산합니다.
  5. 페인팅: 최종적으로 스타일과 레이아웃 정보를 바탕으로 화면에 요소를 그립니다.

FOUC와 FOUT 현상은 주로 렌더 트리 생성 및 레이아웃 단계에서 발생합니다. 스타일 정보가 늦게 도착하거나, 웹 폰트가 로드되는 동안 브라우저가 기본 폰트로 렌더링하기 때문입니다.

브라우저 동작원리에 대해 더 자세히 궁금하다면 https://d2.naver.com/helloworld/59361
원문은 https://web.dev/howbrowserswork/

 

FOUC와 FOUT 현상을 극복하기 위한 최적화 전략

FOUC와 FOUT 현상을 극복하기 위한 여러 전략들이 있습니다. 이 전략들은 브라우저 렌더링 원리를 이해를 기반으로 하고 스타일 로드와 적용 과정을 최적화하는 데 초점을 맞춥니다.

CSS를 HTML 문서의 <head> 태그에 배치:

브라우저는 HTML 문서를 순차적으로 해석하므로, 스타일을 가능한 한 빨리 로드하려면 <head> 태그 내에 <link> 태그를 사용하여 CSS 파일을 연결하는 것이 좋습니다. 이렇게 하면 브라우저가 렌더링을 시작하기 전에 스타일을 먼저 로드하고 적용할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퉁이리</title>
    <link rel="stylesheet" href="styles.css"> <!-- 여기 -->
</head>
<body>
    <!-- Your content here -->
</body>
</html>



인라인 CSS 사용: 

인라인 스타일은 별도의 HTTP 요청 없이 페이지와 함께 로드되기 때문에 렌더링 속도가 빨라질 수 있습니다. 하지만 이 방법은 파일 크기가 커질 수 있으므로, 필수적인 스타일 정보만 인라인으로 삽입하는 것이 좋습니다. 이를 부분적으로 적용하기 위해 크리티컬 CSS라는 기법을 사용할 수 있습니다. 

크리티컬 CSS란 웹 페이지의 초기 렌더링에 영향을 미치는 중요한 스타일을 인라인으로 삽입하는 방법입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퉁이리</title>
    <style>
        /* Critical CSS: 페이지 초기 렌더링에 필요한 중요한 스타일 */
        body {
            font-family: Arial, sans-serif;
            background-color: white;
            margin: 0;
            padding: 0;
        }
        header {
            background-color: #333;
            color: white;
            padding: 1rem;
        }
    </style>
    <link rel="stylesheet" href="styles.css"> <!-- 나머지 스타일은 여기서 로드 -->
</head>
<body>
    <header>
        <h1>퉁이리</h1>
    </header>
    <!-- Your content here -->
</body>
</html>

 


CSS 파일 크기 줄이기: 

CSS 파일의 크기를 최소화하면 로드 시간이 단축되어 FOUC와 FOUT 현상을 줄일 수 있습니다. 이를 위해 불필요한 코드를 제거하거나 CSS 파일을 압축하는 방법을 사용할 수 있습니다.

수동으로 할 수도 있지만, CSS 압축 도구를 사용하면 더 효율적입니다. 자동화를 이용해요!

 


웹 폰트 로드 최적화: 

웹 폰트를 불러오는 방식을 최적화하면 FOUT 현상을 줄일 수 있습니다. 예를 들어, <link> 태그의 preload 속성을 사용하여 웹 폰트를 미리 로드할 수 있습니다. 또는 CSS font-display 속성을 사용하여 웹 폰트의 로드 및 렌더링 동작을 조절할 수 있습니다.

 


JavaScript 로드 순서 조절: 

JavaScript가 페이지의 스타일 적용을 차단하거나 렌더링을 지연시키는 경우, FOUC와 FOUT 현상이 발생할 수 있습니다. 따라서 JavaScript 로드 순서를 조절하여 문제를 해결할 수 있습니다. 스크립트를 HTML 문서의 <body> 태그 끝 부분에 배치하거나 async 또는 defer 속성을 사용하여 스크립트 로드 순서를 변경할 수 있습니다. 이렇게 하면 브라우저가 스크립트 로드를 지연시키고 스타일이 완전히 로드되고 적용된 후에 스크립트를 실행할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퉁이리</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <!-- Your content here -->

    <!-- JavaScript를 문서 끝부분에 위치시키기 -->
    <script src="your-script.js"></script>
    <!-- 또는 `async` 또는 `defer` 속성 사용 -->
    <script async src="your-script.js"></script>
    <script defer src="your-script.js"></script>
</body>
</html>



콘텐츠를 숨겨놓고 로드가 완료된 후에 표시하기: 

이 방법은 초기 로딩 시 콘텐츠를 숨기고, 페이지의 스타일과 스크립트가 완전히 로드된 후에 콘텐츠를 표시하는 것입니다. 예를 들어, 페이지의 최상위 요소에 opacity: 0 또는 display: none 같은 스타일을 적용하여 콘텐츠를 숨길 수 있습니다. 그런 다음 JavaScript를 사용하여 페이지 로드가 완료되면 해당 스타일을 제거하여 콘텐츠를 표시할 수 있습니다. 이 방법은 FOUC 현상을 완전히 제거할 수 있지만, 사용자가 빈 화면을 잠시 볼 수 있으므로 적절한 *로딩 인디케이터를 제공하는 것이 좋습니다.

로딩 인디케이터는 사용자에게 웹 페이지나 애플리케이션의 컨텐츠가 로드 중임을 알려주는 시각적 요소입니다. 로딩 인디케이터는 사용자 경험(UX)의 중요한 부분으로, 사용자가 데이터가 로드되고 있음을 인지하게 해서 기다리는 동안의 불편함을 줄이는 역할을 합니다. 

로딩 인디케이터는 일반적으로 다음과 같은 형태로 나타내요.

스피너(Spinner): 원형 아이콘으로 회전하면서 로드 중임을 나타내는 가장 일반적인 로딩 인디케이터입니다. 스피너는 크기와 색상을 변경할 수 있으며, 웹 페이지나 애플리케이션의 스타일에 맞게 커스터마이징할 수 있습니다.

진행바(Progress bar): 로딩이 진행되는 과정을 가로 또는 세로 형태의 바로 표시하는 인디케이터입니다. 진행바는 데이터 로드가 완료될 때까지 점진적으로 채워지며, 사용자에게 로딩 과정의 상태를 더 구체적으로 표시해줍니다.

스켈레톤 로딩(Skeleton loading): 콘텐츠의 형태와 크기를 대략적으로 표시하는 뼈대를 사용하여 로딩 중임을 나타내는 인디케이터입니다. 스켈레톤 로딩은 실제 콘텐츠가 로드될 때까지 사용자에게 대략적인 레이아웃을 보여주어, 페이지가 로드되는 동안 사용자의 인내심을 높이는 데 도움이 됩니다.

 


서버 사이드 렌더링 (SSR) 사용하기: 

SSR은 클라이언트 사이드에서 렌더링하기 전에 서버에서 HTML을 렌더링하는 기술입니다. 이를 통해 브라우저가 이미 스타일이 적용된 HTML 문서를 받게 되어 FOUC 현상을 피할 수 있습니다. Next.js 등의 프레임워크에서는 SSR을 지원하며, 이를 사용하여 FOUC 현상을 방지할 수 있습니다.

 


FOUC와 FOUT 현상은 웹 페이지의 사용자 경험에 부정적인 영향을 미칠 수 있습니다. 따라서 위에서 제시한 방법 중 하나 이상을 사용하여 FOUC와 FOUT 현상을 최소화하거나 완전히 제거할 수 있도록 노력해야 합니다. 이렇게 함으로써 사용자가 웹 페이지를 더 빠르게 로드하고 스타일이 올바르게 적용된 콘텐츠를 볼 수 있게 되어 사용자 경험을 향상시킬 수 있습니다.

 

 

좋아요는 로그인하지 않아도 누를 수 있습니다!

 

참고

https://stackoverflow.com/questions/60841540/flash-of-unstyled-text-fout-on-reload-using-next-js-and-styled-components

https://dev.to/lyqht/what-the-fouc-is-happening-flash-of-unstyled-content-413j

https://en.wikipedia.org/wiki/Flash_of_unstyled_content#:~:text=A%20flash%20of%20unstyled%20content,before%20all%20information%20is%20retrieved.

https://d2.naver.com/helloworld/59361

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함