[React] - CSS in JS 성능 문제, 폼 컨트롤

Lee Jeong Min·2021년 12월 30일
0
post-thumbnail

styled-components 성능 문제

styled-components는 빌드 시, 정적 CSS 파일을 생성하지 않고, 애플리케이션 실행 중 동적으로 스타일을 계산해서 추가한다. 이러한 이유로 스타일이 복잡해질 경우 (예: 스크롤 애니메이션 등) 성능 문제를 야기!

이러한 문제를 해결하기 위해 정적 CSS 파일 생성이 필요하지만 styled-components는 공식적으로 css 파일을 생성하는 방법 제공 X

Zero Runtime CSS in JS

스크롤 애니메이션(예: Parallax Motion 등) 같은 복잡한 계산이 필요한 경우, Linaria를 사용해 문제를 해결할 수 있다. Linaria는 애플리케이션 실행 중 동적으로 스타일을 계산하는 대신, 정적 CSS 파일을 생성한다.

단점
정적 CSS 파일 임에도 CSS 커스텀 속성을 사용해 컴포넌트의 상태가 변경될 때마다 바뀌는 값을 적용시켜 동적 스타일링을 구현하는 방식을 사용한다. 다만, CSS 커스텀 속성을 사용하므로 IE 브라우저는 지원하지 않는다.

참고사이트: https://github.com/callstack/linaria

React Form 컨트롤

React 애플리케이션에서 폼을 컨트롤 하는 방법을 학습

globalcss 컴포넌트 형식으로 주입

index.js

import './reportWebVitals';
import { GlobalStyle } from 'styles/global.styled';
import { StrictMode } from 'react';
import { render } from 'react-dom';
import App from 'App';

render(
  <StrictMode>
    <GlobalStyle />
    <App />
  </StrictMode>,
  document.getElementById('root')
);

css를 불러올 때 지금껏 import 방식으로 불러왔었지만, styled-components를 사용하여 위와 같이 <GlobalStyle />로 가져올 수 있음.

Create react app에서 절대 경로를 사용하기 위해선 루트 폴더에 jscofing.json에 다음과 같이 입력하여 baesUrl을 사용할 수 있음

{
  "compilerOptions": {
    "baseUrl": "src"
  }
}

스타일 컴포넌트 글로벌 스타일

global.styled.js

import { createGlobalStyle } from 'styled-components/macro';

export const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    font: 1rem/1.5 'Spoqa Han Sans Neo';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  body *,
  body *::before,
  body *::after {
    -webkit-tap-highlight-color: rgba(250 250 0 / 2%);
    box-sizing: border-box;
  }

  img {
    vertical-align: middle;
  }

  button {
    cursor: pointer;
  }

  button:focus:not(:focus-visible) {
    outline: none;
  }

  abbr[title] {
    cursor: help;
    text-decoration: none;
  }

  code {
    font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
      monospace;
  }
`;

스타일 컴포넌트에서 글로벌 스타일을 적용시킬 때, createGlobalStyle() 함수는 글로벌 스타일을 정의하는 컴포넌트를 반환하여 다음과 같이 작성할 수 있다.
또한 안의 코드가 템플릿 리터럴로 작성되어 있기 때문에 js 코드를 보간형태로 표현식 값을 전달하여 사용할 수 있다.

React 컴포넌트 스타일 확장

common.styled.js

import styled, { css } from 'styled-components/macro';
import { px2em, px2rem } from './utils';
import { viewport } from './theme';

/* ------------------------------------------------------ */

export const Wrapper = styled.div`
  ${({ flex }) =>
    flex &&
    css`
      display: flex;
      justify-content: flex-start;
      align-items: flex-start;
    `}
  width: clamp(${px2rem(viewport.min)}, 100vw, ${px2rem(viewport.max)});
  margin-left: auto;
  margin-right: auto;
  padding: 0 1em;

  @media (min-width: ${px2em(viewport.max)}) {
    padding: 0;
  }
`;

Wrapper.displayName = 'Wrapper';

Layout.styled.js

import { Wrapper as GlobalWrapper } from 'styles/common.styled';
const styled = require('styled-components/macro');

export const Container = styled.div`
  min-height: 100vh;
`;

export const Wrapper = styled(GlobalWrapper)`
  flex-flow: ${({ flex }) => flex && 'column'};
`;

common.styled.js에서 정의한 Wrapper를 as GlboalWrapper로 가져와 리액트 컴포넌트 스타일을 확장하여 styled(GlobalWrapper)로 사용한다.

React Router

왜 필요한가? -> 클라이언트 환경에서 접근 가능한곳, 접근이 불가능한 곳을 렌더링 하기 위해서는 React Router를 사용해야한다 (싱글페이지에서)

참고사이트: https://reactrouter.com/

패키지 설치

yarn add react-router-dom

App.js

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { Home } from 'pages';

export default function App() {
  return (
    <Router>
      <Routes>
        {/* 라우터가 하는 일은 지정된 라우트(루트)에 따라 컴포넌트를 렌더링 하도록 설정한다. */}
        <Route path='/' element={<Home />} />
      </Routes>
    </Router>
  );
}

React Router 6 버전 최신 문법으로 작성하면 위와 같다.

이제 라우터가 있으니 링크 클릭 시 서버측에 요청하지 않도록 만들어 주어야 한다.

참고 사이트: https://reactrouter.com/docs/en/v6/api#link

Header.js

// 적용 전
        <HomeLink href={navigationItems.find(({ text }) => text === '홈').to}>
          <Logo title={logoLabel} />
        </HomeLink>


// 적용 후
        <HomeLink to={navigationItems.find(({ text }) => text === '홈').to}>
          <Logo title={logoLabel} />
        </HomeLink>

Header.styled.js

// 적용 전
...

export const HomeLink = styled.a`
  display: flex;
  justify-content: center;
  align-items: center;
  width: ${size}px;
  height: ${size}px;
  border-radius: 4px;
  padding: 2px;

  &:hover {
    background: rgba(10 45 10 / 10%);
  }
`;

// -------------------------------------

// 적용 후
import { Link } from 'react-router-dom';

...

export const HomeLink = styled(Link)`
  display: flex;
  justify-content: center;
  align-items: center;
  width: ${size}px;
  height: ${size}px;
  border-radius: 4px;
  padding: 2px;

  &:hover {
    background: rgba(10 45 10 / 10%);
  }
`;

다른 컴포넌트 또한 스타일 컴포넌트 확장을 이용하여 react-router-dom에서 Link 태그를 합성하여 사용하면 라우팅을 구현할 수 있다.

NavLink를 사용하면 클래스를 사용하지 않아도 자동적으로 페이지가 활성화되면 active클래스를 주어 indicating 해준다. (네비게이션 전용 링크)

참고사이트: https://reactrouter.com/docs/en/v6/api#navlink

profile
It is possible for ordinary people to choose to be extraordinary.

0개의 댓글