WINK-(Web & App)/React.js 스터디

[2025 1학기 React.js 스터디] 이종민 #5주차

jm031203 2025. 5. 29. 00:33
반응형

단단한 돌머리로 리엑트를 부숴보겠습니다 화이팅 !

sass

sass 란 ? : CSS pre-processor 로서, 복잡한 작업을 쉽게 할 수 있게 해주고, 코드의 재활용성을 높여줄 뿐 만 아니라, 코드의 가독성을 높여주어 유지보수를 쉽게해줍니다.

우선 디렉터리를 하나 만든 후 그 안에 Button.js와 Button.scss를 만들어 주었습니다. 기존 css 에서는 사용하지 못하던 문법들이 있습니다. $blue: #228be6; 이런 식으로 스타일 파일에서 사용 할 수 있는 변수를 선언 할 수도 있고 lighten() 또는 darken() 과 같이 색상을 더 밝게하거나 어둡게 해주는 함수도 사용 할 수 있는걸 알 수 있습니다 !

 

App.js를 수정해주고 App.css의 파일명을 App.scss로 바꾼 뒤 수정해줬습니다

와우 ~! 버튼이 생기고 색이 설정됐습니다 !

 

이제 버튼의 사이즈를 조정해보겠습니다. 우선 버튼 크기에 large, medium, small 를 설정해줄 수 있도록 구현을 해보겠습니다.

className={['Button', size].join(' ')}
className={`Button ${size}`}

className 에 CSS 클래스 이름을 동적으로 넣어주고 싶으면 이렇게 두가지 방법으로 설정할 수 있습니다. 하지만, 조건부로 CSS 클래스를 넣어주고 싶을때 이렇게 문자열을 직접 조합해주는 것 보다 classnames 라이브러리를 사용하는 것이 훨씬 편합니다.

우선 Button.js에

import classNames from 'classnames';

를 추가합니다.

위 코드에서

.Button {
  &.large {

  }
}

가 의미 하는 것은

.Button.large {

}

입니다. 결국, Button  large CSS 클래스가 함께 적용되어 있으면 우리가 원하는 스타일을 적용하겠다는 것을 의미합니다.

<Button size="large">BUTTON</Button>
<Button>BUTTON</Button>
<Button size="small">BUTTON</Button>

App.js에 large 버튼과 small 버튼을 추가한 후 출력해봅니다

와우 ~! large button, medium button, small button이 차례대로 출력됐습니다 ~!

이제 Button.scss 아래처럼 추가해줍니다.

& + & {
    margin-left: 1rem;
  }

여기서 &는 .Button을 의미합니다. 이렇게 하면 버튼 사이에 여백을 만들어줄 수 있습니다.

와우 ~! 버튼들 사이에 여백이 생긴것을 알 수 있습니다 ~!

이제 버튼의 색상을 설정해보겠습니다. 색상에 blue, gray, pink 색을 설정 할 수 있도록 구현해보겠습니다. 우선 Button.js에 

color를 추가합니다. 이번에는 Button.scss를 수정해줍니다. 

$gray: #495057;
$pink: #f06595;

blue와 같이 gray와 pink도 추가해줍니다. 그 후 하단에  CSS 클래스에 따라 다른 색상이 적용되도록 코드를 작성해줍니다.

이렇게 반복이 되는 코드는 Sass 의 mixin 이라는 기능을 사용하여 쉽게 재사용 할 수 있습니다. 한번, button-color라는 mixin 을 만들어서 사용해보겠습니다.

왼쪽 mixin 을 추가 후 오른쪽처럼 아래를 수정하면 더욱 코드가 깔끔해집니다.

gray button 과 pink button을 App.js에 추가 후 결과를 확인해보겠습니다.

주의사항 : Button.js에서 defaultProps가 적용이 안됨으로 밑에 사진처럼 함수에 직접 넣어줍니다.

margin-top: 1rem을 추가해주므로 버튼들 간의 간격도 띄워 줬습니다.

와우 ~! 버튼간의 상하 간격이 생기고 파랑, 회색, 핑크가 생겼습니다 !

이번에는 outline 옵션을 만들겠습니다. 

여기서는 outline 값을 props 로 받아와서 객체 안에 집어 넣은 다음에 classNames() 에 포함시켜줬는데요, 이렇게 하면 outline 값이 true 일 때에만 button  outline CSS 클래스가 적용됩니다.

mixin을 사용하여 outline을 쉽게 추가할 수 있습니다 !

App.js에 outline 버튼을 추가하고 확인해보면 ~?

와우 ~! 버튼이 추가되었습니다 ~! (맨 오른쪽 버튼은 커서를 올려두면 색이 바뀌는 모습입니다 ~~!!)

