Custom component

Dongwoo Joo·2023년 4월 19일
0

codestates bootcamp

목록 보기
31/48

학습 내용

CDD(Component driven development)

컴포넌트를 중심으로 개발을 수행하는 개발 방법론이다. 비유하면, 마치 레고처럼 조립해 나갈 수 있는 부품 단위로 UI 컴포넌트를 만들어 나가는 개발 방식이다.

개발자들은 작은 단위의 컴포넌트들을 개발하고,
이러한 컴포넌트들을 조합하여 더 큰 기능을 가진 애플리케이션을 구성하는 것이다.
이렇게 구성된 애플리케이션은 재사용성과 유지보수성이 높아지며, 테스트와 개발이 용이해진다.

CDD를 이용하면, 개발자들은 디자이너와 협업하여 컴포넌트에 대한 설계, 스타일, 상태, 인터랙션 등을 정의하고,
이를 이용하여 UI 라이브러리나 디자인 시스템을 만들 수 있다.

CDD는 다양한 형태의 컴포넌트 라이브러리를 이용하여 개발할 수 있다.
예를 들어 React를 이용하여 컴포넌트를 개발하고 Storybook을 이용하여,
컴포넌트의 UI 및 상태를 확인하고 테스트할 수 있다.

이러한 CDD 방법론은 개발자와 디자이너, 프로덕트 매니저 등의 역할을 분리하여 각자의 역할에 집중할 수 있도록 해주고, 협업을 원활하게 할 수 있도록 도와줍니다. 또한, 재사용성이 높은 UI 라이브러리나 디자인 시스템을 만들어 관리할 수 있으므로, 프로젝트의 일관성과 생산성을 높일 수 있습니다.

구조적인 CSS의 발전

히스토리

POST PC 시대가 도래하고, 사용할 수 있는 다양한 하드웨어 기기가 발전했다.
이에 따라 개발자들의 CSS 작성 방식도 꾸준히 진화해왔다.

PC, 모바일, 태블릿 등 다양한 디바이스에서 웹 사이트를 사용하는데,
디바이스의 디스플레이 크기가 제각각 다르므로,CSS는 더욱 복잡해졌다.
CSS 작업을 더욱 효율적으로 하기 위해 구조화된 CSS 필요성이 대두되었다.

CSS 전처리기

CSS 전처리기 개념이 등장했다.
CSS 전처리기는 CSS의 기능을 확장한 스크립트 언어이며, CSS 코드 작성을 효율적으로 하기 위한 도구 중 하나다.
전처리기를 사용하면, 변수, 함수, 조건문, 반복문 등과 같은 기능을 CSS에서 사용할 수 있다.
이를 통해 코드의 재사용성을 높이고, 유지보수성을 향상시킬 수 있다.

대표적인 CSS 전처리기로는 Sass, Less, Stylus 등이 있다.
이들은 모두 변수, mixin, extend 등의 기능을 제공하며,
CSS 작업을 보다 구조화된 방식으로 처리할 수 있도록 도와준다.
또한 이들 전처리기는 브라우저에서 지원하지 않는 기능을 사용할 수 있게 해주기도 한다.

전처리기를 사용함으로써 작업 속도, 코드의 가독성, 유지보수성을 높일 수 있지만, 동시에 여러 단점도 발생되었다.
SASS가 CSS의 구조화를 도입하면서 생긴 문제를 예로 들어보자.

  • SASS의 사용법에 대한 학습 곡선이 상당히 높다.
    이는 기존의 CSS 사용자들에게는 새로운 문법과 개념을 배워야 하기 때문에, 초기 학습 비용이 높아질 수 있다.
  • CSS 파일의 용량이 더욱 커졌다.
    SASS가 CSS 파일을 생성하는 과정에서 많은 중간 파일이 생성되기 때문이다.
    일반적으로는 브라우저에서 직접 접근할 수 없어서, 디버깅의 어려움을 야기한다.
  • 위의 mixin, extend, nesting 등이 기능을 남용하면, CSS의 우선순위를 결정하는 규칙이 깨질 수 있다.
  • 팀 내에서의 협업이 어려워질 수 있다.
    SASS는 언어의 복잡성과 문법적 제약으로 인해 코드를 작성하는 스타일이 팀 내에서 일관성을 유지하기 어렵기 때문이다. 이는 프로젝트가 큰 규모일수록 문제가 커질 수 있다.

공통 지향점과 컴포넌트 방법론

어쨌든, 다양한 방법론의 공통 지향점은 아래와 같다.

  • 코드의 재사용
  • 코드의 간결화(유지 보수 용이)
  • 코드의 확장성
  • 코드의 예측성(클래스 명으로 의미 예측)

이러한 문제들을 해결하기 위해, CSS-in-JS 개념이 만들어졌다.
CSS를 컴포넌트 영역에서 스타일링하는 것이다.
대표적으로 Styled-Component가 있다.

Styled-Component는 기능적 혹은 상태를 가진 컴포넌트들로부터 UI를 완전히 분리해,
사용할 수 있는 아주 단순한 패턴을 제공한다.

