지난 포스팅에서 pocket을 클론해 반응형 웹을 구현한 코드를 styled-components로 리팩토링 해보았다. 통번역 대학원 다닐 때도 시역(sight translation, 텍스트를 눈으로 읽어나가면서 입으로 소리내어 통역하는 훈련)했던 텍스트로 통역해보고 번역해보고, 정말 좋은 텍스트라면 암기하는 등 이것저것 여러 텍스트를 마구잡이로 다 보는 것보다 좋은 텍스트를 하나 정해서 여러 가지를 해보는 게 실력 증진에 더 큰 도움이 되었다. 부트캠프에서도 기본적으로는 매일매일 해야 할 과제가 다르지만 vanilla js로 작성한 코드를 리액트로 바꿔본다든지, react에서 state를 관리하는 방식으로 구현했던 과제를 가지고 똑같은 리액트 코드에서 state 관리만 redux를 적용해 본다든지 하는 방식으로 주어지는 과제들을 하면서 학습에 큰 도움이 되었다.
기존 코드에서는 react.module.css 방식으로 코드를 작성했는데, styled-components로 리팩토링을 해보니 css 파일을 싹 다 날려버릴 수 있었다. 과연 css-in-js 방식을 직접 써보니 하나의 컴포넌트 파일(.js)에서 html, css, js를 한번에 파악할 수 있는 게 특장점이라고 할 수 있다.
기본적으로 styled-components를 설치해준 다음, css 파일을 import 해오던 컴포넌트마다 styled-components를 불러와서 styled-components를 만들어주고 그 안에 기존 css 코드를 그대로 복사해 오면 됐다. 이번 포스팅에서는 리팩토링 과정에서 새로 알게 된 점 몇 가지만 정리해 본다.
1. css reset 코드는 어디에 써줘야 하는가?
createGlobalStyle 함수를 불러와서 전역 스타일을 설정해 줄 수 있다. 그 다음 최상위 컴포넌트에서 <GlobalStyle> 컴포넌트를 사용하면 전역에 리셋 스타일이 적용된다.
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
// css reset code here
`
function App() {
return (
<>
<GlobalStyle />
<Header />
<Main />
</>
);
}
export default App;
이때, <GlobalStyle></GlobalStyle>처럼 열고 닫는 방식으로 다른 컴포넌트들을 감싸주면 콘솔 창에 다음과 같은 경고 문구가 뜨고, 화면이 전부 하얘지면서 리액트 컴포넌트가 렌더링되지 않으니 주의해야 한다.
찾아보니 스타일 컴포넌트에서 제공하는 reset 패키지도 있다고 한다. styled-reset을 설치해서 다음과 같이 사용하면 된다고 하는데, 이번 실습에서 초기화해줄 css 코드가 많지 않아서 따로 설치해서 사용하지는 않았다.
import reset from 'styled-reset';
const GlobalStyles = createGlobalStyle`
${reset}
`
2. media query 적용
미디어 쿼리도 별 거 없다. 그냥 스타일드 컴포넌트 안에 그대로 써주면 된다.
기존 css 코드 작성을 아래와 같이 했다면,
styled-components로 리팩토링을 할 때는 다음과 같이 해주면 된다. 코드 맨 윗줄에 import로 리액트, styled-components 등을 불러와야 하는 부분은 생략했다.
미디어 쿼리로 분기를 줄 때 스타일 컴포넌트의 자식 요소에 대한 스타일을 변경해야 하는 경우는 다음과 같이 자식 선택자(>)를 써줬다. 기본적인 css와 다른 부분이 크게 없다고 보면 된다. sass처럼 &을 쓸 수 있다는 것 정도인데, 이건 꼭 미디어 쿼리 안에서만 쓸 수 있는 게 아니라 스타일 컴포넌트 안에서 어디서나 다 쓸 수 있다.
const MainContainer = styled.main`
padding: 40px;
padding-top: 64px;
margin: 0 auto;
max-width: 1128px;
@media screen and (max-width: 720px) {
& > h1 {
font-size: 1.4rem;
}
& > h2 {
font-size: 1rem;
font-weight: 500;
}
}
`;
function Main() {
return (
<MainContainer>
<h1>최고의 웹 컨텐츠 검색</h1>
<h2>오늘의 필독 자료</h2>
<Top />
<hr />
</MainContainer>
);
}
3. props로 조건부 렌더링
기존 css를 작성했을 때는 아티클 정보 중에 main 아티클인지 여부를 true, false 등 boolean 값을 갖게 해서 props로 내려받은 아티클 정보를 가지고 class 이름을 mainItem, item으로 다르게 설정해주었다.
스타일 컴포넌트에서는 이 main에 담겨있는 불리언 값을 props로 활용해서 item의 grid-rows와 grid-columns를 아래와 같이 설정해줄 수 있었다. 이때 grid-rows 값 span 2 등을 ""로 묶어주지 않으면 삼항 연산자의 :를 읽지 못하는 syntaxError가 떴다. 확실치는 않지만 추정하기로는 props로 받는 것도 일종의 변수 설정이라고 볼 수 있는데, 변수로 css 속성값을 줄 때에는 ""로 묶어서 string으로 처리해줘야 스타일 컴포넌트가 작동하는 것 같다.
4. html 엘리먼트의 속성을 styled-components에 추가하기
리팩토링 중 의외로 가장 난관을 겪었던 부분이다.
화면 구성에서 기본 컴포넌트 역할을 하는 아티클 카드 컴포넌트에서 <img> 태그의 src 값이 아티클 데이터 중에 imgUrl에 담겨 있었다. 그리고 이 이미지 태그의 스타일링을 위해 width 값 지정과 border-radius를 준 상황이었다.
import styles from "../styles/Card.module.css";
function Card({ data }) {
const { imgUrl, title, source, readtime, excerpt, main } = data;
return (
// 생략
<div className={styles.media}>
<img src={imgUrl}></img>
</div>
// 생략
);
}
// css code
.media img {
width: 100%;
border-radius: 0.8rem;
}
일단 html 태그의 속성을 스타일 컴포넌트로 가져오는 방법을 검색해보니 .attrs() 메소드로 속성을 추가해줄 수 있었다. 기본적인 syntax는 메소드의 전달인자로 html 요소의 속성을 지정해 객체로 전달해 주면 된다.
const Input = styled.input.attrs({ required: true })`
// css code here
`;
여러 속성을 한꺼번에 전달할 수도 있으며, props를 속성값으로 지정할 수도 있다.
const MediaImg = styled.img.attrs((props) => ({ src: props.imgUrl }))`
width: 100%;
border-radius: 0.8rem;
`;
function Card({ data }) {
const { imgUrl, title, source, readtime, excerpt, main } = data;
return (
//생략
<div className="media">
<MediaImg imgUrl={imgUrl}></MediaImg>
</div>
//생략
);
}
이때 객체를 화살표 함수의 리턴값으로 작성하게 되기 때문에 이렇게 attrs(props => { src: props.imgUrl }) 코드를 적으면 컴파일 에러가 난다. 그 이유에 대해서는 전에 이미 같은 유형의 에러를 만난 적이 있어서 간단하게 작성해둔 포스팅으로 갈음한다.
[2023. 2. 4. 추가]
styled-components로 정의한 컴포넌트도 그저 하나의 컴포넌트라는 사실을 간과하고 너무 어렵게 생각했다. attrs() 메소드 없이 컴포넌트에 그대로 속성을 설정해주는 편이 더 간편하다.
// attrs() 메소드 삭제
const MediaImg = styled.img`
width: 100%;
border-radius: 0.8rem;
`;
function Card({ data }) {
const { imgUrl, title, source, readtime, excerpt, main } = data;
return (
// 생략
<MediaImg src={imgUrl}></MediaImg>
);
}
📚 참고자료
styled-components attrs()에 대하여
프로젝트에서 .attrs()을 사용하는 것을 보았는데 이름에서 대충 attributes를 받아다 쓰는 건가보다 싶었다그래서 좀 더 구체적인 사용법을 알아보기로 하였다⚠ 회사에서 모르는 내용이나 미흡한
velog.io
React - Styled Components 사용 방법
React에는 여러 방법을 통해 CSS를 적용할 수 있다. 그 중에서도 개인적으로 가장 좋다고 생각되는 Styled-Components의 여러 사용 방법에 대해 알아보자.
velog.io
'배워서 남 주자' 카테고리의 다른 글
substr(), substring(), slice() 차이 (1) | 2023.01.31 |
---|---|
[React] 조건부 렌더링 (0) | 2023.01.30 |
CSS Grid Layout을 이용해 반응형 웹 디자인으로 Column Grid System 구현하기 (0) | 2023.01.20 |
for loop와 forEach 메소드의 차이 (0) | 2023.01.16 |
to do 앱 만들면서 새로 알게 된 css 몇 가지 (0) | 2023.01.10 |