[회고] Styled-Components를 사용하며

Styled-Component

  • CSS in JS : 자바스크립트를 이용해서 CSS 작성하는 방식
  • Props 전달 : Style 컴포넌트를 만들어 전달받은 props를 이용해 선택적으로 CSS를 사용할 수 있음

스타일 컴포넌트를 사용하면서 가장 신경이 쓰였던 부분은 바로 네이밍 이었다.
여러가지 방법으로 코드를 작성해 보았지만 보기에 깔끔해 보이지 않아서 계속해서 고민을 하게 되었다.

지금까지 사용해왔던 방법들에 대해서 간단히 설명하고 어떤식으로 조정할 수 있을지 적어 보려고 한다.

01. Component 네이밍

첫번째 방법으로는 컴포넌트에 특정 기능에 맞는 이름을 넣어 모든 태그에 네이밍을 해주는 방식이다. 이는 아래와 같다

// MainPage/index.jsx

const MainPage = () => {
	return (
    	<MainPageLayout>
      		<Header>
      			<HeaderTitle>메인 페이지</HeaderTitle>
      			<HeaderNav>
      				<HeaderNavList>
      					// active속성을 props로 전달해서 css를 설정
      					<HeaderNavItem active></HeaderNavItem>
      					<HeaderNavItem>메뉴1</HeaderNavItem>
      					<HeaderNavItem>메뉴2</HeaderNavItem>
      				</HeaderNavList>
      			</HeaderNav>
      		</Header>
      		<Content>
      			<SlideContent>
      				<ContentItem>1</ContentItem>
      				<ContentItem>2</ContentItem>
      				<ContentItem>3</ContentItem>
      			</SlideContent>
      		</Content>
      		<Footer>
      			하단 내용
      		</Footer>
      	</MainPageLayout>
    )
}
  
// MainPage/styles.js

export const MainPageLayout = styled.div``;
export const Header = styled.header``;
export const HeaderTitle = styled.h1``;
export const HeaderNav = styled.nav``;
export const HeaderNavList = styled.ul``;
export const HeaderNavItem = styled.li`
	// active 속성이 true면 파란색 아니면 하얀색
	color: ${({active}) => active ? 'blue' : '#fff'}
`;
export const Content = styled.nav``;
export const Footer = styled.footer``;

// components/SlideContent/index.jsx
const SlideContent = (props) => {
  	const { children } = props;
  
	return (
    	<SlideContentLayout>
      		{children}
      	</SlideContentLayout>
    )
}

위와 같이 사용하면서 느낀 불편한점

  1. MainPage의 코드만 봤을 때 어떤 html 태그를 사용했는지 알 수 없어 코드가 길어지면 html의 구조를 파악하기 힘들어졌다.
  2. 공통 컴포넌트를 사용할때 스타일 컴포넌트와의 구분이 힘들어졌다.

02. ClassName 네이밍

다음으로 사용해본 방식은 가장 상위의 태그만 스타일 컴포넌트로 만들어주고 안에 있는 태그들에는 className을 이용해서 네이밍 해주는 방식이다.

// MainPage/index.jsx
const MainPage = () => {
	return (
    	<MainPageLayout>
      		<header className="header">
      			<h2 className="header__title">메인 페이지</h2>
      			<nav className="nav">
      				<ul claName="nav__list">
      					// 특정 조건일때는 className에 --active를 붙여주도록 코드를 작성해야함
      					<li className="nav__item nav__item--active"></li>
            			<li className="nav__item">메뉴1</li>
            			<li className="nav__item">메뉴2</li>
      				</ul>
      			</nav>
      		</header>
      		<div className="content">
      			<SlideContent className="content__list">
      				<li className="content__item">1</li>
      				<li className="content__item">2</li>
      				<li className="content__item">3</li>
      			</SlideContent>
      		</div>
      		<footer className="footer">
      			하단 내용
      		</footer>
      	</MainPageLayout>
    )
}

// MainPage/styles.js
export const MainPageLayout = styled.div`
	.header {
		.header__title {}
		
		.nav {
			.nav__list {
				.nav__item {
					color: #fff;
					.nav__item--active { color: blue }
				}	
			}
		}

		.content {}

		.footer {}
	}
`;

위와 같이 사용하면서 느낀 불편한점

  1. 선택적인 className을 지정 해주는 것이 불편함. props나 상태에 따라서 다른 스타일을 주기위해서는 className 속성으로 조건문을 이용해 className을 선택적으로 지정해줘야 함
  2. html의 하위 태그들이 많아지게 되면 className의 네이밍이 힘들어지고 길어짐 또한 SCSS 뎁스가 깊어져서 복잡해짐

03. 혼합 네이밍

위의 두 방식을 혼합한 방식으로 스타일만 가지고있는 태그들은 className을 이용해 네이밍하고, 상태를 가지고있는 태그들은 스타일 컴포넌트를 이용해 네이밍하는 방식이다.

