Framework/React ์™„๋ฒฝ ๊ฐ€์ด๋“œ

[React ์™„๋ฒฝ ๊ฐ€์ด๋“œ] section 6 : ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ๋ง

yuri lee 2022. 9. 19. 23:37
๋ฐ˜์‘ํ˜•
์ด ๊ธ€์€ udemy์˜ React ์™„๋ฒฝ ๊ฐ€์ด๋“œ with Redux, Next.js, TypeScript ๊ฐ•์ขŒ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

82. ๋ชจ๋“ˆ ์†Œ๊ฐœ

  • Conditional & Dynamic Styles
  • Styled Components
  • CSS Modules

error

error:03000086:digital envelope routines::initialization error
  • ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋ฐ›์•„ ์‹คํ–‰ํ•˜์ž ๋‹ค์Œ์˜ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ๋…ธ๋“œ 17๊ด€๋ จ ์—๋Ÿฌ๋กœ nvm ์„ ์‚ฌ์šฉํ•˜์—ฌ node ๋ฒ„์ „์„ ๋‚ฎ์ถฐ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋‹ˆ ์ •์ƒ ์ž‘๋™๋˜์—ˆ๋‹ค. 

83. ๋™์  ์ธ๋ผ์ธ ์Šคํƒ€์ผ ์„ค์ •ํ•˜๊ธฐ

  • input ์ฐฝ์— ์ž…๋ ฅ ์—†์ด Add Goal์„ ๋ˆŒ๋ €์„ ๋•Œ color๋ฅผ ๋™์ ์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋„๋ก ํ•œ๋‹ค. 
    <div className="form-control">
        <label style={{ color: !isValid ? "red" : "black" }}>Course Goal</label>
        <input
          style={{
            borderColor: !isValid ? "red" : "black",
            background: !isValid ? "salmon" : "transparent",
          }}
          type="text"
          onChange={goalInputChangeHandler}
        />
      </div>

  • ํ•˜์ง€๋งŒ inline ์Šคํƒ€์ผ์€ css์— ์ตœ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋‘๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  style์„ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ํ•ด๋‹น ๋ฐฉ๋ฒ•์„ ์„ ํ˜ธํ•˜์ง„ ์•Š๋Š”๋‹ค. (๊ทธ๋™์•ˆ ์ œ๋Œ€๋กœ style ์•ˆ๋จน์œผ๋ฉด..๋ฌด์กฐ๊ฑด inline styling ์ ์šฉํ–ˆ์—ˆ๋Š”๋ฐ, ์‚ผ๊ฐ€ํ•ด์•ผ ๋˜๊ฒ ๋‹ค....๐Ÿ™ƒ ) 

84. ๋™์ ์œผ๋กœ CSS ํด๋ž˜์Šค ์„ค์ •ํ•˜๊ธฐ 

  • backticks (๋ฐฑํ‹ฑ) ์‚ฌ์šฉํ•˜๊ธฐ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์œผ๋กœ ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฐ๋‹ค. 
  • ์œ„ ๊ฐ„๋‹จํ•œ ๊ตฌ๋ฌธ์œผ๋กœ ๋™์ ์ธ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. 
.form-control.invalid input {
  border-color: red;
  background: rgb(255, 202, 202)
}

.form-control.invlid label {
  color: red;
}
    <form onSubmit={formSubmitHandler}>
      <div className={`form-control ${!isValid ? "invalid" : ""}`}>
        <label style={{ color: !isValid ? "red" : "black" }}>Course Goal</label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>

85. Styled Components ์†Œ๊ฐœ

  • ํŠน์ • ์Šคํƒ€์ผ์ด ์ฒจ๋ถ€๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ํŒจํ‚ค์ง€์ด๋‹ค. 
  • https://styled-components.com/
  • Actually, styled package has methods for all HTML elements. It has p method for a paragraph h1, h2, and so on for the h1, h2 tags, div to create a div and so on.
const Button = props => {
  return (
    <button type={props.type} className="button" onClick={props.onClick}>
      {props.children}
    </button>
  );
};

export default Button;
import styled from "styled-components";

const Button = styled.button`
  font: inherit;
  padding: 0.5rem 1.5rem;
  border: 1px solid #8b005d;
  color: white;
  background: #8b005d;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;

  &:focus {
    outline: none;
  }
  &:hover,
  &:active {
    background: #ac0e77;
    border-color: #ac0e77;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
  }
`;

export default Button;

→ button tag์— ์ ์šฉ๋œ ์ด์ƒํ•œ class 2๊ฐœ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ๊ฐ€ ์„ค์ •ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ styled-components ํŒจํ‚ค์ง€์— ์˜ํ•ด ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ž˜์Šค ์ด๋ฆ„์ด๋‹ค. ์ด ํŒจํ‚ค์ง€๋Š” ๊ฒฐ๊ตญ ์šฐ๋ฆฌ๊ฐ€ ์„ค์ •ํ•œ style์„ ๋ณด๊ณ  ์ƒ์„ฑ๋œ ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ ์ด ์Šคํƒ€์ผ์„ ๊ฐ์‹ธ๋Š”๋ฐ ๋ชจ๋“  ํด๋ž˜์Šค๋Š” ๊ณ ์œ ํ•œ ์ด๋ฆ„์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์— ์žˆ๋Š” ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ด class๋ฅผ ์ „์—ญ css๋กœ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์ด๋‹ค. 

