[React] Emotion 설치 후 간단한 예제 만들어보기

Lemon·2023년 5월 2일
0

React

목록 보기
21/21
post-thumbnail
post-custom-banner

Emotion은 JavaScript로 css 스타일을 작성하도록 설계된 라이브러리입니다.
👉🏻Emotion 공식홈페이지 바로가기


1. 설치

// npm 설치 
npm install @emotion/react

// yarn 설치
yarn add @emotion/react

일반 자바스크립트 프로젝트에서는 @emotion/css패키지를 설치


2. 패키지 import

Emotion에서 사용하는 css()함수는 설치한 @emotion/react패키지에서 불러온다.

import { css } from "@emotion/react";

3. JSX pragma 작성

/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";

/** @jsxImportSource @emotion/react */ 이 부분을 JSX pragma라고 하는데 Babel 트랜스파일러한테 JSX 코드를 변환할 때, React의 jsx()함수가 아니라 Emotion의 jsx()함수를 대신 사용하라고 알려주기 위함이다.
이를 작성하지 않으면 css prop에 넘어간 스타일이 제대로 반영되지 않는다.
매번 JSX pragma를 사용하기가 번거로우시다면 Emotion에서 제공하는 Babel 플러그인이나 프리셋을 사용하시는 것을 고려하길 바란다.


4. 기본 문법

 Emotion의 css()함수는 CSS 스타일 선언 내용을 인자로 받는다.
css()함수가 반환 결과를 해당 스타일을 적용하고 싶은 HTML 요소나 React 컴포넌트의 css라는 prop에 넘겨주면 된다.
객체형으로 넘겨도 되고, 문자형으로 넘겨된다.

4-1. 객체형 스타일을 css() 함수의 인자로 넘기기

/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";

function EmotionObjectComponent() {
  return (
    <div
      css={css({
        backgroundColor: "yellow",
      })}
    >
      노란색 영역
    </div>
  );
}

4-2. 문자형 스타일을 css() 함수의 인자로 넘기기

/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";

function EmotionStringComponent() {
  return (
    <div
      css={css`
        background-color: yellow;
      `}
    >
      노란색 영역
    </div>
  );
}

Emotion 문서에서 가급적 스타일을 객체로 선언해서 css()함수에 넘기라고 권장하고 있다. 이 방법을 사용하면 css()함수를 호출을 생략하고 css prop에 바로 객체를 넘길 수 있으며, 특히 타입스크립트(TypeScript)를 사용하면 타입 체킹(type checking)을 통해 오타를 줄일 수 있기 때문이다.


5. 예제만들기

5-1. 고정 스타일링

css prop을 통해 css 속성을 정의하고 객체로 넘긴다.

/** @jsxImportSource @emotion/react */

function Button({ children }) {
  return (
    <button
      css={{
        borderRadius: "6px",
        border: "1px solid rgba(27, 31, 36, 0.15)",
        backgroundColor: "rgb(246, 248, 250)",
        color: "rgb(36, 41, 47)",
        fontFamily: "-apple-system, BlinkMacSystemFont, sans-serif",
        fontWeight: "600",
        lineHeight: "20px",
        fontSize: "14px",
        padding: "5px 16px",
        textAlign: "center",
        cursor: "pointer",
        appearance: "none",
        userSelect: "none",
      }}
    >
      {children}
    </button>
  );
}

export default Button;

<Button> 컴포넌트를 React 컴포넌트에서 사용한다.

import { Button } from "./Button";

function App() {
  return <Button>Button</Button>;
}

F12를 통해 브라우저에서 해당 버튼의 소스를 검색해보면 Emotion에서 자동으로 class 이름이 붙어있는 걸 확인할 수 있다.

내부 스타일시트를 확인해보면 Emotion으로 작성한 CSS 속성 내용과 동일함을 확인할 수 있다.
여기서 특별한 것은 Emotion이 자동으로 브라우저 별로 필요한 CSS 속성을 추가해준다는 것이다.

-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;

이런 작업을 vendor prefixing이라고 한다. Emotion을 사용할 때 공짜로 얻을 수 있는 또 다른 이점이다.

5-2. 가변 스타일링