CSS-in-JS

CSS-in-JS는 컴포넌트 단위로 CSS 스타일링을 하는 개념으로,
컴포넌트를 렌더링할 때마다 해당 컴포넌트에 필요한 스타일이 동적으로 생성된다.
이렇게 하면 컴포넌트 단위로 스타일링을 하기 때문에,
전역 스타일 충돌과 같은 문제를 해결할 수 있으며, 재사용성과 유지보수성이 향상된다.

Styled component

React(HTML+JS) + CSS
=> React + styled-component = React에서 한꺼번에 HTML+CSS+JS 를 작성한다.

Styled-Component는 React 기반의 CSS-in-JS 라이브러리 중 하나로,
JSX 안에 스타일링 정보를 포함시키는 방식으로 동작한다.

설치

터미널에 Styled Components 라이브러리 설치

$ npm install --save styled-components
$ yarn add styled-components

Styled Components는 package.json에 다음 코드를 추가하도록 권장한다.
아래의 코드를 추가하면 여러 버전의 Styled Components가 설치되어 발생하는 문제를 줄여줍니다.

{
"resolutions": {
"styled-components": "^5"
}
}

  • Styled Components를 사용할 파일로 불러오기
import styled from "styled-components"

문법

컴포넌트 만들기

Styled Components는 ES6의 Templete Literals 문법을 사용한다.
즉, 따옴표가 아닌 백틱을 사용한다.

const 컴포넌트 이름 = styled.태그 css 속성 1 : 속성값; css 속성 2 : 속성값;
태그 끝에부터 백틱을 사용해서 css 속성을 감싸주는 것을 잊지 말자.

예시

const OpenButton = styled.button`
  background-color : green;
  color : white;
`;

컴포넌트 재활용하여 새로운 컴포넌트 만들기

위에서 만든 OpenButton으로 새로운 버튼을 만들 수 있다.
OpenButton과 똑같은 컴포넌트를 재활용 하는 것인데,
이 컴포넌트에 새로운 CSS를 스타일링 할 수 있다.

const NewOpenButton = styled(OpenButton)`
  background-color : green;
  color : white;
`;

자세히보면, styled 뒤에, dot(.)이 오는게 아니라,
소괄호안에 컴포넌트를 입력해주는 문법을 볼 수 있다.

Props 활용하기

Styled Component로 만든 컴포넌트도 React 컴포넌트처럼 props를 내려줄 수 있다.
내려준 props 값에 따라서 컴포넌트를 렌더링 하는 것도 가능하다.

const 컴포넌트 = styled.태그`
   css 속성 : ${ (props) => 함수 코드 }
`;

Styled Components는 템플릿 리터럴 문법(${ })을 사용하여 JavaScript 코드를 사용할 수 있다.
props를 받아오려면 props를 인자로 받는 함수를 만들어 사용하면 된다.

  • Props로 조건부 렌더링
const Button = styled.button`
  background-color: ${(props) => props.green ? "green" : "white" }
`;

삼항 연산자를 사용해, Button 컴포넌트에 green이라는 props가 있으면, 배경색을 green으로, 없으면 white로 지정하는 코드이다.

만약 아래와 같이 컴포넌트를 만들면, 녹색 버튼과 흰색 버튼이 렌더링 될 것이다.

<Button green>Button1</Button> => 녹색 버튼
<Button>Button1</Button> => 흰색 버튼
  • Props 값으로 렌더링하기
    props의 값을 활용해서 컴포넌트 렌더링에 활용할 수 있다.

props의 값을 색으로 나타낸 예시 2가지

const Button1 = styled.button`
  background: ${(props) => (props.color ? props.color : "white")};
`;
// props.color가 있으면, props.color 리턴, 없으면 흰색 리턴
const Button2 = styled.button`
  background: ${(props) => props.color || "white"};
`;
// props.color 또는 흰색 리턴

꼭 삼항 연산자만 사용해야 하는 것은 아니다.
JavaScript 코드라면 무엇이든 사용할 수 있으므로 원하는 값을 사용할 수 있도록,
함수 코드를 만들어서 사용하면 된다.

전역 스타일 설정하기

때론, 컴포넌트에 일일이 스타일을 해주는 것은 번거로울 수도 있다.
전역 스타일링을 할 수 있는 방법이 있다.

  • 전역 스타일을 설정하기 위해 Styled Components에서 createGlobalStyle 함수를 불러온다.
import { createGlobalStyle } from "styled-components";
  • Styled Components 문법에 맞게 스타일을 작성한다.
const GlobalStyle = createGlobalStyle`
	button {
    padding : 10px;
    margin : 5px;
    border-radius : 15px;
	}
`
  • 이렇게 만들어진 컴포넌트를 최상위 컴포넌트에서 사용해 주면, 전역에 컴포넌트의 스타일이 적용된다.
function App() {
	return (
		<>
			<GlobalStyle />
			<Button>전역 스타일 적용</Button>
		</>
	);
}

장단점

장점

