Font Awesome 아이콘 크기 버그 해결

SSR/SSG 기능을 위한 필수 설정하기

수정11-15분 읽기태그: Web Dev, Gatsby, Gatsby Plugins, SSR, Static Site Generator, Font Awesome, Icon Fonts

배포한 웹사이트의 첫 로딩에서 Font Awesome 아이콘이 크게 표시되었다가 정상 크기로 줄어드는 현상이 발생할 수 있다. 이 현상은 Gatsby 웹사이트에서 Font Awesome 스타일을 불러오는 설정이 누락되었을 때 발생한다.


준비물

  • Gatsby v5 웹사이트: Gatsby로 만든 웹사이트가 필요하다. 프로젝트 생성 방법은 다음 문서를 참고한다. → Gatsby Quick Start
  • Font Awesome 사용: React 용 패키지를 설치하고 관련 컴포넌트를 사용해야 한다. -> Font Awesome 6 사용하기

문제: 웹사이트 첫 화면에서 Font Awesome 아이콘이 매우 컸다가 작아진다

웹사이트 로딩시 Font Awesome 아이콘이 매우 컸다가 작아지는 증상
웹사이트 로딩시 Font Awesome 아이콘이 매우 컸다가 작아지는 증상

이 문제는 아래와 같은 환경에서 확인할 수 있다.

  1. FontAwesomeIcon 컴포넌트를 페이지에 포함하고 있어야 한다.

    CSS content로 구현한 아이콘에는 발생하지 않는 버그다.

    src/pages/example.tsx
    import React from 'react';
    import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
    import {faFaceGrinWide} from '@fortawesome/free-solid-svg-icons';
     
    const ExamplePage = () => {
        return (
            <div style={{fontSize: '32px'}}>
                <FontAwesomeIcon icon={faFaceGrinWide}/>
            </div>
        );
    };
    export default ExamplePage;
  2. production 모드로 빌드 후 서버를 실행한다.

    develop 모드에서는 확인할 수 없다.

    gatsby build && gatsby serve
  3. 실행된 서버의 주소를 웹 브라우저에서 확인한다.

    http://localhost:9000/example/
    
  4. 첫 페이지에 Font Awesome 아이콘이 있다면 현상을 바로 확인할 수 있다. (=첫 방문 시 확인 가능)
    만약 다른 페이지에 아이콘이 있다면 그 페이지로 이동 후 새로고침 한다.

    웹페이지가 로딩된 후 내부에서 링크로 이동하면 현상을 확인할 수 없다.

해결: 아이콘 스타일을 명시적으로 불러오기

웹사이트 로딩시 Font Awesome 아이콘이 커지는 현상이 사라졌다
웹사이트 로딩시 Font Awesome 아이콘이 커지는 현상이 사라졌다

Next.js 웹사이트에 적용하기

Font Awesome 공식 홈페이지의 "Use React with..." 페이지 화면 (2023.4.26 기준)
Font Awesome 공식 홈페이지의 "Use React with..." 페이지 화면 (2023.4.26 기준)

이 문제의 해결법은 Font Awesome 공식 홈페이지의 Use React with...페이지의 Next.js 섹션에서 찾을 수 있다.

React로 개발하고 Next.js 프레임워크를 사용한 경우 생기는 문제이며 이 경우에 아래의 간단한 설정으로 해결된다고 안내하고 있다.

pages/_app.js에 위 3줄을 추가해 주세요
import '@fortawesome/fontawesome-svg-core/styles.css'
import { config } from '@fortawesome/fontawesome-svg-core'
config.autoAddCss = false
 
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

Gatsby 웹사이트에 적용하기

Gatsby 웹사이트에서 문제를 해결하는 방법은 Next.js 때와 동일하다.

  1. 만약 프로젝트 루트에 gatsby-browser.tsx 파일이 없다면 만들고,
  2. 이 파일에 동일한 코드 3줄을 추가하면 된다.
gatsby-browser.tsx
import '@fortawesome/fontawesome-svg-core/styles.css'
import { config } from '@fortawesome/fontawesome-svg-core'
config.autoAddCss = false

원인: 아이콘과 스타일이 적용되는 시점 차이

Gatsby 프레임워크는 React 기반이다. React 프로젝트에서 Font Awesome 아이콘을 사용하려면 @fortawesome/react-fontawesome 패키지를 사용한다. Next.js도 Gatsby와 같은 React 프레임워크다. 둘 다 서버 측 랜더링(이하 SSR) Server-side Rendering과 정적 사이트 생성(이하 SSG) Static Site Generation 기능을 제공하는데 이것 때문에 문제가 발생한다. 각 환경에서 아이콘과 스타일이 적용되는 시점을 비교한다.


@fortawesome/react-fontawesome 패키지가 아이콘 크기를 조정하는 방식

  1. Font Awesome CSS 코드는 동적으로 웹사이트에 추가된다. 여기에는 아이콘 크기를 조정하는 스타일도 포함된다.

    브라우저에서 개발자 도구를 열면 Font Awesome 관련 스타일이 추가된 것을 확인할 수 있다
    브라우저에서 개발자 도구를 열면 Font Awesome 관련 스타일이 추가된 것을 확인할 수 있다
  2. FontAwesomeIcon 컴포넌트는 svg 태그로 변환됐고 svg-inline--fa 클래스를 갖고 있다. width, height 같은 크기 속성은 없다.

    FontAwesomeIcon 컴포넌트는 svg 태그로 변환된다
    FontAwesomeIcon 컴포넌트는 svg 태그로 변환된다
  3. 아이콘의 크기는 svg-inline--fa 클래스 스타일에서 height: 1em;를 적용받아 부모 요소의 폰트 크기와 동일한 크기로 보인다.

    Font Awesome CSS 일부
    .svg-inline--fa {
        display: var(--fa-display, inline-block);
        height: 1em;
        overflow: visible;
        vertical-align: -0.125em;
    }
  4. height: 1em; 스타일이 없다면 svg아이콘이 원본 크기로 보이는 것을 확인할 수 있다.

    높이 스타일을 비활성화하면 아이콘이 원본 크기로 보인다
    높이 스타일을 비활성화하면 아이콘이 원본 크기로 보인다

