sooleeandtomas

FOUC ? 본문

코딩 공부 노트/웹 이론

FOUC ?

sooleeandtomas 2020. 12. 10. 23:15

FOUC 란?

FOUC란? : Flash Of Unstyled Content

외부의 CSS가 불러오기 전에 잠시 스타일이 적용되지 않은 웹 페이지가 나타나는 현상입니다.

웹 브라우저가 웹 페이지에 스타일 정의를 부르고 적용할 때 보여지는 부분을 최대한 빨리 수정하지만,

이 변화는 짧지 않은 시간 동안 나타나므로 사용자는 페이지에 오류가 있다는 생각을 하게됩니다.

 

FOUC가 발생하는 이유?

브라우저의 랜더링 과정 때문입니다.

브라우저렌더링과정

DOM ⇢ CSS ⇢ JS 순으로 진행되기 때문에,

번들이 되거나,  CSS가 여러개일 때, CSS를 로더하기 전, HTML 이 먼저 렌더된다면, CSS없이 페이지가 랜더될 수 있는 것입니다.

 

FOUC를 더욱 발생시키는 요소?

1. 최근의 웹 페이지들은 아래와 같은 방법으로 여러 개의 스타일 시트를 참조하는 경우.

2. @import로 스타일 파일을 가져와서 다른 CSS파일을 참조하는 경우.

3. 온라인 광고와 동영상과 검색 엔진같은 다른 곳에서 삽입된 콘텐츠는 종종 코드 블록 내에서 자신의 스타일 규칙을 구술하는 경우.

 

기본 페이지에서의 FOUC 해결 방법 : 

해결1: head

<link rel='stylesheet' href='~'> 스타일 시트를 <head> 아래에 배치합니다.

DOM트리가 모두 형성되기 전에, CSS트리가 먼저 로드되어야 CSS 랜더링이 차단되지 않습니다.

 

해결2: media query
미디어 쿼리를 사용하는 경우, 최적화를 해줍니다.

미디어 쿼리  (all,print,screen,speech) 가 브라우저와 일치할 경우에만 조건적으로 CSS를 적용시킬 수 있습니다. 아래 예시 참고

  <link href="style.css" rel="stylesheet" />
  <link href="print.css" rel="stylesheet" media="print" />
  <link href="portrait.css" rel="stylesheet" media="orientation:portrait" />

 

해결3: @import

@import의 사용을 자제해야 합니다.

   -import의 다운로드 방식은 병렬이 아닌 직렬 방식이기 때문에, 전체의 로딩시간이 길어집니다.

   -Edge에서 import를 지원하지 않스빈다.

 

해결4: display:block
FOUC가 발생하는 구역을 숨겼다가 브라우저가 준비됐을 때 다시 보여주는 방법이 있습니다. 아래 예시 참고

  
  <html class="no-js">
      <head>
          <style>
              .js #fouc {display: none}
          </style> 
          <script>
              (function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)
          </script>
      </head>
      <body>
          <div id="fouc"> ... </div> <!-- /#fouc --> 
          <script> document.getElementById("fouc").style.display="block"; </script>
      </body>
  </html>
  

출처

 

Webpack에서의 FOUC 해결 방법 :

css Loader의 sourceMap 옵션을 false로 변경합니다.

 

css loader 옵션 중 debug를 위한 souceMap 옵션을 사용하면 css module이 Blob(Binary Large Object) 형태로 생성된다는 것이다.
이 블로그에 따르면 Blob은 “데이터의 크기(Byte) 및 MIME 타입을 알아내거나, 데이터를 송수신을 위한 작은 Blob 객체로 나누는 등의 작업에 사용된다.” css loader 와 webpack의 역할은 모든 모듈을 하나의 파일로 합치는 것이다. souceMap 옵션은 디버깅을 위해 합쳐진 파일을 나눠야 한다. 개인적으로 나누기 위한 방법으로 CSS 모듈을 Blob으로 로드하는 것이 아닐까 생각해봤다. 출처
 
 module:{
 	rules:[
    	{
        	test:/\.scss$/,
            use:[
            	{loader:'css-loader'},
                options:{
                	modules:{
                    	localIdentName:'[local]'
                    },
                    sourceMap:false
                }
            ]
        }
    ]
 }
 

 

blob이란: Binary large object "데이터를 작은 객체로 나누는 작업"입니다.

바이너리 라지 오브젝트(Binary large object, BLOB)는 데이터 베이스 관리 시스템의 하나의 엔티티로서 저장되는 이진 데이터의 모임입니다.
BLOB은 일반적으로 그림,오디오 또는 기타 멀티미디어 오브젝트인 것이 보통이지만, 바이너리 실행 코드가 BLOB으로 저장되기도 합니다.
-위키백과

JavaScript에서 Blob은 대개 데이터의 크기(Byte) 및 MIME 타입을 알아내거나, 
데이터를 송수신을 위한 작은 Blob 객체로 나누는 등의 작업에 사용합니다.
출처

 

위의 출처에서 sourceMap을 false로 설정하여 blob화 시키는것을 방지했을 때, css가 loader.css.js 하나의 파일로 로드되고, 더불어 FOUC가 방지되었다고 합니다.

브라우저의 최적화의 관건은 파일을 단순화 시키는 것이라고 생각합니다.

이런 점에서 여러 작은 blob들보다는, 하나의 파일이 더 효율적으로 브라우저를 로딩할 수 있는 건가? 라는 의문점을 남기며 마치겠습니다.

 

위의 정보는 여러 블로그 또는 아티클을 토대로 작성되었습니다. 부족한 점이나 틀린 점이 있다면 댓글로 지적바랍니다. 감사합니다. 즐코하세요!

'코딩 공부 노트 > 웹 이론' 카테고리의 다른 글

macrotask, microtask, event... what the..?  (0) 2020.12.11
= , == , ===  (0) 2020.12.11
Progressive enhancement vs Graceful degradation  (0) 2020.12.10
defer, async의 차이점  (0) 2020.12.10
what is Reflow, Repaint ?  (0) 2020.12.10
Comments