React 컴포넌트와 CSS를 결합하여, 이를 하나의 단위로 다룰 수 있다.
스타일 정보와 컴포넌트 로직이 함께 작성되므로, 코드의 가독성과 유지보수성이 향상된다.

CSS 파일을 작성할 필요가 없으며, CSS의 모든 기능을 JavaScript 코드 안에서 사용할 수 있다.
이러한 방식의 CSS-in-JS를 사용함으로써, 애플리케이션의 성능도 개선된다.
또한, Styled Components는 CSS의 캡슐화 기능을 지원하기 때문에,
전역 스타일 충돌을 방지하고, 컴포넌트 내부 스타일의 영향력이 컴포넌트 외부로 노출되는 것을 막아준다.

단점

  • 초기 학습 곡선이 높다.
    기존 CSS를 작성하는 방식과는 다른 방식이기 때문에 처음에는 적응이 필요하다.

  • 성능에 대한 이슈가 있을 수 있다.
    styled component는 컴포넌트 단위로 스타일을 생성하기 때문에 렌더링이 느려질 수 있다.
    이를 해결하기 위해 CSS-in-JS 라이브러리 중에서는 일부가 서버사이드 렌더링에 최적화된 솔루션을 제공하기도 한다.

  • 재사용성과 관리의 어려움.
    스타일을 컴포넌트와 함께 작성하다 보면, 다른 컴포넌트에서 재사용하기가 어려울 수 있다.
    또한 스타일이 분산되어 있어 유지보수가 어려울 수 있다.
    이를 해결하기 위해 컴포넌트 라이브러리와 같은 방법을 사용할 수 있다.

  • 서버사이드 렌더링이 어려울 수 있다.
    styled component는 기본적으로 클라이언트에서 동작하기 때문에 서버사이드 렌더링을 할 때 조금 더 복잡한 설정이 필요할 수 있다.
    이를 해결하기 위해 styled-components에서는 서버사이드 렌더링을 위한 API를 제공한다.

Styled Component는 CSS를 컴포넌트에서 관리할 수 있어 유지보수성이 좋아지고 재사용성도 증가하는 장점이 있지만, 초기 학습 곡선이 높고, 성능과 서버사이드 렌더링 등의 이슈도 고려해야 한다.

Storybook

UI 개발 도구 - 컴포넌트 시각화 & 문서화

useRef

React는 가상 DOM을 사용한다.
가상 DOM을 거쳐서 진짜 DOM을 바꾸는게 react의 기본 작동 방식이다.
진짜 DOM을 직접 건드리는 것은 react의 기본 작동 방식에 어긋나는 방식이다.

하지만, DOM을 직접 건드리는 것이 더 좋은 상황이 있다.
예를 들어, DOM 객체 주소가 필요한 상황이다.
focus, media playback
그 때 사용하려고 useRef 메서드를 만든 것이다.

useRef를 쓸 때, usestate로 상태관리를 하지 않는다.

(중요)리액트에서 상태가 변하면 리렌더링 된다.

예제를 보자.

리렌더링이 되면, 입력창에 작성한 내용이 사라질텐데?
그럼 작성한 내용이 사라지지 않게 하려면?

useState를 쓰는 방식
상태를 4개를 관리해야 한다.
focus, input 1, input2, input3, input4

useRef를 쓰는 방식
상태가 바뀐게 아니기 때문에, 내용이 남아있게 된다.

예제 2번 동영상
상태로 관리할 때,
Play, pause 버튼이 있다.
isplaying 일 때, 재생 상태로 하자.
play, pause를 누를 때면, 리렌더링이 된다.
그럼 중간에 영상을 멈추지 못하게 된다.
따라서, 상태 관리로 쓸 수 없고, useRef를 이용해서 진짜 DOM을 조작해야 한다.

true false 왔다갔다 할 때는, !를 사용하면 좋다.

질의응답

  • 이벤트 버블링
    의도하지 않은 이벤트가 일어날 때, 이벤트 버블링을 의심해라.
    => event.stopPropagation 메서드로 막을 수 있다.

Styled-Components 사용하면,
따로 클래스명을 지정하지 않아도 된다.
하지만, 개발자 도구에서 element를 확인해보면, div class에 이상한 클래스명이 생긴다.
=> 어떤 클래스인지 알아보기 어려우니, 클래스 옆에 id를 지정해서, 표시한다. 이 과정은 좀 번거로워 보인다.

새로 알게 된 사실
z-index

Background-color: rgba(0, 0, 0, 0)
16진수보다 이렇게 쓰면 더 편하다.

Position: fixed;
=> 내가 페이지 스크롤을 올리거나 내려도, 계속 가운데에 고정된다.

left: 0; right:0; top:0; bottom:0;
=> 양옆 위 아래에 붙으라고 명령했기 때문에, 화면에 꽉 찬다.

Flex-direction: column

내 생각

인간은 어떻게 하면 더 편하게 할 수 있을까를 고민한다.
하지만, 편하다고 다 좋은 것은 아닌 것 같다는 직감이 든다.
편한 만큼 그에 상응하는 댓가가 반드시 있을 거라는 생각이 든다.

profile
pursue nature

0개의 댓글