[Front-End] 복잡한 styled-components 구조 개선해보기

하영·2022년 11월 22일
34

Front-End

목록 보기
3/4
post-thumbnail
post-custom-banner

0. 들어가며

너저분한 styled-components 코드와 계속 내려가는 스크롤 ,,,

styled-components 를 주요 스타일링 기술로 사용하지만 구조를 깔끔하게 하고 효율적으로 작성할 줄 모릅니다. 그래서 페이지 하나에 절반이 스타일 관련 코드인 경우가 대부분이죠 ... 🤦‍♀️중복되는 스타일 코드도 많고 하나 고치기 위해 스크롤을 계속 왔다갔다 해야 했습니다. 정말 불편하기도 하고,재사용 하기에 좋지 못한 코드라 생각이 점차 들어서 마음 먹고 개선해봐야 겠다는 생각이 들었습니다.

1. 컴포넌트 이름은 어떻게?

컴포넌트들의 이름을 지으려다 보면 혼란에 빠집니다.

  • 감싸는 컴포넌트니까 Wrapper 로 할까?
  • 컴포넌트를 담는 컴포넌트니까 Container로 할까?
  • 아닌가.. 관련없이 Box로 하는게 맞을까?
  • 어순을 어떻게 하면 좋을까

와 같은 생각을 끊임없이 반복합니다. 정해진 규칙이 있어야 다른 사람들에게 설명하기도 편하고 사람들이 이해하기도 편하니까요. 그렇게 해서 정한 컨벤션은 아래와 같습니다.

  • 컴포넌트의 이름은 반드시 대문자로 시작하여야 합니다.
  • 1개의 요소를 감싸는 컴포넌트는 Wrapper 로 끝나게끔 짓습니다.
  • 여러개 요소를 감싸는 컴포넌트는 Container로 끝나게끔 짓습니다.
  • 최상위 레이아웃 설정 컴포넌트는 Layout 으로 끝나게끔 짓습니다
  • div 태그 컴포넌트 이름은 자유롭게 하나 Box를 제안합니다
  • ul 태그 컴포넌트는 List로 끝나게끔 짓습니다
  • li 태그 컴포넌트는 Item 으로 끝나게끔 짓습니다
  • 반복되는 컴포넌트는 Item 으로 끝나게끔 짓습니다
  • 모든 컴포넌트의 이름에는 기능을 암시하는 단어를 집어넣습니다.
const CompleteButtonWrapper = styled.div`
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top: 0.5rem;
`;

이런식으로 말이죠... !!

2. 어떨때 컴포넌트를 만들어야 될까?

이름을 짓고 나면 이어서 하는 고민입니다. 매번 컴포넌트를 만들기엔 재사용 되는 컴포넌트도 있지만 아닌 컴포넌트도 있기 때문이에요.

저는 여러 곳에서 재사용 되지 않는 컴포넌트라면 가장 상위의 태그만 스타일 컴포넌트로 만들어주고 하위 태그들은className을 사용해서 스타일링을 합니다. 또는 & 를 활용하여 하위선택자에 스타일링 합니다.

const KakaoLoginBtn = styled.button`
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 30px;
  border-radius: 30px;
  height: 50px;
  background-color: #fbe54d;
  border: none;
  margin-bottom: 20%;
  &:hover {
    cursor: pointer;
  }
  & img {
    position: relative;
    width: 18px;
    height: 17px;
    margin-right: 20px;
  }
  & span {
    font-weight: bold;
    color: #391c1c;
  }
`;

하지만, props 를 사용하여 특정 변수 값을 전달하거나 css 를 활용하여 경우에 따른 렌더링 변화를 주기 위해서는 컴포넌트로 제작해주어야 합니다.

반복 사용 되거나 다른 페이지에서 재사용 될 수도 있는 태그는 컴포넌트로 만들어 주면 좋을 것 같습니다.

3. S-dot 네이밍

3.1 S-dot 네이밍 이란?

또다른 문제는 스타일 코드가 길어지면 파일 내에 코드가 어마무시하게 길어지게 됩니다 ... 맨 위에 걸어둔 사진 처럼요. 저는 이게 정말 싫었습니다. 지저분하고 찾기도 어려웠어요,, 그래서 구글을 찾아보니 좋은 방법이 있었습니다.!!!!! 😊😊😊

모듈을 불러올 때 import *방식을 사용하여 불러온 뒤 S로 네이밍을 변경하는 방식입니다.

S-dot 네이밍을 사용하기 위해서는 style 코드와 component 코드를 구분하게 되는데, 이것만 해도 코드를 구분하기 정말 쉬워질 듯 합니다.

component 파일명create.tsx 라면 style 파일명create.style.ts 로 지어주도록 합니다.

style.ts 파일은 styles
S-dot 네이밍을 사용하면 아래와 같은 장점이 있다고 합니다.

  • 컴포넌트와 스타일 컴포넌트간에 구분이 쉬워진다
  • styled-components를 export 하여 다른 파일에서도 쉽게 사용할 수 있다
  • import 구문이 한층 더 간결해집니다
  • 자동완성이 잘 됩니다

간결한 컴포넌트를 작성할 땐 하나의 파일에 작성해도 될 듯 합니다! 필요한 경우에만 구분하면 좋을 것 같아요.

3.2 적용 방법은?

styles 폴더에 pages 폴더 구조와 동일하게 styles 폴더를 구성해줍니다. 헷갈리지 않도록..

