Logo

React로 버튼 컴포넌트 만들기

버튼은 웹 에서 사용자와 상호 작용에 있어서 핵심이 되는 요소로서 하나의 웹 애플리케이션에서도 여러 종류의 버튼이 필요하기 마련입니다.

이번 포스팅에서는 다앙한 크기와 형태의 버튼을 표현하기 위해 사용할 수 있는 React로 컴포넌트를 함께 개발해보도록 하겠습니다.

컴포넌트 함수

우선 disabledchildren prop을 인자로 받고 아무 스타일링없이 단순히 <button> HTML 엘리먼트를 반환하는 간단한 컴포넌트 함수를 작성합니다.

// Button.jsx

function Button({ disabled, children }) {
  return <button disabled={disabled}>{children}</button>;
}

export default Button;

지금부터 React에서 Styled Components 라이브러리를 사용해서 이 버튼 컴포넌트에 필요한 스타일을 적용하도록 하겠습니다.

Styled Components에 대한 자세한 설명은 관련 포스팅를 참고 바랍니다.

기본 스타일링

버튼 컴포넌트가 어떤 상황에서 사용되든지 공통적으로 필요한 스타일을 먼저 적용해볼까요?

Styled Components로 <StyledButton/> 컴포넌트를 생성한 후, 버튼의 기본적인 스타일을 CSS로 정의해줍니다. 여기서 버튼 종류의 따라 바뀔 수 있는 속성값에는 CSS 변수(CSS variable, CSS custom property)를 사용하였습니다.

이제 컴포넌트 함수가 반환하는 값을 <button> 엘리먼트가 아닌 <StyledButton/> 컴포넌트로 교체해줍니다.

// Button.jsx

import styled from "styled-components";

function Button({ disabled, children }) {
  return <StyledButton disabled={disabled}>{children}</StyledButton>;
}

const StyledButton = styled.button`
  margin: 0;
  border: none;
  cursor: pointer;
  font-family: "Noto Sans KR", sans-serif;
  font-size: var(--button-font-size, 1rem);
  padding: var(--button-padding, 12px 16px);
  border-radius: var(--button-radius, 8px);
  background: var(--button-bg-color, #0d6efd);
  color: var(--button-color, #ffffff);

  &:active,
  &:hover,
  &:focus {
    background: var(--button-hover-bg-color, #025ce2);
  }

  &:disabled {
    cursor: default;
    opacity: 0.5;
    background: var(--button-bg-color, #025ce2);
  }
`;

export default Button;

크기 스타일링

여러 가지 크기를 지원하는 버튼 컴포넌트를 만들기 위해서 size라는 prop을 추가합니다. 버튼 크기에 영향을 줄 수 있는 CSS 변수를 Styled Components의 css 함수를 사용하여 SIZES라는 자바스크립트 객체 저장해두었습니다.

// Button.jsx

import styled, { css } from "styled-components";

const SIZES = {
  sm: css`
    --button-font-size: 0.875rem;
    --button-padding: 8px 12px;
    --button-radius: 4px;
  `,
  md: css`
    --button-font-size: 1rem;
    --button-padding: 12px 16px;
    --button-radius: 8px;
  `,
  lg: css`
    --button-font-size: 1.25rem;
    --button-padding: 16px 20px;
    --button-radius: 12px;
  `,
};

function Button({ disabled, size, children }) {
  const sizeStyle = SIZES[size];

  return (
    <StyledButton disabled={disabled} sizeStyle={sizeStyle}>
      {children}
    </StyledButton>
  );
}

const StyledButton = styled.button`
  ${(p) => p.sizeStyle}

  margin: 0;
  border: none;
  cursor: pointer;
  /* 이하 생략 */
`;

export default Button;

변형 스타일링

성공, 오류, 경고 등 여러 상황에서 활용이 가능한 버튼 컴포넌트를 만들기 위해서 variant라는 prop을 추가합니다. 마찬가지 방법으로 버튼 형태에 영향을 줄 수 있는 CSS 변수를 Styled Components의 css 함수를 사용하여 자바스크립트 객체 VARIANTS라는 자바스크립트 객체 저장해두었습니다.

// Button.jsx

import styled, { css } from "styled-components";

const SIZES = {
  // 생략
};

const VARIANTS = {
  success: css`
    --button-color: #ffffff;
    --button-bg-color: #28a745;
    --button-hover-bg-color: #218838;
  `,
  error: css`
    --button-color: #ffffff;
    --button-bg-color: #dc3545;
    --button-hover-bg-color: #c82333;
  `,
  warning: css`
    --button-color: #212529;
    --button-bg-color: #ffc107;
    --button-hover-bg-color: #e0a800;
  `,
};

function Button({ disabled, size, variant, children }) {
  const sizeStyle = SIZES[size];
  const variantStyle = VARIANTS[variant];

  return (
    <StyledButton
      disabled={disabled}
      sizeStyle={sizeStyle}
      variantStyle={variantStyle}
    >
      {children}
    </StyledButton>
  );
}

const StyledButton = styled.button`
  ${(p) => p.sizeStyle}
  ${(p) => p.variantStyle}

  margin: 0;
  border: none;
  cursor: pointer;
  /* 이하 생략 */
`;

export default Button;

전체 코드

본 포스팅에서 작성한 코드는 아래에서 직접 확인하고 실행해볼 수 있습니다.

마치면서

이상으로 React와 Styled Components를 사용해서 재사용이 용이한 버튼 컴포넌트를 만들어보았습니다.

많은 React 프로젝트에서 이렇게 하나의 버튼 컴포넌트를 만들어 놓고 여러 컴포넌트에서 재사용하는 패턴이 많이 사용됩니다. 필요할 때 마다 매번 처음부터 버튼 컴포넌트를 만들면 중복해서 코딩을 해야할 뿐만 아니라 일관성있는 UI를 제공하기 어려워지기 때문입니다.