이번에는 fulwidth라는 옵션을 추가하여 버튼이 전체 너비를 차지하도록 구현을 해보겠습니다.

우선 Button.js의 함수에 fullwidth를 추가해줍니다. 그 후 Button.scss를 수정해줍니다.

마진을 0으로 해주고 width를 100으로 해주었습니다

마지막으로 버튼을 App.js에 추가해주면 ~?

와우 ~! 꽉찬 버튼이 생겼습니다 !

버튼을 모두 만들었으니 onClick과 onMouseMove를 설정해보겠습니다.

필요한 이벤트가 있을 때 마다 매번 이렇게 넣어주는건 귀찮습니다. 이러한 문제를 해결 해줄 수 있는 문법이 있는데요! 바로 spread와 rest 입니다. 이 문법은 주로 배열과 객체, 함수의 파라미터, 인자를 다룰 때 사용하는데, 컴포넌트에서도 사용 할 수 있답니다.

이렇게 ...rest를 사용해서 우리가 지정한 props 를 제외한 값들을 rest 라는 객체에 모아주고, <button> 태그에 {...rest} 를 해주면, rest 안에 있는 객체안에 있는 값들을 모두 <button> 태그에 설정을 해준답니다.

onClick이 호출되는것을 볼 수 있습니다 ! 컴포넌트가 어떤 props 를 받을 지 확실치는 않지만 그대로 다른 컴포넌트 또는 HTML 태그에 전달을 해주어야 하는 상황에는 이렇게 ...rest 문법을 활용하면 됩니다.

 

CSS Module

리액트 프로젝트에서 컴포넌트를 스타일링 할 때 CSS Module 이라는 기술을 사용하면, CSS 클래스가 중첩되는 것을 완벽히 방지할 수 있습니다. CRA 로 만든 프로젝트에서 CSS Module 를 사용 할 때에는, CSS 파일의 확장자를 .module.css 로 하면 됩니다.

좌 : Box.module.css 우 : Box.js

리액트 컴포넌트 파일에서 해당 CSS 파일을 불러올 때 CSS 파일에 선언한 클래스 이름들이 모두 고유해집니다. 고유 CSS 클래스 이름이 만들어지는 과정에서는 파일 경로, 파일 이름, 클래스 이름, 해쉬값 등이 사용 될 수 있습니다. className 을 설정 할 때에는 styles.Box 이렇게 import로 불러온 styles 객체 안에 있는 값을 참조해야 합니다.

리액트 컴포넌트를 위한 클래스를 작성 할 때 제가 자주 사용하는 CSS 클래스 네이밍 규칙은 다음과 같습니다.

  • 컴포넌트의 이름은 다른 컴포넌트랑 중복되지 않게 한다.
  • 컴포넌트의 최상단 CSS 클래스는 컴포넌트의 이름과 일치시킨다.
  • 컴포넌트 내부에서 보여지는 CSS 클래스는 CSS Selector 를 잘 활용한다.

지금 당장은, 스타일링도 하지 않고, 체크 아이콘도 사용하지 않고 그냥 이 컴포넌트에 필요한 HTML 태그들만 미리 선언을 해주었습니다.

...rest 를 사용한 이유는, CheckBox 컴포넌트에게 전달하게 될 name, onChange 같은 값을 그대로 input 에게 넣어주기 위함입니다.

지금 input 이 아닌 텍스트 부분을 선택했는데도 값이 바뀌는 이유는 현재 우리가 해당 내용을 label 태그로 감싸줬기 때문입니다.

이제 스타일링을 해보겠습니다. react-icons라는 라이브러리를 설치 후 하겠습니다. 이 라이브러리를 사용하면 Font Awesome, Ionicons, Material Design Icons, 등의 아이콘들을 컴포넌트 형태로 쉽게 사용 할 수 있습니다.

$ yarn add react-icons

CheckBox.js 를 react-icons에서 MdCheckBox, MdCheckBoxOutline를 사용하여 수정해주었습니다. 이렇게 수정을 해주면, 텍스트 대신 아이콘이 나타나게 됩니다. 이제 CheckBox.module.css 파일을 components 디렉터리에 생성해주겠습니다.

CSS Module 을 작성 할 때에는 CSS 클래스 이름이 다른 곳에서 사용되는 CSS 클래스 이름과 중복될 일이 없기 때문에 .icon, .checkbox 같은 짧고 흔한 이름을 사용해도 상관이 없습니다.

