7. StyledComponents

๐ŸŽฎ Styled Components ๋ฅผ ์จ๋ณด์ž

Styled Components ๋Š” React ์ปดํฌ๋„ŒํŠธ ์‹œ์Šคํ…œ์—์„œ์˜ ๋ณต์žกํ•œ CSS๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์„์ง€์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ์ด๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ๋‹ค.

  • ๋ Œ๋”๋ง๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ถ”์ ํ•˜์—ฌ ํ•ด๋‹น ์Šคํƒ€์ผ๋งŒ ์‚ฝ์ž…ํ•˜๊ณ  ์ˆ˜์ •ํ•œ๋‹ค.

  • ์ฝ”๋“œ๋ฅผ ๋ถ„ํ• ํ•˜์—ฌ ์ตœ์†Œํ•œ์˜ ์ฝ”๋“œ๋งŒ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ณ ์œ ํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ƒ์„ฑํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค๋ช…์— ๋ฒ„๊ทธ๊ฐ€ ์—†๋‹ค.

  • ๋”ฐ๋ผ์„œ, ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ญ์ œ๋˜๋ฉด, ํ•ด๋‹นํ•˜๋Š” ๋ชจ๋“  ์Šคํƒ€์ผ์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์˜ props ์™€ ๊ธ€๋กœ๋ฒŒ ํ…Œ๋งˆ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์Šคํƒ€์ผ์„ ์กฐ์ •ํ•˜์—ฌ ์ง๊ด€์ ์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ์Šคํƒ€์ผ์„ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ์กฐ์‚ฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

  • ํ‘œ์ค€์— ๋งž๊ฒŒ CSS๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” Styled Components ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•œ๋‹ค. tailwind ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ํ‘œ์ค€์— ๋งž๋Š” CSS๋Š” ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ง„์ž… ์žฅ๋ฒฝ์ด ์žˆ๋‹ค.

๐ŸŽธ Styled Components ์„ค์น˜

npm ์œผ๋กœ ์„ค์น˜ํ•˜๋˜, type ๊นŒ์ง€ ์„ค์น˜ํ•ด์ค€๋‹ค.

npm install styled-components
npm i -D @types/styled-components @swc/plugin-styled-components

SWC๋กœ Babel ์„ ๋Œ€์ฒดํ•œ๋‹ค.

npm i -D @swc/plugin-styled-components

React ์—์„œ SWC๋ž€?

  • Speedy Web Compiler์˜ ์•ฝ์ž

  • Rust๋กœ ์ž‘์„ฑ๋œ ์ดˆ๊ณ ์† ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ/ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ๋Ÿฌ

  • ๋ฐ”๋ฒจ๊ณผ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์–ด ํ›จ์”ฌ ๋น ๋ฅธ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์„ ์ œ๊ณต

  • SWC๋Š” ์ปดํŒŒ์ผ๊ณผ ๋ฒˆ๋“ค๋ง ๋ชจ๋‘์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ

์ปดํŒŒ์ผ์˜ ๊ฒฝ์šฐ, ์ตœ์‹  JavaScript ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ JavaScript/TypeScript ํŒŒ์ผ์„ ๊ฐ€์ ธ์™€ ๋ชจ๋“  ์ฃผ์š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›๋˜๋Š” ์œ ํšจํ•œ ์ฝ”๋“œ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

.swcrc ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": true,
            "ssr": true
          }
        ]
      ]
    }
  }
}

VSCODE ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ์„ค์น˜(์ค‘์š”)

vscode ์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ vscode-styled-components extension ์„ ์„ค์น˜ํ•œ๋‹ค.


๐Ÿ‘ ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

1. ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฐฉ๋ฒ•

import styled from 'styled-components';

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

export default function Test() {
  <Wrapper>
    <Title className={className}>title</Title>
  </Wrapper>;
}

2. ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์Šคํƒ€์ผ์„ ์ •์˜ํ•œ ํ›„ ๋„˜๊ฒจ๋ฐ›์•„ ์‚ฌ์šฉํ•˜๊ธฐ

import styled from 'styled-components';

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

const BigTitle = styled(Title)`
  font-size: 3em;
`;

const RedBigTitle = styled(BigTitle)`
  font-size: 3em;
  color: red;
`;

export default function Test() {
  <Wrapper>
    <RedBigTitle>title</RedBigTitle>
  </Wrapper>;
}

3. return ์ฝ”๋“œ๋ฅผ ๋”ฐ๋กœ ๋นผ์„œ className ์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ

import styled from 'styled-components';

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

const BigTitle = styled(Title)`
  font-size: 3em;
`;

const RedBigTitle = styled(BigTitle)`
  font-size: 3em;
  color: red;
`;

function TitleCSS({ className }: React.HtmlHTMLAttributes<HTMLElement>) {
  return (
    <Wrapper>
      <RedBigTitle className={className}>title</RedBigTitle>
    </Wrapper>
  );
}

const SmallTitle = styled(TitleCSS)`
  font-size: 0.8rem;
`;

export default function Test() {
  return <SmallTitle />;
}

์•Œ์•„๋‘˜ ๊ฒƒ: styled. ์˜ ์—ญํ• ์€ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

3. props ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ ์œผ๋กœ CSS ์†์„ฑ ๊ฐ’์„ ๋ณ€๊ฒฝ

version 1

import { styled } from 'styled-components';
import { useBoolean } from 'usehooks-ts';

type ButtonProps = {
  active?: boolean;
};

function background(props: ButtonProps) {
  return props.active ? '#00FF' : '#FFF';
}

const Button = styled.button<ButtonProps>`
  background: ${(props) => background(props)};
`;

export default function Switch() {
  const { value: active, toggle } = useBoolean(false);

  return (
    <Button type='button' onClick={toggle} active={active}>
      On/Off
    </Button>
  );
}

version 2

import { styled } from 'styled-components';
import { useBoolean } from 'usehooks-ts';

type ButtonProps = {
  active?: boolean;
};

const Button = styled.button<ButtonProps>`
  font-size: ${(props: ButtonProps) => (props.active ? '2rem' : '1rem')};
  background: #fff;
`;

export default function Switch() {
  const { value: active, toggle } = useBoolean(false);

  return (
    <Button type='button' onClick={toggle} active={active}>
      On/Off
    </Button>
  );
}

4. attr ์„ค์ •

import { css, styled } from 'styled-components';
import { useBoolean } from 'usehooks-ts';

type ButtonProps = {
  type?: 'button' | 'submit' | 'reset';
  active?: boolean;
};

const Button = styled.button.attrs<ButtonProps>((props) => ({
  type: props.type ?? 'button',
}))<ButtonProps>`
  background: #fff;

  ${(props: ButtonProps) =>
    props.active &&
    css`
      background: red;
    `}
`;

const PrimaryButton = styled(Button)`
  background: black;
  color: white;

  ${(props: ButtonProps) =>
    props.active &&
    css`
      background: red;
    `}
`;

export default function Switch() {
  const { value: active, toggle } = useBoolean(false);

  return (
    <PrimaryButton type='submit' onClick={toggle} active={active}>
      On/Off
    </PrimaryButton>
  );
}

Theme

jest manual mock ๋ฌธ์„œ ๋ณด๊ธฐ

Last updated