ํ•˜์ง€๋งŒ ๋ชจ๋“  styled components๋งˆ๋‹ค ๊ณ ์œ ํ•œ class name์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ ์„ค์ •ํ•œ style์€ app ๋‚ด์˜ ๋‹ค๋ฅธ component์—๋Š” ์ ˆ๋Œ€ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. unique class name ์€ styled componet ๋ณ„๋กœ ๊ณ ์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ ๐Ÿ‘  ์ด๊ฒŒ ๋ฐ”๋กœ styled-component ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 

86. Styled Components & ๋™์  Props

    border: 1px solid ${(props) => (props.invalid ? "red" : "#ccc")};
    background: ${(props) => (props.invalid ? "red" : "#ccc")}

→ ; ํ•˜๋‚˜ ์ฐจ์ด๋กœ ์ ์šฉ์ด ๋˜์—ˆ๋‹ค๊ฐ€ ์•ˆ๋˜์—ˆ๋‹ค๊ฐ€ ํ•˜๋„ค...?!

87.  Styled Components & ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ 

  • ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 
const Button = styled.button`
  width: 100%;
  font: inherit;
  padding: 0.5rem 1.5rem;
  border: 1px solid #8b005d;
  color: white;
  background: #8b005d;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;
  @media (min-width: 768px) {
    width: auto;
  }
  &:focus {
    outline: none;
  }
  &:hover,
  &:active {
    background: #ac0e77;
    border-color: #ac0e77;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
  }
`;

export default Button;

88. CSS ๋ชจ๋“ˆ ์‚ฌ์šฉํ•˜๊ธฐ

  • https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
  • st yled ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ข‹์•„ํ•˜๊ฑด, ๊ทธ๋ ‡์ง€ ์•Š๊ฑด ๊ทธ๊ฒƒ์€ ์™„์ „ํžˆ ๊ฐœ์ธ์ ์ธ ์ทจํ–ฅ์ด๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ ํ•„์ž๋Š” css๋Š” css ํŒŒ์ผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•œ๋‹ค. (css ํŒŒ์ผ๊ณผ js ๋ถ„๋ฆฌ)
  • css ๋ชจ๋“ˆ์€ ์ด ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋„๋ก ์„ค์ •๋œ ํ”„๋กœ์ ํŠธ์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. why? ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์ฝ”๋“œ์˜ ๋ณ€ํ™˜์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‹คํ–‰ํžˆ ๋ฆฌ์•กํŠธ์•ฑ์œผ๋กœ ์ƒ์„ฑํ•œ project๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ css module์„ ์ง€์›ํ•˜๋„๋ก ์„ค์ •๋˜์–ด ์žˆ๋‹ค. 
  • *.module.css : ๊ธฐ๋ณธ์ ์œผ๋กœ css ๋ชจ๋“ˆ์ด ์ž‘๋™ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋ผ๊ณ  ์ปดํŒŒ์ผ ํ”„๋กœ์„ธ์Šค์—๊ฒŒ ๋ณด๋‚ด๋Š” ์‹ ํ˜ธ์ด๋‹ค. 
import styles from "./Button.module.css";

const Button = (props) => {
  return (
    <button type={props.type} className={styles.button} onClick={props.onClick}>
      {props.children}
    </button>
  );
};

export default Button;

→ ์ปดํฌ๋Š”ํ„ฐ์ด๋ฆ„_ํด๋ž˜์Šค ์ด๋ฆ„_๊ณ ์œ ํ•œ ํ•ด์‹œ๊ฐ’ ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. css module ๋‚ด๋ถ€ ํ”„๋กœ์„ธ์Šค๋Š” css ํด๋ž˜์Šค๋‚˜ css ํŒŒ์ผ์„ ํ†ตํ•ด ๊ทธ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ ๊ณ ์œ ํ•˜๊ฒŒ ๋ฐ”๊พผ๋‹ค. ์ด๊ฒŒ ๋ฐ”๋กœ ํ•ต์‹ฌ ์ž‘์—…!

 importํ•˜๋Š” ๋ชจ๋“  css ํŒŒ์ผ์„ ๊ณ ์œ ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค. 

๋ Œ๋”๋ง๋œ DOM์—์„œ <head> ๋ถ€๋ถ„์„ ํ™•์žฅํ•ด ๋ณด๋ฉด  ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง„ ํด๋ž˜์Šค๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

→ css module์€ cssํŒŒ์ผ์—์„œ ์„ค์ •ํ•œ css style์˜ ๋ฒ”์œ„๊ฐ€ ์ด file์— import ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์— ํ•œ์ •๋œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์‹คํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. 

→ ๊ฐœ๋ฐœ์ž์ธ ์šฐ๋ฆฌ๊ฐ€ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜๋Š” ์—†์ง€๋งŒ ๋™์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ํด๋ž˜์Šค name๊ณผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•! 

89.  CSS ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ ๋™์  ์Šคํƒ€์ผ

<div className={styles["form-control"]}></div>
  <div className={`${styles["form-control"]} ${!isValid && styles.invalid}`}></div>

 

์ •๋ฆฌ

1. css ๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ

2. styled ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ

3. css module ์‚ฌ์šฉ

 

๊ฐ์ž ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

 

90.  ๋ชจ๋“ˆ ๋ฆฌ์†Œ์Šค

  • ๊ฐ•์˜ ์ฐธ๊ณ  

 


https://www.udemy.com/course/best-react/

๋ฐ˜์‘ํ˜•