체크박스의 스타일링도 된것을 확인할 수 있습니다. CSS Module 을 사용 할 때에는 styles.icon 이런 식으로 객체안에 있는 값을 조회해야 하는데요, 만약 클래스 이름에 - 가 들어가 있다면 다음과 같이 사용해야합니다: styles['my-class']

그리고, 만약에 여러개가 있다면 다음과 같이 작성해합니다: ${styles.one} ${styles.two}

 

classnames 라이브러리에는 bind 기능이 있는데, 이 기능을 사용하면 CSS Module 을 조금 더 편하게 사용 할 수 있습니다.

classnames 의 bind 기능을 사용하면, CSS 클래시 이름을 지정해 줄 때 cx('클래스이름') 과 같은 형식으로 편하게 사용 할 수 있습니다.

 CSS Module 은 Sass 에서도 사용 할 수 있습니다. 그냥 확장자를 .module.scss 로 바꿔주면 됩니다. 그리고, CSS Module 을 사용하고 있는 파일에서 클래스 이름을 고유화 하지 않고 전역적 클래스이름을 사용하고 싶다면 다음과 작성하면 됩니다.

:global .my-global-name {

}

만약 Sass 를 사용한다면 다음과 같이 할 수도 있습니다.

:local {
  .make-this-local {

  }
}

 

styled-components

CSS in JS : 이 문구가 뜻하는 그대로, 이 기술은 JS 안에 CSS 를 작성하는 것을 의미합니다.

이 기술을 사용하는 라이브러리인 styled-components 를 다뤄보겠습니다. styled-components 를 사용하기 전에, Tagged Template Literal 이라는 문법에 대하여 짚고 넘어가면, styled-components 가 내부적으로 어떻게 작동하는지 이해 할 수 있습니다.

const name = 'react';
const message = `hello ${name}`;

console.log(message);
// "hello react"

문자열 조합을 더욱 쉽게 할 수 있게 해주는 ES6 문법입니다

const object = { a: 1 };
const text = `${object}`
console.log(text);
// "[object Object]"

 Template Literal 을 사용 할 때 ${} 안에 일반 문자열 / 숫자가 아닌 객체를 넣는다면 ?

const fn = () => true
const msg = `${fn}`;
console.log(msg);
// "() => true"

아니면, 만약에 함수를 넣는다면 ? 만약에, 우리가 Template Literal 을 사용하면서도, 그 내부에 넣은 자바스크립트 값을 조회하고 싶을 땐 Tagged Template Literal 문법을 사용 할 수 있습니다. Tagged Template Literal 을 사용하면 만약 ${} 을 통하여 함수를 넣어줬다면, 해당 함수를 사용해줄 수도 있답니다.

function sample(texts, ...fns) {
  const mockProps = {
    title: '안녕하세요',
    body: '내용은 내용내용 입니다.'
  };
  return texts.reduce((result, text, i) => `${result}${text}${fns[i] ? fns[i](mockProps) : ''}`, '');
}
sample`
  제목: ${props => props.title}
  내용: ${props => props.body}

 

이제 본격적으로 styled-components 를 본격적으로 사용해보겠습니다.

styled-components 를 사용하면 이렇게 스타일을 입력함과 동시에 해당 스타일을 가진 컴포넌트를 만들 수 있습니다. 만약에 div 를 스타일링 하고 싶으면 styled.div, input 을 스타일링 하고 싶으면 styled.input 이런식으로 사용하면 됩니다.

이번에는, Circle 컴포넌트에 color 라는 props 를 넣어줘보겠습니다. Circle 컴포넌트에서는 color props 값을 설정해줬으면 해당 값을 배경색으로 설정하고, 그렇지 않으면 검정색을 배경색으로 사용하도록 설정되었습니다.

이번에는 huge라는 props 를 설정됐을 때 크기를 더 키워서 보여주도록 했습니다. 이런식으로 여러 줄의 CSS 코드를 조건부로 보여주고 싶다면 css 를 사용해야합니다., css 를 불러와서 사용을 해야 그 스타일 내부에서도 다른 props 를 조회 할 수 있습니다.

 

이번에는 위에서 sass로 했던  Button 컴포넌트를 styled-components 로 구현을 해보겠습니다. 우선 src 안에 components 디렉터리를 생성 후, 그 안에 Button.js 파일을 만들어줬습니다.

기본적인 버튼을 만들어 주었습니다. Sass 를 사용 할 때에는 lighten() 또는 darken() 과 같은 유틸 함수를 사용하여 색상에 변화를 줄 수 있었는데요, CSS in JS 에서도 비슷한 유틸 함수를 사용하고 싶다면polished  라는 라이브러리를 사용하면 됩니다.

버튼이 생겼습니다 ! 

반응형