본문 바로가기
웹 프론트엔드/React 리액트 (기초)

[React] 컴포넌트에 스타일을 적용해보자 ① Text

by 지구인한군 2020. 10. 7.

2020/09/29 - [Web프론트엔드/리액트] - [React] 리액트 기초 관련 글 정리 (개발환경, 데이터, 컴포넌트 등)

2020/10/06 - [Web프론트엔드/리액트] - [React] 재활용 가능한 기본적인 Input 컴포넌트

2020/10/06 - [Web프론트엔드/리액트] - [React] 테스트 도구인 스토리북(storybook)을 사용해보자

2020/10/06 - [Web프론트엔드/리액트] - [React] 스토리북에 다양한 확장 도구(Addon) 추가


 지금까지의 포스팅은 컴포넌트의 스타일보다는 기능에 중점을 둔 글이었습니다. 그래서 스타일 관련 글을 다루기 위해, 테스트 도구인 스토리북을 추가하기도 했었습니다. 앞으로 다룰 스타일은 기존 css나 scss가 아닌 직접 컴포넌트에 붙여서 사용할 수 있는 react-with-styles 입니다. 스토리북과 마찬가지로 에어비앤비에서 공개 관리하고 있습니다.

 

먼저 명령 프롬프트를 열어 라이브러리를 추가합니다.

> yarn add react-with-styles aphrodite react-with-styles-interface-aphrodite

여기서 aphrodite(아프로디테)는 스타일을 서버 쪽에서 먼저 적용할 수 있도록 도와주는 라이브러리입니다.

 

문제없이 완료됐다면 아래처럼 기본 스타일 파일을 만듭니다. 혹여 설치에 문제가 있다면 공식 사이트를 참고하세요.

 

// ..\test_project\src\styles\defaultStyles.js

export default {
  size: {
    xg: 24,
    lg: 20,
    md: 16,
    sm: 12,
    xs: 8,
  },
  color: {
    default: "#999999",
    error: "#FF0000",
    white: "#FFFFFF",
    black: "#000000",
    gray: "#CCCCCC",
    primary: "#FF5A5F",
    secondary: "#00A699",
  },
};

 

일단 가장 기본적인 스타일만 정의한 상태입니다. 그럼 이제 아래처럼 공통적으로 쓰일 스타일 함수를 만들겠습니다.

 

// ..\test_project\src\styles\withStyles.js

import themedStyleSheet from "react-with-styles/lib/ThemedStyleSheet";
import aphroditeInterface from "react-with-styles-interface-aphrodite";
import { css, withStyles, withStylesPropTypes } from "react-with-styles";
import defaultStyles from "./defaultStyles";

// 기본적인 스타일(테마)를 등록
themedStyleSheet.registerTheme(defaultStyles);

// 기본 인터페이스로 아프로디테를 사용
themedStyleSheet.registerInterface(aphroditeInterface);

export { css, withStyles, withStylesPropTypes, themedStyleSheet };
export default withStyles;

 

 위에서 만든 기본 스타일을 등록하고 인터페이스를 연결한 뒤에, 컴포넌트에서 사용하기 위해 익스포트 합니다. 이제 준비는 끝났습니다. 실제로 컴포넌트를 만들어서 스타일을 적용하면 됩니다. 그럼 Text.jsx 를 만들어 보시죠!

 

// ..\test_project\src\components\Text.jsx

import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import withStyles, { css } from "../styles/withStyles";

class Text extends PureComponent {
  render() {
    // 상위 컴포넌트에서 넘어오는 프로퍼티
    const {
      // 스타일 옵션 값들 (boolean)
      xsmall,
      small,
      medium,
      large,
      xlarge,
      primary,
      secondary,
      styles, // withStyles에서 정의한 스타일 목록
      children, // Text태그로 감싼 부분 <Text>children(문자 내용)</Text>
    } = this.props;
    return (
      // 전개 연산자를 사용해 span 엘리먼트 적용
      <span
        {...css(
          styles.default,
          xsmall && styles.xsmall,
          small && styles.small,
          medium && styles.medium,
          large && styles.large,
          xlarge && styles.xlarge,
          primary && styles.primary,
          secondary && styles.secondary
        )}
      >
        {children}
      </span>
    );
  }
}

// children(문자 내용) 필수, 나머지는 중복 가능한 옵션 값
Text.propTypes = {
  children: PropTypes.node.isRequired,
  xsmall: PropTypes.bool,
  small: PropTypes.bool,
  medium: PropTypes.bool,
  large: PropTypes.bool,
  xlarge: PropTypes.bool,
  primary: PropTypes.bool,
  secondary: PropTypes.bool,
};

// withStyles()함수를 사용해 defaultStyles.js 내용으로 매칭
export default withStyles(({ size, color }) => ({
  default: {
    fontSize: size.medium,
    color: color.default,
  },
  xsmall: {
    fontSize: size.xsmall,
  },
  small: {
    fontSize: size.small,
  },
  medium: {
    fontSize: size.medium,
  },
  large: {
    fontSize: size.large,
  },
  xlarge: {
    fontSize: size.xlarge,
  },
  primary: {
    color: color.primary,
  },
  secondary: {
    color: color.secondary,
  },
}))(Text);

 

 소스가 길어 보이지만 대부분 스타일 적용을 위한 옵션입니다. 중요한 부분은 span 태그에 엘리먼트를 적용하는 것인데, 상위 컴포넌트에서 받은 옵션의 유무로 withStyles() 함수에서 정의한 값들을 css() 함수의 인수로 넣고, 객체형 반환 값들을 전개 연산자(...)로 span 태그의 엘리먼트에 대입하고 있습니다. 이제 스토리북에 넣어서 확인해보시죠!

 

// ..\test_project\src\stories\Story_TestText.jsx

import React from "react";
import { storiesOf } from "@storybook/react";
import Text from "../components/Text";

storiesOf("Test Text", module)
  .addWithJSX("base", () => <Text>코로나 Goodbye!</Text>)
  .addWithJSX("xsmall", () => <Text xsmall>코로나 Goodbye!</Text>)
  .addWithJSX("small", () => <Text small>코로나 Goodbye!</Text>)
  .addWithJSX("medium", () => <Text medium>코로나 Goodbye!</Text>)
  .addWithJSX("large", () => <Text large>코로나 Goodbye!</Text>)
  .addWithJSX("xlarge", () => <Text xlarge>코로나 Goodbye!</Text>)
  .addWithJSX("primary", () => <Text primary>코로나 Goodbye!</Text>)
  .addWithJSX("secondary", () => <Text secondary>코로나 Goodbye!</Text>)
  // 두가지 옵션을 동시에 사용
  .addWithJSX("xlarge & secondary", () => (
    <Text xlarge secondary>
      코로나 Goodbye!
    </Text>
  ));

 

 위에서 작성한 Text 컴포넌트를 다양한 프로퍼티 옵션으로 사용했습니다. 스타일 관련 포스팅은 App.js 통해 확인이 어려우니, 실습을 하실 분들은 꼭 스토리북 관련 포스팅을 참고해서 확인하시기 바랍니다. 아래는 실행화면입니다.

 

Text 스타일 컴포넌트

 

 왼쪽에 있는 메뉴에서 다양한 옵션을 선택하면 Text 스타일이 적용되는 것을 확인할 수 있습니다.

 

참 스타일 나죠?


2020/10/08 - [Web프론트엔드/리액트] - [React] 컴포넌트에 스타일을 적용해보자 ② Button

댓글