๐Ÿ‘จโ€๐Ÿ’ป ํ›ˆ๋ จ์ž์˜ ๊ด€์ ์—์„œ ๋ฐ˜์‘ | 5๋ถ€๋ถ„-๐ŸŽจ ์กฐํ˜•๋ฒ•

6042 ๋‹จ์–ด reactcodenewbiecss
React์˜ ์Šคํƒ€์ผ์€ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ด๊ฒƒ์€ ๊ฒฐ์ฝ” ์–ด๋ ต์ง€ ์•Š์ง€๋งŒ, ๋งŽ์€ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ๋‹ค.์ •์  ์›น ํŽ˜์ด์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚˜์—๊ฒŒ ๋‚ด์—ฐ ์–‘์‹์ด ํ™˜์˜์„ ๋ฐ›์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ฐ€๋ฅด์ณ ์ฃผ์—ˆ๋‹ค.๋น ๋ฅธ style.css ํŒŒ์ผ ํ›„์— ๋‚˜๋Š” ๊ณ„์† ์ „์ง„ํ–ˆ๋‹ค.React๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋‹น์‹ ์˜ ๋‹จ์ผ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ (SPA) ์„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ทธ๊ฒƒ์„ ๋ถ„ํ•ดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ–Œ๏ธ ์Šคํƒ€์ผ ๊ฐœ์š”๐Ÿ–Œ๏ธ