Emotion으로 React 컴포넌트에 넘어온 props에 따라 다른 스타일을 적용할 수 있다.
바꾸고 싶은 CSS 속성값에 상수 대신에 prop에 따라 변하는 변수를 할당해주면된다.

/** @jsxImportSource @emotion/react */

const colors = {
  default: "rgb(36, 41, 47)",
  danger: "rgb(207, 34, 46)",
  outline: "rgb(9, 105, 218)",
};

function Button({ children, variant = "default" }) {
  return (
    <button
      css={{
        borderRadius: "6px",
        border: "1px solid rgba(27, 31, 36, 0.15)",
        backgroundColor: "rgb(246, 248, 250)",
        color: colors[variant],
        fontFamily: "-apple-system, BlinkMacSystemFont, sans-serif",
        fontWeight: "600",
        lineHeight: "20px",
        fontSize: "14px",
        padding: "5px 16px",
        textAlign: "center",
        cursor: "pointer",
        appearance: "none",
        userSelect: "none",
      }}
    >
      {children}
    </button>
  );
}

export default Button;

위 예시는 <Button /> 컴포넌트에 variant라는 prop을 추가한 후 prop에 어떤 값이 넘어오냐에 따라 글자색을 바워주는 코드이다.

import B7utton from "./Button";

function App() {
  return (
    <>
      <Button variant="default">Default</Button>
      <Button variant="danger">Danger</Button>
      <Button variant="outline">Outline</Button>
    </>
  );
}

적용 후 variant prop에 들어간 값대로 색이 바뀐 것을 볼 수 있다.

5-3. 여러가지 스타일 가변 스타일링

바꾸고 싶은 CSS 속성이 하나가 아니라 여러 개일 경우 CSS 속성 값뿐만 아니라 CSS 속성 이름과 값을 동시에 객체로 만들면된다.
예를 들어, size라는 prop에 넘어온 값에 따라 fontSize 속성과 padding 속성을 다르게 해보겠다.

/** @jsxImportSource @emotion/react */

const colors = {
  default: "rgb(36, 41, 47)",
  danger: "rgb(207, 34, 46)",
  outline: "rgb(9, 105, 218)",
};

const sizeStyles = {
  sm: {
    fontSize: "12px",
    padding: "3px 12px",
  },
  md: {
    fontSize: "14px",
    padding: "5px 16px",
  },
  lg: {
    fontSize: "16px",
    padding: "9px 20px",
  },
};

function Button({ children, size = "md", variant = "default" }) {
  return (
    <button
      css={{
        borderRadius: "6px",
        border: "1px solid rgba(27, 31, 36, 0.15)",
        backgroundColor: "rgb(246, 248, 250)",
        color: colors[variant],
        fontFamily: "-apple-system, BlinkMacSystemFont, sans-serif",
        fontWeight: "600",
        lineHeight: "20px",
        ...sizeStyles[size],
        textAlign: "center",
        cursor: "pointer",
        appearance: "none",
        userSelect: "none",
      }}
    >
      {children}
    </button>
  );
}

export default Button;

이제 3가지 크기의 3가지 색상, 총 9가지 종류의 버튼을 만들 수 있다.

import Button from "./Button";

function App() {
  return (
    <>
      <Button size="sm" variant="default">
        Default
      </Button>
      <Button size="md" variant="default">
        Default
      </Button>
      <Button size="lg" variant="default">
        Default
      </Button>
      <hr />
      <Button size="sm" variant="danger">
        Danger
      </Button>
      <Button size="md" variant="danger">
        Danger
      </Button>
      <Button size="lg" variant="danger">
        Danger
      </Button>
      <hr />
      <Button size="sm" variant="outline">
        Outline
      </Button>
      <Button size="md" variant="outline">
        Outline
      </Button>
      <Button size="lg" variant="outline">
        Outline
      </Button>
    </>
  );
}

마치며

최근에는 일반 CSS와 styled-component를 사용했었는데, 이번에 새로운 프로젝트에 들어가게 되면서 Emotion을 사용하기로했다. 처음 접해봤는데, 생각보다 사용이 간편해서 유용하게 쓸 수 있을 것 같다.


🔗참고링크
https://www.daleseo.com/emotion/

profile
개미는 뚠뚠..오늘도 뚠뚠🐜
post-custom-banner

0개의 댓글