[ 오늘의 TODO ]
코드 스테이츠) 월~수 내용 복습// Styled-Component// useRef패스트 캠퍼스) 인강 3개 이상 듣기 // optional생활) 물 1L 이상 마시기생활) 1시간 이상 걷기

[ 오늘의 복습 ]
오늘 복습 내용을 확실하게 숙지하려면 CSS 의 기본적인 내용과 리액트의 개발 특징을 좀 알고 있어야 했던 것 같다.
1. Styled-Component
리액트는 단방향 데이터 흐름과 함께 대표적인 특징으로 꼽는 것이 컴포넌트 단위로 개발한다는 것이다. 페이지가 모두 완성됐는데 갑자기 내비게이션 바를 수정해달라는 요청이 들어왔다. 만약에 컴포넌트 단위로 개발하지 않았다면 CSS파일 등 내비게이션 바와 얽혀 있는 모든 것을 수정해야 한다. 하지만, 컴포넌트 단위로 개발을 했다면 그 내비게이션 바를 만든 컴포넌트에서 수정을 하면 된다. 이런 방식을 CDD(Component-Driven Development)라고 부르는데 컴포넌트를 UI 조각처럼 사용해서 컴포넌트들을 조립해 웹 애플리케이션을 만들어 감을 의미한다. 그렇다면 따로 떨어져서 개발해온 CSS 파일은 어떻게 한 컴포넌트 안에 넣을 수 있을까? 이런 물음의 해답으로 Styled-Component 를 내놓을 수 있다.
1) CSS의 발전 과정
CSS 는 오랜 시간 동안 꾸준히 발전해왔다. 웹 애플리케이션과 관련된 기술이 발전하면서 프로젝트의 규모가 커지게 됐고, 당연히 CSS 도 그에 맞춰야 했다. 그러나 우리가 일반적으로 사용하는 CSS 는 많은 개발자가 개발 과정을 공유해야 하고 유지 보수해야 하는 규모가 큰 프로젝트를 진행함에 있어서 일정한 패턴이 없다는 게 큰 걸림돌이 됐다. 그렇게 CSS 작업을 효율적으로 하기 위한 구조화된 CSS가 필요하게 됐고 그에 따라서 CSS 는 여러 모습으로 바뀌었다.
CSS 전처리기
CSS 전처리기는 CSS 가 구조적으로 작성될 수 있도록 도움을 준다. CSS 는 깊이 생각하기보다 타이핑이 매우 많고 반복적인 작업이 매우 많다. 이런 문제를 해결하기 위해 프로그래밍 언어의 개념(변수, 함수, 상속 등)을 가져와서 그 문제를 해결해나가고자 했다. 그 대표적인 예시가 SASS 다.
SASS 는 가장 유명한 CSS 전처리기다. CSS를 만들어주는 언어로써 자바 스크립트 특정 속성의 값을 변수로 선언해 필요한 곳에 선언된 변수를 적용하거나 반복되는 코드를 한 번의 선언으로 여러 곳에서 재사용할 수 있도록 해주는 기능을 지녔다. 같은 코드 내용인데 약간의 변형만 있다면 for 문을 돌릴 수도 있다. SASS 는 SCSS 읽고 전처리한 다음, 컴파일해서 전역 CSS 번들 파일을 만들어준다.
문제는 전처리기 내부에서 어떤 작업을 하는지 모른다는 것이다. 그렇기에 스타일이 겹치는 문제를 해결하려고 단순히 계층 구조를 만들어야 했으며, 그 결과 컴파일된 CSS 용량은 매우 커졌다.
CSS 방법론
CSS 전처리기의 문제를 보완하기 위해 BEM, OOCSS, SMACSS 등의 CSS 방법론이 나왔다. 이런 방법론들의 공통적인 지향점은 코드의 재사용, 간결화, 확장성, 예측성이다. 일관된 방법론을 사용함으로써 협업을 하는 과정에 있어 개인차에 의한 오류와 비용을 해결할 수 있다.
대표적인 방법론은 BEM이다. Block-Element-Modifier 로 구분해서 클래스를 작성하는 방법이다. 구분할 때는 Block__Element--Modifier 로 __ 와 -- 를 사용한다.
.footer__article--aritcle-text {
// CSS 내용
}
하지만 이런 방법론에 따르면 클래스명 선택자가 장황해진다. 클래스명이 매우 길어지기에 마크업은 불명해지고 재사용할 때마다 UI 컴포넌트를 명시적으로 확장해야 했다.
특히 전처리기와 방법론의 가장 큰 문제점 중 하나는 언어 로직 상에서 진정한 의미의 캡슐화가 없단 것이다. 이로 인해 개발자들은 유일한 클래스명을 선택하는 것에 의존해야만 했다.
CSS-in-JS
CSS 를 컴포넌트의 영역으로 불러들이기 위해 CSS-in-JS 가 탄생한다. CSS-in-JS 의 대표가 Styled-Component 며, 그 외에도 Emotion, styled-jsx가 있다. 이 라이브러리들은 컴포넌트를 기반으로 CSS 를 작성할 수 있게 도와주며 CSS 를 컴포넌트 안으로 캡슐화해준다.
Styled-Component 의 장점은 다음 챕터에서 얘기할 예정이니 생략하고 단점을 꼽자면 페이지를 로드하는 데 속도가 다른 것들에 비해 느리다는 점이 있다.
2) Styled-Component 기본 개념
Styled-Component 는 React 컴포넌트 기반 개발 환경에서 CSS 를 컴포넌트 안으로 끌어들이기 위해 탄생된 라이브러리다. 기존 CSS 문법을 스타일 속성이 추가된 컴포넌트로 만들어 준다. 즉, CSS 를 하나의 컴포넌트로 만든다는 것이며 이는 기능을 구현하는 컴포넌트와 Style을 꾸미는 컴포넌트를 분리해서 사용할 수 있으며, 컴포넌트이기에 컴포넌트가 지니는 모든 장점을 지닌다.
장점
Styled-Component의 장점은 다음과 같이 정리할 수 있다.
- Automatic critical CSS
Styled-Component는 화면에 어떤 컴포넌트가 렌더링 됐는지를 추적해서 해당 컴포넌트에 스타일을 자동적으로 삽입한다. 코드를 적절히 분배하면 최소한의 코드로 화면을 띄울 수 있게 해준다. - No class name bugs
가장 큰 장점 중 하나다. Styled-Component 는 자동적으로 고유한 className 을 생성한다. 그러므로 우리가 따로 className 을 어떻게 지어줘야할 지, 이전에 그런 className 을 사용했는지 고민하지 않아도 된다. - Easier deletion of CSS
기존에 더 이상 사용하지 않거나 삭제한 컴포넌트에 해당하는 스타일 속성을 제거하려면 CSS 파일 안에서 그와 동일한 className 을 찾으려 애써야 했다. 하지만, Styled Component는 모든 스타일 속성이 특정 컴포넌트와 연결되어 있기에 컴포넌트를 더이상 사용하지 않으면 스타일 속성도 삭제된다. - Simple Dynamic Styling
React의 props나 전역 속성을 기반으로 컴포넌트에 스타일 속성을 부여할 수 있고 className 을 일일이 수동으로 관리해주지 않아도 된다. - Painless Maintenance
컴포넌트 스타일을 상속하는 속성을 찾아 다른 CSS 파일을 검색하지 않아도 되기에 코드의 크기가 커져도 유지 보수하기 쉽다. - Automatic Vendor Prefixing
개별 컴포넌트마다 기존의 CSS를 이용해 스타일 속성을 정의하면 된다. 이외의 것들은 Styled-Component가 알아서 정리한다.
설치 방법
# npm 사용시
$ npm install --save styled-components
# yarn 사용시
$ yarn ad styled-components
3) Styled-Component 사용하기
Styled-Component 는 tagged template literals 라는 문법을 사용하는데, 이 문법에 대한 자세한 개념을 파헤치기보다는 그냥 Styled-Component 의 사용 예시를 보면서 익히는 것이 좋다. 그래도 일단은 template literals 를 사용하므로 백틱 기호가 반드시 사용되고, ${} 가 사용될 수 있다는 점만 알아두자. 밑의 예시는 공식 문서에 존재하는 내용이다.
https://styled-components.com/docs/basics#getting-started
styled-components: Basics
Get Started with styled-components basics.
styled-components.com
기본
// 최상단에서 라이브러리를 사용하기 위해 import 문을 작성한다.
import styled from "styled-components";
// <h1> 태그를 렌더링 할 title component
// 주의점은 렌더링하는 함수 안에서 작성하지 않는 것이다.
// const [컴포넌트명] = styled.[태그명]`
// [CSS내용]
// `
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// <section> 태그를 렌더링 할 Wrapper component
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
export default function App() {
// rendering 되는 부분에 일반적인 컴포넌트 사용하는 것처럼 넣어주면 된다.
return (
<Box>
<Text>Hello World!</Text>
</Box>
);
}
props 내용에 따라 스타일 다르게 적용하기
전달받은 props 의 내용과 삼항연산자로 props 의 내용에 따라 스타일을 다르게 입힐 수 있다.
// Button component
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// 해석하면 backround의 내용은
// props로 전달받은 것 중 primary라는 props가 존재하는가?
// 존재하면 palevioletred, 존재하지 않으면 white
// App component
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
스타일 내용 상속받기
이전에 작성한 스타일 컴포넌트의 내용과 별 차이가 없을 경우 Styled([상속받고자 하는 컴포넌트명]) 을 통해 스타일을 상속받는다.
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
// 해석하면 TomatoButton 컴포넌트는 Button 컴포넌트의 스타일을 모두 상속받는다
// 단 백틱 안의 내용은 덮어 씌운다.
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
Passed props
컴포넌트에 props 로 스타일 속성이 전달된다면 해당 컴포넌트는 props로 전달된 속성을 우선 적용한다. 전달된 속성이 없다면 기본으로 설정된 속성을 적용한다.
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.inputColor || "palevioletred"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
// color에 대한 내용을 해석한다면
// 가져온 props 중에
// inputColor 가 존재한다면 props.inputColor 를 사용하고
// inputColor 가 존재하지 않는다면 "palevioletred" 를 사용한다
// a || b 는
// a가 truthy 한 값일 때 a를 사용하고
// a가 falsy 한 값일 때 b를 사용한다는
// 단축 평가 논리 계산법이다(자세한 내용은 패캠 인강 카테고리에 올려놨다)
render(
<div>
<Input defaultValue="@probablyup" type="text" />
<Input defaultValue="@geelen" type="text" inputColor="rebeccapurple" />
</div>
);
2. useRef
React 내용은 대부분의 프론트 엔드 요구 사항을 구현할 수 있지만 직접적인 DOM 조작을 금지하고 있다. 이런 by designed 내용으로 인해 다음과 같은 기능을 구현하기 어렵다
- focus
- text selection
- media playback
- 애니메이션
- d3.js, greensock 등 DOM 기반 라이브러리 활용
그러나 위의 예시에서 볼 수 있든 프론트엔드 개발은 필연적으로 DOM 을 조작해야 하는 경우가 반드시 생기게 된다. 그럴 때 사용하는 Hook 이 useRef 다.
1) 기본 사용법
const [주소값을 담을 변수] = useRef(참조자료형)
// 주소 값을 담을 변수에는 어느 컴포넌트의 주소값이든 다 받을 수 있다
// 기본적으로 return 문까지 렌더링이 다 끝난 후에 변수에 주소값이 할당된다.
// 그렇기에 어떤 경우 useRef 인자로 넣은 참조자료형은 초기에 null 로 넣는 경우가 있다.
return (
<div>
<input ref={주소값을 담을 변수} type="text" />
{/* React에서 사용 가능한 ref라는 속성에 주소값을 담을 변수에 값으로 할당하면*/}
{/* 주소값을 담을 변수에는 input DOM 엘리먼트의 주소가 담긴다. */}
{/* 향후 다른 컴포넌트에서 이 변수를 통해서 input 주소값을 활용할 수 있게 된다. */}
</div>
);
useRef 는 리렌더링 되더라도 바뀌지 않는다.
'코드스테이츠 > 코드스테이츠 @ 개발 복습' 카테고리의 다른 글
[코드 스테이츠] 83일차, "12주차 복습 (1)" (0) | 2021.10.09 |
---|---|
[코드 스테이츠] 63일차, "9주차 복습 (2) - Redux" (0) | 2021.09.19 |
[코드 스테이츠] 56일차, "8주차 복습(2) - CORS, 미들웨어" (0) | 2021.09.12 |
[코드 스테이츠] 55일차, 8주차 복습(1) - React 데이터 흐름, Effect Hook" (0) | 2021.09.11 |
[코드 스테이츠] 49일차, "7주차 복습 (2) - 2티어 아키텍처, 프로토콜, HTTP, 브라우저 작동원리" (0) | 2021.09.05 |