React 106 _ styled-components

suineGy zaL·2022년 10월 24일
0

React

목록 보기
9/9

리액트는 웹 애플리케이션 개발에 사용하는 라이브러리이다. 그러므로 스타일링에는 물론 웹 개발과 동일한 CSS를 사용할 수 있다.

프로젝트 생성

npx create-react-app my-app-style --template=typescript

컴포넌트 사용을 보기 위해서는 css는 넘어가도 됨


css파일 사용가능

연습을 위해 public에 temp.css파일을 추가하고 수정한다.

.App-header{
    background-color: red !important;
}

제대로 적용되는지 확인하기 위해 App-header클래스의 배경에 강제적으로 빨간색을 표시하도록 했다
그럼 이제 public의 index.html를 수정하자

<link rel="stylesheet" href="%PUBLIC_URL%/temp.css"/>
<title>React App</title>

보통의 웹서비스처럼 태그를 사용해서 temp.css파일을 불러왔다
create-react-app으로 만든 프로젝트의 public폴더에는 %PUBLIC_URL%을 사용해서 지정해야한다. css가 적용되었는지 확인하자

npm start

으악

리액트 프로젝트가 문제 없이 실행되면 빨간색 배경의 페이지가 열리는 것을 확인 할 수 있다. 이렇게 보통의 웹 페이지처럼 css를 추가해서 웹 서비스의 스타일링을 할 수 있다.

하지만 리액트는 보통의 웹서비스 개발과는 다르게 💡컴포넌트 중심으로 개발한다. 그러므로 이렇게 모든 css를 한 곳에서 관리하게 되면 어떤 컴포넌트에서 어떤 스타일으 활용하는지 쉽게 알 수 없기 때문에

css파일도 리액트 컴포넌트 파일에서 import하는 방식으로 💡스타일도 컴포넌트 중심으로 설계할 수 있도록 한다.


css 컴포넌트 import

기본적으로 생성된 프로젝트에서 역시 import를 한 것을 볼 수 있다.

리액트는 위와같이 JSX파일에서 직접 CSS를 import하는 것으로 해당 리액트 컴포넌트가 어떤 스타일을 사용하는지 알 수 있도록 하고 있다. 해당 스타일이 적용되고 있는지 확인하기 위해 ./src/App.css 파일을 열어 배경 색을 강제적으로 되돌리도록 수정해보자