// MainPage/index.jsx
const MainPage = () => {
	return (
    	<MainPageLayout>
      		<header className="header">
      			<h2 className="header__title">메인 페이지</h2>
      			<nav className="nav">
      				<ul claName="nav__list">
      					// 상태값을 가지는 태그는 스타일 컴포넌트로 분리
      					<NavItem active></NavItem>
            			<NavItem>메뉴1</NavItem>
            			<NavItem>메뉴2</NavItem>
      				</ul>
      			</nav>
      		</header>
      		<div className="content">
      			<SlideContent className="content__list">
      				<li className="content__item">1</li>
      				<li className="content__item">2</li>
      				<li className="content__item">3</li>
      			</SlideContent>
      		</div>
      		<footer className="footer">
      			하단 내용
      		</footer>
      	</MainPageLayout>
    )
}

// MainPage/styles.js
export const NavItem = styled.li`
	color: ${({active}) => active ? 'blue' : '#fff'};
`;
export const MainPageLayout = styled.div`
	.header {
		.header__title {}
		
		.nav {
			.nav__list {}
		}

		.content {}

		.footer {}
	}
`;

위와 같이 사용하면서 느낀 불편한점

  1. 단점이 하나씩 줄어들었지만 그에 따른 단점들도 생김.
  2. className을 이용한 네이밍을 사용함으로써 html의 하위 태그들이 많아지게 되면 className의 네이밍이 힘들어지고 길어짐 또한 SCSS 뎁스가 깊어져서 복잡해짐
  3. styled component 네이밍을 사용함으로써 공통 컴포넌트와의 구분이 힘들어짐

04. 다른 방식들을 찾아..

위와 같은 방식들을 사용해 네이밍을 하면서 다른 개발자분들은 어떤식으로 네이밍을 하는지 궁금해졌다. 그래서 구글링을 해본 결과 나와 같은 방식으로 네이밍을 하는 분들도 있고, 다른 방식으로 하시는 분들도 많았다.

그 중에서 기억에 남는 방식을 정리해보려고 한다.

S-dot 네이밍

스타일 컴포넌트를 분리할때 S라는 이름으로 요약하여 구분해주는 방식이다.
스타일 파일을 분리해서 스타일들을 내보낼때 객체에 담아서 내보내고, 사용할 index파일에서 모든 요소들을 S라는 이름으로 묶어서 불러와 사용한다.

// MainPage/index.jsx
import * as S from ./styles.js;

const MainPage = () => {
	return (
    	<S.MainPageLayout>
      		<S.Header>
      			<S.HeaderTitle>메인 페이지</HeaderTitle>
      			<S.HeaderNav>
      				<S.HeaderNavList>
      					// active속성을 props로 전달해서 css를 설정
      					<S.HeaderNavItem active></S.HeaderNavItem>
      					<S.HeaderNavItem>메뉴1</S.HeaderNavItem>
      					<S.HeaderNavItem>메뉴2</S.HeaderNavItem>
      				</S.HeaderNavList>
      			</S.HeaderNav>
      		</S.Header>
      		<S.Content>
      			<SlideContent>
      				<ContentItem>1</S.ContentItem>
      				<ContentItem>2</S.ContentItem>
      				<ContentItem>3</S.ContentItem>
      			</SlideContent>
      		</S.Content>
      		<S.Footer>
      			하단 내용
      		</S.Footer>
      	</S.MainPageLayout>
    )
}
  
// MainPage/styles.js

export const MainPageLayout = styled.div``;
export const Header = styled.header``;
export const HeaderTitle = styled.h1``;
export const HeaderNav = styled.nav``;
export const HeaderNavList = styled.ul``;
export const HeaderNavItem = styled.li`
	color: ${({active}) => active ? 'blue' : '#fff'}
`;
export const Content = styled.nav``;
export const Footer = styled.footer``;

// components/SlideContent/index.jsx
export const ContentItem = ({children}) => {
	return (
    	<ContentItemLayout>
     		{children}
      	</ContentItemLayout>
    )
}

const SlideContent = (props) => {
  	const { children } = props;
  
	return (
    	<SlideContentLayout>
      		{children}
      	</SlideContentLayout>
    )
}

위와 같은 방식으로 코드를 작성하면 스타일 컴포넌트와 공통 컴포넌트의 분리가 용이해진다. 또한, MainPage의 코드를 봤을때 html의 구조를 파악하기 어려워지는 문제점은 네이밍 컨벤션을 이용해 해결할 수 있을 것 같다.
스타일 컴포넌트 네이밍 규칙을 정해서 각 태그에 맞는 컴포넌트 명을 사용한다면 html의 구조를 파악하는데 용이할 것이다.

네이밍 컨벤션

  1. 최상위 컴포넌트 명
    • '컴포넌트명'Layout
  2. 각 태그들의 컴포넌트 명
    • div : '컴포넌트명'Box
    • section : '컴포넌트명'Section
    • ul : '컴포넌트명'List
    • li : '컴포넌트명'Item
    • p : '컴포넌트명'Paragraph
    • span : '컴포넌트명'Span
  3. 컴포넌트들을 묶어주는 컴포넌트 명
    • '컴포넌트명'Row/Col

출처

GitHub - Hi-Fi-Club/FE > Styled Components : Naming Convention
미디엄 - Orry Baram : Naming Styled Components

좋은 웹페이지 즐겨찾기