예를 들어, pages/member/login.tsx 페이지의 스타일 코드를 분리 하기 위해 styles/member/login.style.ts 파일을 만듭니다

기존 pages/member/login.tsx 에 있는 스타일링 코드를 모두 옮깁니다. 스타일 코드를 가져온 후, 작성한 styled-components 는 모두 export 해주어야 합니다!

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

export const bounce = keyframes` 
  0% {transform: translatey(0px);}
  5% {transform: translatey(-10px);}
  10% {transform: translatey(0px);}
  100% {transform: translatey(0px);}
`;


export const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background-color: #fff;
`;
 export const MainContainer = styled.div`
  background-color: white;
  border-radius: 30px;
  display: flex;
  position: relative;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
`;
export const Title = styled.div`
  span {
    position: relative;
    display: inline-block;
    animation: ${bounce} 2s linear 0.1s infinite;
    &:nth-child(2) {
      animation-delay: 0.2s;
    }
    &:nth-child(3) {
      animation-delay: 0.3s;
    }
    &:nth-child(4) {
      animation-delay: 0.4s;
    }
  }
  font-family: 'RixInooAriDuriR';
  font-size: 3.5rem;
  color: #ff4d57;
  padding: 1rem 0 1rem 0;
  margin-bottom: 10%;
`;
export const SubTitle = styled.div`
  font-size: 18px;
  font-weight: bold;
  text-align: center;
  margin-bottom: 20%;
  strong {
    color: #ff4d57;
  }
`;
export const KakaoLoginBtn = styled.button`
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 30px;
  border-radius: 30px;
  height: 50px;
  background-color: #fbe54d;
  border: none;
  margin-bottom: 20%;
  &:hover {
    cursor: pointer;
  }
  & img {
    position: relative;
    width: 18px;
    height: 17px;
    margin-right: 20px;
  }
  & span {
    font-weight: bold;
    color: #391c1c;
  }
`;

그리고 pages/member/login.tsx 기존 페이지 컴포넌트로 돌아와서 코드를 변경해줍니다

import * as S from 'styles/member/login.style';

S 라는 이름으로 style.ts 에서 내보내는 모든 컴포넌트를 가져옵니다
S.Wrapper 식으로 접근이 가능합니다

아래에 이어서 작성해줍니다

<S.Wrapper>
  <S.MainContainer>
    <S.Title>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </S.Title>
    <S.SubTitle>
      로그인 <strong>1</strong>초컷 하고 <br />
      <strong>나만의 퀴즈</strong>를 만들어보세요!
    </S.SubTitle>
    <S.KakaoLoginBtn onClick={goKakaoLogin}>
      <img src={'/assets/img/kakao_icon.png'} />
      <span>카카오로 시작하기</span>
    </S.KakaoLoginBtn>
  </S.MainContainer>
</S.Wrapper>

페이지 내 스타일 코드가 줄어들어 기능에 더 집중할 수 있게 되었습니다! 복잡하지도 않고요!

4. ThemeProvider로 공통 스타일 속성 관리

보통은 전역으로 적용해야 하는 스타일이 있을때, 공통으로 사용되는 변수가 있을 때 전역 스타일링을 사용합니다. styled-components 에서도 전역 스타일링을 제공합니다.

하지만 사용하고 있지 않았죠.. 정말 불편하게 코딩하고 있었음..

서비스에서 자주 사용하는 색상코드를 변수화 하고자 시도해보았습니다. 기존 css에서 제공하는 :root 처럼 말이죠 !

styles/theme.ts 파일을 만들어 주고 아래와 같이 색상팔레트를 만들어줍니다. 저는 임시로 메인 컬러만 작성해보았어요

const theme = {
    mainColor: '#ff4d57',
};
export default theme;

이를 적용하기 위해서는 ThemeProvider를 사용합니다. 그리고 이를 통해 porps 형태로 theme에 지정된 값들을 가져올 수 있습니다. color 말고도 다양한 스타일 요소 적용이 가능합니다! 다크모드 같은걸 만들때 좋죠.

가장 상위 파일로 이동한 후 아래 코드를 추가합니다
pages/_app.tsx

import styled, { ThemeProvider } from 'styled-components';
import theme from 'styles/theme';

... 

<ThemeProvider theme={theme}>
	<Component {...pageProps} />
</ThemeProvider>
color: ${(props) => props.theme.mainColor};

와 같이 적용하여 사용하면 됩니다!.

4. 마치며

프론트엔드가 스타일 보다는 기능에 조금 더 치중한 건 맞지만, 스타일 능력은 가장 기본이라고 생각합니다. 효율적으로 하는 건 필수역량 일 것 같구요! 이를 항상 부족하게 여겼기 때문에 부족함을 채워나가는 기회를 꼭 얻고 싶었습니다. 찾아보니 좋은 방법이 있어 바로 적용해 보았습니다. 코드가 깔끔해지고 매우 만족스럽네요 !

꾸준히 적용할 수 있었으면 좋겠습니다.. 어서 손에 익기를 !

공부하며 작성한 글이기 때문에 부족한 부분이나 궁금한 점이 있으시다면 댓글 자유롭게 남겨주세요 😊 감사합니다!

출처

profile
maker를 넘어 solver를 지향합니다.
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 2월 19일

참고가 많이 됫습니다 감사합니다

답글 달기