정상: React 프로젝트 + SSR/SSG 미설정

React 웹사이트인데 SSR이나 SSG를 설정하지 않았다면 문제 되지 않는다. Gatsby나 Next.js는 SSR/SSG를 지원하지만, develop 모드에서 서버를 실행할 때는 SSR, SSG는 실행 하지 않기 때문에 문제 되지 않는다.

이 경우에는 Font Awesome 스타일이 head 내부에 추가되는 시점과 svg 아이콘이 body 내부에 추가되는 시점이 동일하다.

일반 React 웹사이트에서 @fortawesome/react-fontawesome 패키지가 아이콘 크기를 조정하는 방식
일반 React 웹사이트에서 @fortawesome/react-fontawesome 패키지가 아이콘 크기를 조정하는 방식

오류: React 프로젝트 + SSR/SSG 설정

React 웹사이트에서 SSR, SSG를 설정하면 production 모드로 빌드 할 때 각 HTML 페이지에 내부 내용을 포함한다. 그래서 Font Awesome 아이콘도 svg 요소로 변환해서 포함되었다. 그런데 이 HTML 문서에는 Font Awesome 스타일은 포함되지 않는다. 그래서 웹사이트 첫 로딩 때 크기 설정이 되지 않은 아이콘이 보였다가 스타일이 나중에 추가되어서 정상 크기로 변경되는 것이 눈에 보이게 된다.

Gatsby, Next.js 등 SSR/SSG 지원 React 웹사이트에서 @fortawesome/react-fontawesome 패키지가 아이콘 크기를 조정하는 방식
Gatsby, Next.js 등 SSR/SSG 지원 React 웹사이트에서 @fortawesome/react-fontawesome 패키지가 아이콘 크기를 조정하는 방식

정상: React 프로젝트 + SSR/SSG 설정 + Font Awesome 설정

Gatsby 웹사이트에 적용하기에서 언급한 설정을 소스에 추가하면 어긋났던 시점이 다시 맞춰져서 아이콘의 급격한 크기 변경 현상이 없어진다.

  1. config.autoAddCss 설정값을 false로 하면 브라우저에서 React 웹사이트가 초기화될 때 Font Awesome 스타일이 head에 추가되지 않는다.

    gatsby-browser.tsx
    import { config } from '@fortawesome/fontawesome-svg-core'
    config.autoAddCss = false
  2. @fortawesome/fontawesome-svg-core/styles.css 파일을 직접 임포트하면 빌드할 때 Font Awesome 스타일이 head에 추가된다. 이 CSS 파일 내용은 autoAddCss 설정으로 추가되는 스타일과 동일한 내용이다.

    gatsby-browser.tsx
    import '@fortawesome/fontawesome-svg-core/styles.css'
Gatsby, Next.js 등 SSR/SSG 지원 React 웹사이트에서 추가 설정 후 아이콘 크기를 조정하는 방식
Gatsby, Next.js 등 SSR/SSG 지원 React 웹사이트에서 추가 설정 후 아이콘 크기를 조정하는 방식

불필요한 해결법: gatsby-plugin-fontawesome-css 플러그인 사용하기

Gatsby Plugins 페이지에서 'fontawesome'으로 검색하면 가장 위에 gatsby-plugin-fontawesome-css 플러그인이 나온다. (2023.4.27 기준)
Gatsby Plugins 페이지에서 'fontawesome'으로 검색하면 가장 위에 gatsby-plugin-fontawesome-css 플러그인이 나온다. (2023.4.27 기준)

gatsby-plugin-fontawesome-css 플러그인은 현재(2023년 4월 기준) 2년 넘게 업데이트되지 않고 있지만 Gatsby Plugins 사이트에 따르면 1만 7천 번 이상 다운로드된 인기 있는 플러그인이다.

이 플러그인은 Font Awesome 아이콘 크기 버그 해결만을 위한 단순한 플러그인이다. 다음 이유로 이 플러그인 대신 공식 문서의 설정을 사용한다.

  1. 가장 중요한 이유는 공식 문서의 해결 방법이 이미 명확하고 쉽기 때문이다.

  2. 이 플러그인은 Gatsby 5 버전 이상 환경에 설치 시 의존성 버전이 맞지 않아--force 옵션으로 설치해야 한다.

  3. 플러그인 내용을 보면 공식 문서의 해결 방법보다 복잡하게 Font Awesome 스타일을 추가하고 있다.

    gatsby-ssr.js + utils.js
    // import '@fortawesome/fontawesome-svg-core/styles.css'
    // 위 코드와 동일한 효과를 위해 아래의 코드를 사용한다.
     
    const React = require('react')
    const { dom } = require('@fortawesome/fontawesome-svg-core')
     
    let styleTag = null
    exports.onRenderBody = ({ setHeadComponents }) => {
        if (!styleTag) {
            styleTag = React.createElement('style', {
                key: 'gatsby-plugin-fontawesome-css',
                type: 'text/css',
                dangerouslySetInnerHTML: { __html: dom.css() },
            })
        }
        setHeadComponents([styleTag])
    }

참고 자료

이 글에서 참고한 자료는 다음과 같다.