layout shift
처음엔 List Item 의 width 가 바짝 차렷 하고있는 모습을 먼저 보였다.
이를 해결하기 위해 Item 의 width 를 어떻게줄까.. 하다가 List 에 max-content 를 주니 해결이 되는 모습을 보았다.
그런데 문제가 생겼다.
Layout Shift?
처음엔 저게 왜 생겼지? top, left 를 지정해주다 생긴건가? 싶었는데 여러 테스트를 해보면서
width 가 max-content 로 동적으로 지정되니 생기는 문제인가.. 로 추측해보면서 Dropdown Item 의 width 를 지정해줘보았다.
const DropdownItem = (props) => {
const { children } = props;
return (
<li
css={css`
width: 100px;
`}
{...props}
>
{children}
</li>
);
};
뭔가 list item 의 width 를 동적으로 계산해서 생기는 문제같긴 한데.. 명확한 이유를 몰랐다.
첫 번째 시도를 했던 list item 에 width 지정해주기 방법으로도 Layout Shift 가 사라졌었지만 다른 프로젝트를 할 때 텍스트 길이에 따라 변하는 요소에 의해 Layout Shift 가 발생했던 적이 없었다. 다른 UI 를 제공하는 라이브러리들의 demo 를 보아도 비슷한 증상은 없었다.
그리고 클릭을 할 때마다 깜빡거리는 증상과 움찔 하는 듯한 느낌이 있는 데, layout shift 를 해결하면 해결되지 않을까 해서 관련 증상을 찾아보았다.
1. FOUC 라는 키워드 - 증상은 같으나 현재 매우 가벼운 프로젝트에서 발생할 이유가 아니라고 생각했음, SSR 도 아님
2. network 탭을 확인해보니 클릭 이벤트시에 폰트를 다시 받아오는데, 이게 왜 다시 받아오는 건지 찾아보았다.
결국 이유는 styled components 에서 새로운 컴포넌트가 특정 이벤트에 의해서 렌더링되면 새로운 클래스를 넣기 위해 style 태그를 변경하는데, styled components 에서 font 를 import 하면 해당 과정에서 폰트를 다시 불러오는 현상 때문이었다
며칠 전 제로초님의 인프런 강의를 들으면서 결국 index.html 에서 처리하는게 생긴다~ 라고 하신 부분이 이런 부분일까 싶었다.
그래서 createGlobalStyle 내부에서 @font-face 를 만드는 로직을 별도로 분리하여 index.html 에 직접 넣었다.
폰트 관련 부분을 수정하니 반짝임도 사라지고, layout shift 도 없어졌다. (layout shift 도 원인이 폰트때문이었는 듯)
신기하네.. width 관련 문제를 해결했을 땐 layout shift 가 사라지기도 했지만
폰트 관련 문제를 해결하니 width 를 어떻게 쓰든 layout shift 가 없다.
또 변경..
위 해결법이 배포시 문제가 된다는걸 다시 깨달았다.
build 를 하면 webpack 이 하나의 js 로 번들링 해주는데, 폰트를 public 폴더 하위에 존재하게 두면 배포를 위한 빌드에서 폰트를 포함시키는게 곤란했다.
여러모로 생각해보니 그냥 하나의 js 로 번들링 시키는게 낫겠다 싶어 app.css 를 만들어 import 하여 쓰는걸로 다시 변경했다.
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 400;
src: url('./assets/fonts/noto-sans-kr-regular.woff2') format('woff2');
}
@font-face {
font-family: NotoSansKR;
font-style: normal;
font-weight: 400;
src: url('./assets/fonts/roboto-regular.woff2') format('woff2');
}
import './app.css';
...
const App: React.FC = () => {
return (
<ThemeProvider theme={isDarkMode ? darkTheme : lightTheme}>
<GlobalStyle />
<Routes />
</ThemeProvider>
);
};
export default App;
결론
1. Box 가 생성되고 폰트가 새롭게 불러와짐 -> 폰트가 달라져서 layout 이 변경됨 (폰트 크기가 다르므로) -> layout shift
2. width 설정할 시 -> 폰트가 달라져도 layout 이 그 width 안에 존재함 -> layout shift 없을 수 있음