React์—์„œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์Šคํƒ€์ผ์„ ์„ค์ •ํ•˜๋Š” ๋‹ค์„ฏ ๊ฐ€์ง€ (ish) ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์Šคํƒ€์ผ์‹œํŠธ-a์˜ ๊ณ ์ „ ์Šคํƒ€์ผ์‹œํŠธ.css.scss ๋“ฑ ํ˜•์‹
  • CSS ๋ชจ๋“ˆ - ์ œํ•œ๋œ ๋ฒ”์œ„์˜ ๊ฐœ๋ณ„ ์Šคํƒ€์ผ์‹œํŠธ
  • CSS ํ”„๋ ˆ์ž„์›Œํฌ - ์ง๋ ฌ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค/๊ตฌ์„ฑ ์š”์†Œ
  • JSS-JavaScript ์Šคํƒ€์ผ
  • ์Šคํƒ€์ผ๋ง ์–ด์…ˆ๋ธ”๋ฆฌ - JS์˜ CSS
  • ์Šคํƒ€์ผ ์‹œํŠธ


    ์ง€๊ธˆ ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์…จ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.CodePen์—์„œ๋Š” ๋ชจ๋“  ํŽœ์— ์Šคํƒ€์ผ์‹œํŠธ๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.react์—์„œ, ์Šคํƒ€์ผ์‹œํŠธ๋Š” ๋ณดํ†ต ๊ตฌ์„ฑ ์š”์†Œ๋‚˜ ํŽ˜์ด์ง€์™€ ๊ฐ™์€ ํด๋”์— ๋†“์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค.์˜ˆ:
    Project
    |
    +-- src
    | |
    | +-- components
    |   |
    |   +-- Nav
    |     |
    |     +-- index.jsx
    |         style.css
    
    
    ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ ์˜ˆ์‹œ์˜nav๋Š” style.css ๊ฐ€์ ธ์˜ค๊ธฐ import './style.css' ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.์ด๋Ÿฐ ๋ฐฉ๋ฒ•์€ ์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๊ณ ์ „์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ—ˆ๋ฝํ•œ๋‹ค.์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    body {
      margin: 0;
    }
    
    .nav-button {
      color: blue;
    }
    
    ์Šคํƒ€์ผ์‹œํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €์— ์ตœ์ ํ™”๋˜๊ธฐ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๋‹ค์‹œ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ, ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

    CSS ๋ชจ๋“ˆ


    CSS ๋ชจ๋“ˆ์€ ๊ฐ™์€ ์œ„์น˜์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ€์ผ์‹œํŠธ์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค(์œ„์˜ ํŒŒ์ผ ๊ตฌ์กฐ ์ฐธ์กฐ).๊ทธ๊ฒƒ๋“ค์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ณ  ๋กœ์ปฌ์—์„œ ๋ฒ”์œ„๋ฅผ ์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐ ๋”์šฑ ์ข‹๋‹ค.์Šคํƒ€์ผ์‹œํŠธ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ๋ช…๋ช…๋ฉ๋‹ˆ๋‹ค.์˜ˆ: module.style.css.๊ทธ๊ฒƒ๋“ค์€ index.jsx์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ž…ํ•œ๋‹ค: import styles from './module.style.css'.
    ์Šคํƒ€์ผ์‹œํŠธ์—์„œ ๋งŒ๋“  styles ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋‹ค์Œ ์˜ˆ๋Š” ๊ทธ๋“ค์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ค‘์ ์ ์œผ๋กœ ์†Œ๊ฐœํ–ˆ๋‹ค.
    import React from 'react';
    import styles from './module.style.css';
    
    const Nav = () => (
      <nav className={styles.navbar}>
        <span className={styles.link}>Home</span>
      </nav>
    );
    
    export default Nav;
    
    ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“ˆ์—์„œ ๋งŒ๋“  ๋ชจ๋“  ์ข…๋ฅ˜๋Š” ์  ๊ธฐํ˜ธ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.๊ทธ๊ฒƒ๋“ค์€ ๋งค์šฐ ์œ ์ตํ•˜๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์Šคํƒ€์ผ์˜ ์—ญํ•  ์˜์—ญ (๋กœ์ปฌ) ์€ ๋” ์ด์ƒ ์Šคํƒ€์ผ ์ถฉ๋Œ์ด ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. CSS๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์— ๋…ธ์ถœ๋˜๊ณ  ๋‹ค์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.๋ฐ˜๋Œ€๋กœ ์ „์—ญ CSS์™€ ํ˜ผํ•ฉํ•˜๊ธฐ ์–ด๋ ค์›Œ์„œlowerCamelCase๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ  ์›นํŒฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    CSS ํ”„๋ ˆ์ž„์›Œํฌ



    ๋งŽ์€ CSS ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋ชจ๋“  ๊ฒƒ์€ ๋ฌธ์„œ์™€ ๋ชจ๋‘๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” ํŠน์„ฑ์ด ์žˆ๋‹ค.์˜ˆ๋ฅผ ๋“ค์–ด ๋ชจ๋‘๊ฐ€ ์•Œ๋‹ค์‹œํ”ผ ์•ˆ๋‚ด๋Š” ์ธํ„ฐ๋„ท์—์„œ ์›น ๊ฐœ๋ฐœ์ž์˜ ์š”๊ตฌ ์‚ฌํ•ญ(๊ฒ€์ƒ‰ ์•ˆ๋‚ด memes)์ด๋‹ค.๊ทธ๊ฒƒ๋“ค์€ ๋งค์šฐ ๋งŽ๋‹ค.๋‚ด๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” CSS ํ”„๋ ˆ์ž„์›Œํฌ๋Š” Bulma, Semantic, materialui์ด๋‹ค.ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž์™€ ํ•จ๊ป˜ ์„ค์น˜ํ•˜๊ณ  ์ „์—ญ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ํ•„์š”์— ๋”ฐ๋ผ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
    import React from 'react';
    import {
      Button,
      Container
    } from 'react-bulma-components/full';
    
    const Nav = () => (
      <Container>
        <Button color='danger' size='large' rounded outlined>Home</Button>
      </Container>
    );
    
    export default Nav;
    
    ์œ„์˜ ์˜ˆ์—์„œ๋Š” CSS ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•˜๋‚˜์˜ ์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ด๊ฒƒ์€ ๋ฏธ๋ฆฌ ์„ค๊ณ„๋˜์—ˆ์ง€๋งŒ, ์ˆ˜์‹์ž ์ข…๋ฅ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ํ…Œ๋งˆ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์„œ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์šฐ๋ฆฌ๋Š” ๋‹จ์ถ” ๊ตฌ์„ฑ ์š”์†Œ์— ์›ํ˜•, ํฐ, ๋นจ๊ฐ„์ƒ‰, ์œค๊ณฝ์„ ์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.
    CSS ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ์ฐฝ์„คํ•  ๋•Œ ์ ‘๊ทผ์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์‹คํ˜„ํ•˜๊ธฐ ์‰ฝ๋‹ค.๊ทธ๊ฒƒ๋“ค์€ ํšจ๊ณผ์ ์œผ๋กœ ์ตœ์ ํ™”ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜๋„ ์žˆ๊ณ , ๋ณด๊ธฐ์— ์‹ ์„ ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๊ณ , ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

    JSS ํšŒ์‚ฌ


    ์Šคํƒ€์ผ๋ง ์–ด์…ˆ๋ธ”๋ฆฌ์™€ ์œ ์‚ฌํ•˜๊ฒŒ JSS๋Š” JS/JSX ํŒŒ์ผ์—์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.๊ทธ๊ฒƒ๋“ค์€ ์šฐ๋ฆฌ๊ฐ€ ์†Œ๊ฐœํ•œ ๋‹ค๋ฅธ ๊ฐœ๋…๋ณด๋‹ค ์•ฝ๊ฐ„ ์„ ์ง„์ ์ด์ง€๋งŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” JSS๊ฐ€ React์—์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค(์˜ˆ: JSS foundhere์˜ ํ™ˆ ํŽ˜์ด์ง€์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค).
    import React from 'react'
    import {render} from 'react-dom'
    import {createUseStyles} from 'react-jss'
    
    // Create your Styles. Remember, since React-JSS uses the default preset,
    // most plugins are available without further configuration needed.
    const useStyles = createUseStyles({
      myButton: {
        color: 'green',
        margin: {
          // jss-plugin-expand gives more readable syntax
          top: 5, // jss-plugin-default-unit makes this 5px
          right: 0,
          bottom: 0,
          left: '1rem'
        },
        '& span': {
          // jss-plugin-nested applies this to a child span
          fontWeight: 'bold' // jss-plugin-camel-case turns this into 'font-weight'
        }
      },
      myLabel: {
        fontStyle: 'italic'
      }
    })
    
    // Define the component using these styles and pass it the 'classes' prop.
    // Use this to assign scoped class names.
    const Button = ({children}) => {
      const classes = useStyles()
      return (
        <button className={classes.myButton}>
          <span className={classes.myLabel}>{children}</span>
        </button>
      )
    }
    
    const App = () => <Button>Submit</Button>
    
    render(<App />, document.getElementById('root'))
    
    ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์„ค์น˜ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ํ…Œ๋งˆํ™”์™€ ์ „์—ญ ์Šคํƒ€์ผ์„ ํ—ˆ์šฉํ•œ๋‹ค.๊ฒŒ์œผ๋ฅธ ์Šคํƒ€์ผ์‹œํŠธ๋Š” ํ•„์š”ํ•  ๋•Œ๋งŒ ์กด์žฌํ•œ๋‹ค.์Šคํƒ€์ผ์‹œํŠธ์˜ ์ •์  ์š”์†Œ๋Š” ๋ชจ๋“  ์š”์†Œ ๊ฐ„์— ๊ณต์œ ๋ฉ๋‹ˆ๋‹ค.๊ทธ๊ฒƒ๋“ค์€ ๊ตญ๋ถ€์ ์ธ ๋ฒ”์œ„๋ฅผ ์ œ๊ณตํ–ˆ์ง€๋งŒ ํ•™์Šต๊ณผ ์ฝ๊ธฐ๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜๋„ ์žˆ๋‹ค.

    ์Šคํƒ€์ผ ๊ตฌ์„ฑ ์š”์†Œ


    ๋‚˜๋Š” ์ตœ๊ทผ์— ๋ง‰ ์™„์„ฑํ–ˆ๋‹ค. (๊ทธ๋Ÿฌ๋‚˜ ์™„์„ฑํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.) ๋‚˜๋Š” ์ด๊ณณ์˜ ์ƒˆ๋กœ์šด ํˆฌ์ž ์กฐํ•ฉ์„ ๋งŒ๋“ค์—ˆ๋‹ค. shameless plug. ๋‚˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์Šคํƒ€์ผํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.์Šคํƒ€์ผ ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž์™€ ํ•จ๊ป˜ ์„ค์น˜ํ•œ ๋‹ค์Œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ index.js(x) ํŒŒ์ผ์— ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค.๋‹ค์Œ์€ ๋‚ด ํˆฌ์ž์กฐํ•ฉ์˜ ํ•œ ์˜ˆ๋‹ค.
    import styled from 'styled-components';
    
    export const Container = styled.div`
      max-width: 1280px;
      margin: 0 auto;
      width: 90%;
      @media (min-width: 601px) {
        width: 90%;
      }
      @media (min-width: 993px) {
        width: 80%;
      }
    `;
    
    ์œ„์˜ ๊ตฌ์„ฑ ์š”์†Œ๋Š” Container๋กœ ๋‚ด๋ณด๋‚ด์ ธ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ด๊ฒƒ์€ div ํ˜•์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ์Šคํƒ€์ผํ™”๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ…Œ๋งˆํ™”ํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ ์„ค์น˜ ํ›„ SASS์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋‚˜๋Š” npm i styled-components๋ฅผ ์‚ฌ์šฉํ•œ ํ›„์— ์ผ์„ ์‹œ์ž‘ํ–ˆ๋‹ค.์•ฝ๊ฐ„์˜ ํ•™์Šต ๊ณก์„ ๊ณผ ์„ฑ๋Šฅ์€ ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋“ค์€ ์ •๋ง ๋ฉ‹์ง„ ์ผ์„ ํ•œ๋‹ค.

    ๋ณด์ƒ: ์ง๋ ฌ ์Šคํƒ€์ผ๋ง

    <h1 style={{color: 'blue'}}>Hellow World</h1>

    ๊ฒฐ๋ก 


    ์›Œํ„ฐ ํด๋ฆฌ๋‹‰ ์Šคํƒ€์ผ์„ ์„ ํƒํ•  ๋•Œ ๋งŽ์€ ์„ ํƒ์ด ์žˆ๋‹ค.ํ”„๋กœ์ ํŠธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์Šคํƒ€์ผ๋ง ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.๋‹น์‹ ์ด ์ข‹์•„ํ•˜๋Š” ๊ฒƒ์„ ์ฐพ์•„์„œ ์ง„์ •์œผ๋กœ ๊ทธ๊ฒƒ์„ ์ž˜ํ•˜๋ฉด ๋‹น์‹ ์€ ์Šคํƒ€์ผ๋ง์˜ ๊ถŒ์„ธ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.๋ณ€ํ•จ์—†์ด ๋‹ค์Œ ์ฃผ์— ๋ด์š”~์•„๋ก 

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