[DevCamp] ๐Ÿ“ฑ React์—์„œ ๋ชจ๋ฐ”์ผ ๋Œ€์‘ํ•˜๊ธฐ

๋™๊ฑดยท2025๋…„ 4์›” 29์ผ
0

DevCamp

๋ชฉ๋ก ๋ณด๊ธฐ
57/85

๐Ÿ“ฑ React์—์„œ ๋ชจ๋ฐ”์ผ ๋Œ€์‘ํ•˜๊ธฐ

React๋ฅผ ์‚ฌ์šฉํ•ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ,
๋ฐ์Šคํฌํ†ฑ ํ™˜๊ฒฝ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ๋„ ์ž˜ ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

์‚ฌ์šฉ์ž๋“ค์˜ ๋งŽ์€ ๋น„์œจ์ด ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋ฐ”์ผ ๋Œ€์‘์€ ํ•„์ˆ˜๊ฐ€ ๋˜์—ˆ๋‹ค.


๐Ÿงน ๋ฐ˜์‘ํ˜• ์›น์ด๋ž€?

๋ฐ˜์‘ํ˜• ์›น(Responsive Web)์€ ๋‹ค์–‘ํ•œ ํ™”๋ฉด ํฌ๊ธฐ์— ๋”ฐ๋ผ
์ฝ˜ํ…์ธ ์™€ ๋ ˆ์ด์•„์›ƒ์ด ์ž๋™์œผ๋กœ ์กฐ์ •๋˜๋Š” ์›น ๋””์ž์ธ ๋ฐฉ์‹์ด๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๋ฐ์Šคํฌํ†ฑ, ํƒœ๋ธ”๋ฆฟ, ๋ชจ๋ฐ”์ผ ๋“ฑ
๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ๋™์ผํ•œ ์›น์‚ฌ์ดํŠธ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ“ ๋ทฐํฌํŠธ ์„ค์ •ํ•˜๊ธฐ

๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ์ ์ ˆํ•œ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด ๊ฐ€์žฅ ๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€
๋ทฐํฌํŠธ ๋ฉ”ํƒ€ ํƒœ๊ทธ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

์ด ํƒœ๊ทธ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด
๋ชจ๋ฐ”์ผ ๋ธŒ๋ผ์šฐ์ €๋Š” ์›นํŽ˜์ด์ง€๋ฅผ ์ถ•์†Œํ•ด์„œ ๋ณด์—ฌ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„ํ•œ UI๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์—†๋‹ค.


๐Ÿ–ผ๏ธ CSS ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

CSS์˜ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ™”๋ฉด์˜ ๋„ˆ๋น„์— ๋”ฐ๋ผ ์Šคํƒ€์ผ์„ ๋‹ค๋ฅด๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

/* ๋ชจ๋ฐ”์ผ ์šฐ์„  */
.container {
  padding: 16px;
}

/* ํƒญ๋ง ์ด์ƒ */
@media (min-width: 768px) {
  .container {
    padding: 24px;
  }
}

/* ๋ฐ์Šคํฌํ† ํ”„ ์ด์ƒ */
@media (min-width: 1024px) {
  .container {
    padding: 32px;
  }
}

๋ชจ๋ฐ”์ผ ํผ์ŠคํŠธ ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„ํ•˜๋ฉด ๊ธฐ๋ณธ ์Šคํƒ€์ผ์€ ๋ชจ๋ฐ”์ผ์„ ๊ธฐ์ค€์œผ๋กœ ์ž‘์„ฑํ•˜๊ณ ,
์ ์  ๋„“์€ ํ™”๋ฉด์— ๋งž์ถฐ ์Šคํƒ€์ผ์„ ํ™•์žฅํ•ด ๋‚˜๊ฐ„๋‹ค.


โš™๏ธ styled-components์—์„œ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

React์—์„œ styled-components๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด,
JS ์•ˆ์—์„œ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

import styled from 'styled-components'

const Box = styled.div`
  padding: 16px;

  @media (min-width: 768px) {
    padding: 24px;
  }

  @media (min-width: 1024px) {
    padding: 32px;
  }
`

์ฝ”๋“œ๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์— ์šฉ์ดํ•˜๋‹ค.


๐Ÿง CSS ๋‹จ์œ„ ์‚ฌ์šฉ์— ์ฃผ์˜ํ•˜๊ธฐ

๋ชจ๋ฐ”์ผ ๋Œ€์‘ ์‹œ px ๋‹จ์œ„๋ณด๋‹ค๋Š” rem, %, vh, vw ๊ฐ™์€ ์ƒ๋Œ€ ๋‹จ์œ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
ํฐํŠธ ํฌ๊ธฐ๋‚˜ ๋งˆ์ง„์ด ๊ธฐ๊ธฐ ํ•ด์ƒ๋„์— ๋งž๊ฒŒ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์กฐ์ •๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

font-size: 1.2rem;
width: 80%;
height: 50vh;

๐Ÿช  useWindowSize ํ›…์œผ๋กœ ๋™์  ๋Œ€์‘ํ•˜๊ธฐ

JavaScript๋กœ ํ™”๋ฉด ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฐœ์ฒด ๋ฐ UI๋ฅผ ์กฐ์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š”
useWindowSize ๊ฐ™์€ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•œ๋‹ค.

import { useState, useEffect } from 'react'

function useWindowSize() {
  const [size, setSize] = useState([window.innerWidth, window.innerHeight])

  useEffect(() => {
    const handleResize = () => {
      setSize([window.innerWidth, window.innerHeight])
    }
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [])

  return size
}

์ด๋ฅผ ํ†ตํ•ด ํ™”๋ฉด ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋“ฑ ์œ ์—ฐํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿงช ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  • Chrome DevTools์˜ Device Toolbar ์‚ฌ์šฉ
  • ์‹ค์ œ ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ์—์„œ ์ง์ ‘ ํ…Œ์ŠคํŠธ
  • react-device-detect ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๋””๋ฐ”์ด์Šค ๊ฐ์ง€

๐Ÿ”จ TIL

  • ๋ชจ๋ฐ”์ผ ๋Œ€์‘์€ ๋ทฐํฌํŠธ ์„ค์ •๊ณผ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ถ€ํ„ฐ ์‹œ์ž‘๋œ๋‹ค.
  • CSS๋Š” ๋ชจ๋ฐ”์ผ ํผ์ŠคํŠธ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๊ณ , ์ƒ๋Œ€ ๋‹จ์œ„๋ฅผ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • styled-components ์—์„œ๋„ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • JavaScript๋กœ ํ™”๋ฉด ํฌ๊ธฐ๋ฅผ ๊ฐ์ง€ํ•ด ๋™์ ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๋‹ค์–‘ํ™”ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜๋‹ค.
profile
๋ฐฐ๊ณ ํ”ˆ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€