Component Driven Development (CDD) : 재사용할 수 있는 컴포넌트를 먼저 생성하고, 이렇게 만들어진 컴포넌트를 결합하고, 페이지를 조립해 나가는 Bottom-up 방식 개발 방법이다.
yes! 🙌
Storybook은 Component Driven Development을 하기 위한 도구로, 여러 컴포넌트들을 각각 따로 볼 수 있게 해 주어 한 번에 하나의 컴포넌트에서 작업이 가능하게 해 준다.
- 프로젝트의 규모가 커지면서 복잡해지고, 팀원의 수도 많아지면서 CSS 작업을 효율적으로 하기 위한 CSS의 구조화가 필요해졌다. 이를 위한 해결 방법으로 CSS 전처리기(CSS Preprocessor)는 구조화된 CSS를 작성할 수 있게 도움을 주는 도구이다. CSS의 문제점들을 프로그래밍 개념(변수, 함수, 상속 등)을 활용하여 해결해 나갈 수 있다. CSS 전처리기에 맞는 Compiler를 사용해야 하고, 대표적으로 SASS가 있다. 내부에서 어떤 기능을 하는 지 모른 채 사용되며 용량이 어마하게 커지는 CSS 전처리기의 문제점을 보완하기 위해 CSS 방법론이 만들어졌다. 어플리케이션으로의 개발 방향의 진화와 컴포넌트 단위의 개발은 캡슐화의 중요성을 불러왔다. 이를 위해 CSS-in-JS는 컴포넌트 기반의 방식을 위해 만들어졌고, 대표적으로 Styled-Component가 있다.
CSS 방법론의 지향점
- 코드의 재사용
- 코드의 간결화(유지보수 용이)
- 코드의 확장성
- 코드의 예측성(클래스 명으로 의미 예측)
yes! 👍
다음과 같이 작성한다.import styled from "styled-components"; const 컴포넌트명 = styled.태그` // ...스타일 속성 `;
활용 1 : 다음과 같이 props의 여부에 따라 다르게 적용이 가능하다! (
pressed props
: props 속성 우선 적용)
활용 2 : 스타일도 상속받을 수 있다!import styled from "styled-components"; const Button = styled.button` background: ${(props) => (props.colored ? "blue" : "white")}; // 활용 1 : props 적용 color: ${(props) => (props.colored ? "white" : "blue")}; // ... `; const Red = styled(Button)` // 활용 2 : 스타일 상속 color: Red; `; export default function App() { return ( <div className="App"> <Button>기본버튼</Button> <Button>기본버튼</Button> <Button colored>props적용</Button> <Red>기본버튼상속+레드색상추가</Red> </div> ); }
결과는 아래와 같다! 한 파일에서 기능과 스타일 모두 관리할 수 있어 편하다!
useRef : Dom 엘리먼트 주소값을 활용해야 하는 경우 사용한다. 할당된 주소값은 리렌더링 되어도 바뀌지 않고, 컴포넌트의 속성만 조회 & 수정한다. useState처럼 남용해서는 안된다.
useRef를 사용하는 경우 (특정 Dom을 가리킬 때!)
- focus
- text selection
- media playback
- 에니메이션 적용
- d3.js, greensock 등 DOM 기반 라이브러리 활용
기본 사용법은 다음과 같다.
import React, { useRef } from "react"; const 주소값_그릇 = useRef(참조자료형) return ( <div> <input ref={주소값_그릇} type="text" /> // 주소값_그릇에 input DOM 엘리먼트 주소가 담김 </div> );
아래는 focus를 활용해 로그인을 만들어보자.
우선 아이디와 패스워드 인풋에 사용할 useRef를 선언해 준다.const Focus = () => { const idRef = useRef(null); const pwdRef = useRef(null);
아래 컴포넌트에서
ref={pwdRef}
이 형식으로 주소값을 담으면current 속성 객체
를 반환한다. 따라서 조건을 걸어줄 때주소값_그릇.current
이렇게 사용한다. 아래는 키를 누르고 엔터를 눌렀을 때focus()
로 다음 인풋창으로 키를 이동시켜준다.const handleInput = (event) => { if (event.key === "Enter") { if (event.target === idRef.current) pwdRef.current.focus(); else if (event.target === pwdRef.current) idRef.current.focus(); else return; } }; return ( <div> <div>로그인</div> <div> <label>아이디</label> <input ref={idRef} onKeyUp={handleInput} /> </div> <div> <label>비밀번호</label> <input ref={pwdRef} onKeyUp={handleInput} /> </div> </div> ); };
처음엔 이해가 좀 안됐는데 쓰다보니까 딱 위와 같이 활용해야할 적절한 사례가 있는 것 같다.
HTML Entities : HTML에서 특정 캐릭터들이 예약되어있기 때문에 표기의 혼란을 막기 위해서 사용한다.
다음과 같이 사용한다!<span>×</span>
Enter
를 눌렀을 때 이벤트핸들러 함수를 실행시키고 싶다면! 이벤트핸들러 함수에서 if (event.key === 'Enter') { ... }
이걸 추가하면 된다! event.key
가 사용자가 누르는 키를 받아온다!onClick={() => eventHandler(props)}
이렇게 전달해 주어야 한다! 이걸 까먹어서 계속 에러와 씨름을 했다...😫 계속 API만 하다가 오랜만에 무언가 만들려니까 머리가 쑤셨다 🤯useState
를 사용 할때, 특정 인덱스의 값을 삭제하려고 했는데 .splice
로 하려니 되지 않았다! 반환값이 삭제되는 데이터였던 걸 까먹었었다... 아 생각해보니 알고리즘 푼 지 엄청 오래 됐다. 🥲 stackoverflow
화이팅!!