.App-header {
  background-color: #282c34 !important;


시뻘건 색이었던 배경이 다시 원래 색으로 되돌아 왔다.
이렇게 리액트에서는 link태그를 통해 css를 사용할 수 도 있고 컴포넌트에서 css를 import해 사용할 수도 있다.

보통 리액트는 컴포넌트를 기반으로 개발하게 되고 컴포넌트 별로 css를 갖는 형식으로 스타일을 관리하게 된다.

모든 css를 한곳에서 관리하지 않다 보면 vss의 클래스명이 중복되어 잘못된 스타일이 적용될 수 있다.
반면에 한 곳에서 모든 스타일을 관리하다보면 어떤 스타일이 컴포넌트에 적용되고 있는지 한눈에 알 수 없다.

이런 문제를 해결하고자 styled-components 라이브러리가 탄생했고 리액트에서 이걸 사용해 스타일을 적용할 수 있다

장점

  • 클래스 이름 버그 해결
    보통 css에 클래스 이름을 생성하고 스타일을 작성한 다음 해당 이름을 html 태그에 적용함으로 스타일을 적용하지만 이런 방식은 클래스명의 중복, 겹침 또는 철자 오류가 발생할 수 있다. styled-components는 스타일을 컴포넌트에 직접 적용함으로 이런 문제를 해결하고 있다.
  • 더 쉬운 css 관리
    일반적인 방식으로 스타일을 적용하면 해당 스타일의 클래스가 코드의 어디에서 사용되는지 쉽게 알 수 없다. styled-components에서는 모든 스타일이 특정 컴포넌트에 연결되기 때문에 더 명확히 사용되는 스타일을 알 수 있고, 또 그이유로 인해 사용되지 않은 불필요한 스타일을 쉽게 제거할 수 있다.
  • 간단한 동적 스타일 적용
    동적인 스타일을 관리하기 위해 여러 클래스를 만들 필요가 없으며 컴포넌트의 상태에 따라 쉽고 직관적으로 동적 스타일을 적용할 수 있다.
  • css 자동 구성
    styled-components는 페이지에 렌더링되는 컴포넌트를 추적하여 해당 스타일을 완전히 자동으로 추가한다. 또한 코드 분할(code-splitting)과 결합하여 사용자가 필요한 최소한의 코드를 자동으로 추가한다.

프로젝트에 적용

my-app-style>cd my-app-style
npm install --save-dev @types/styled-components jest-styled-components
  • 현재 페이지를 styled-components를 사용해 리펙토링해 보자 App.tsx파일을 열어 import한다
import './App.css';
import Styled from 'styled-components';
  • .App클래스를 대체할 새로운 컴포넌트를 생성하기 위해 App.tsx에 코드를 추가한다.
...
import Styled from 'styled-components';

const Container = Styled.div`
`;
...

💡 styled-components를 사용하여 리액트 컴포넌트를 생성하기 위해서는 Styled.[HTML 태그]형식과 자바스크립트의 탬플릿 리터럴(Template literals,`)를 사용한다. 이 템플릿 리터럴 기호 안에 다음과 같이 스타일을 작성함으로써 컴포넌트의 스타일링을 하게 된다.

...
const Container = Styled.div`
	text-align: center;
`;
...
  • 이제 styled-components로 생성한 리액트 컴포넌트를 사용하기 위해 .App클래스를 사용하는 부분을 찾아 수정한다.
function App() {
  return (
    //<div className="App">
    <Container>
      ...
    </Container>
    //</div>
  );
}

기존에 있던

태그 부분은 삭제해되 되지만 비교하기 쉽게 하니까 공부하는거니까 주석 처리했다.

  • 내가 만든 styled-components를 사용하기 위해
    태그의 css 클래스 명을 제거하고
  • 태그 대신 styled-components로 만든 컴포넌트를 사용했다 >리액트에서는 class 대신 className을 사용해 클래스를 지정한다.

브라우저는 아무 변화 없이 잘 돌아간다.

  • 태그 도 변경해 보자 (App.css파일에 있는 코드이다)
...
const Container = Styled.div`
  text-align: center;
`;
const Header = Styled.header`
background-color:#282c34 !important;
min-height:100vh;
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
font-size:calc(10px+2vmin);
color:white;
`;
...

앞에서 만든 Container 컴포넌트와 마찬가지로 Styled[HTML태그]와 탬플릿 리터럴을 사용해 Header 컴포넌트를 정의했다

  • 이렇게 생성한 styled-components의 컴포넌트를 사용하기 위해 App.tsx파일을 수정한다.
...
function App() {
  return (
    //<div className="App">
    <Container>
      {/*<header className="App-header">*/}
      <Header>
        ...
        </Header>
      {/*</header>*/}
    </Container>
    //</div>
  );
}

역시 비교하기 쉽게 하려고

태그를 삭제하지 않고 주석 처리 했다. 그리고 styled-components로 만든 Header 컴포넌트를 태그 대신 사용했다

  • 애니메이션이 표함되어 조금 복잡한 .App-logo 클래스를 변경해보자 App.tsx
...
const AppLogo = Styled.img`
  height: 40vmin;
  pointer-events: none;
`;
...

실제 사용하는 부분도 수정해 준다.

...
{/*<img src={logo} className="App-logo" alt="logo" />*/}
<AppLogo src={logo} alt="logo" />
...

로고는 나오지만 애니메이션은 적용하지 않았기 때문에 회전하지는 않는다.

  • 회전 애니메이션 추가
...
const AppLogo = Styled.img`
  height: 40vmin;
  pointer-events: none;
  @media (prefers-reduced-motion: no-preference){
    animation: App-logo-spin infinite 20s linear;
  }
  @keyframes App-logo-spin{
    from{
    transform:rotate(0deg);
  }
  to{
    transform:rotate(360deg);
  }
`;
...

이것 역시 App.css파일을 복붙한건데 차이가 있다면 css는 애니메이션을 사용할 클래스명이 다르다

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

반면 styled-components에서는 해당 컴포넌트가 직접 애니메이션을 수행하므로 클래스명을 특별히 지정하지 않아도 된다.

...
const AppLogo = Styled.img`
 ...
  @media (prefers-reduced-motion: no-preference){
    animation: App-logo-spin infinite 20s linear;
  }
 ...
`;

이렇게 수정한 후 브라우저를 확인해 보면 이전과 같이 로고가 잘 회전하고 있는걸 볼 수 있다.

이렇게 애니메이션이 한 곳에서만 사용되는 경우, 하나의 컴포넌트에 전부 선언하여도 된다.
하지만 여러곳에서 같은 애니메이션을 사용한다면 styled-components의 keyframes을 사용해 분리할 수 있다. App.tsx

import Styled, {keyframes} from 'styled-components';

그리고 keyframes를 사용해 로고 이미지에서 사용할 회전 애니메이션을 선언한다.

const spin = keyframes`
  from{
    transform:rotate(0deg);
  }
  to{
    transform:rotate(360deg);
  }
`;

실제 애니메이션을 사용하는 부분에 keyframes를 적용한다.

const AppLogo = Styled.img`
  height: 40vmin;
  pointer-events: none;
  @media (prefers-reduced-motion: no-preference){
    animation: ${spin} infinite 20s linear;
  }
`;

styled-components는 자바스크립트의 탬플릿 리터럴을 사용하기 때문에 위와 같이 문자열 중간에 자바스크립트 변수를 사용할 수 있다. 이처럼 자주 반복되어 사용되는 애니메이션은 keyframes를 사용해 미리 정의하고 필요한 부분에서 불러와 사용하면 된다.

태그에는 어떤 스타일도 적용되어 있지 않으니 패스하고 `.App-link`클래스를 변경해보자

App.tsx

...
const AppLink = Styled.a`
  color: #61dafb;
`;
...
<AppLink
  href="https://reactjs.org"
  target="_blank"
  rel="noopener noreferrer"
  >
    Learn React
</AppLink>

스타일에 관예하는 모든 css 내용을 수정했다 이제 import를 해제해도 그대로 메인 페이지가 잘 보인다.

그럼 이제 이 코드가 제대로 동작하는지 확인해보자. 이전에 사용했던 코드들을 사용할 것이다.

--업데이트 됨

profile
숲으로

0개의 댓글