์‚ฌ์šฉ์ž ์ •์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ„์ด ๋ฐ˜์งโœจ๋ฐฐ๊ฒฝ ๋งŒ๋“ค๊ธฐ (tailwindCSS)

2024. 9. 14. 16:41ยทWhat I Learn

 

box-shadow๋กœ ์ฃผ๋ณ€์„ ๋ฐํ˜”๋‹ค ์–ด๋‘ก๊ฒŒ ํ–ˆ๋‹ค ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ˜์ง์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์—ฐ์ถœํ•œ ๋ฐฉ์‹์„ ๋ณด๊ณ  ์ฐธ๊ณ ํ•ด์„œ ์ž‘์„ฑํ–ˆ๋‹ค.

 

ํด๋ž˜์Šค๋ช…์œผ๋กœ ์‚ฌ์šฉํ•  ๋ฐฐ์—ด๋กœ ๊ฐ๊ฐ ๋ณ„์˜ ์‚ฌ์ด์ฆˆ, ํˆฌ๋ช…๋„, **์• ๋‹ˆ๋ฉ”์ด์…˜** (์•„๋ž˜์—์„œ ๋‚ด๊ฐ€ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•  ๊ฒƒ, ์ด ํด๋ž˜์Šค๋ช…์—์„œ ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ๋‹ค.... ํ•˜๋‹จ์—์„œ ์„ค๋ช…ํ•  ๊ฒƒ)์„ ์„ ์–ธํ•˜๊ณ 

getRandomValue ํ•จ์ˆ˜๋กœ ๋ณ„์ด ๋ฟŒ๋ ค์งˆ ๋žœ๋คํ•œ ๊ฐฏ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ–ˆ๋‹ค. 

 

ํŽ˜์ด์ง€์˜ ๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ์œผ๋กœ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด์—ˆ๊ธฐ์— ์‚ฌ์šฉ์ž๊ฐ€ ์“ฐ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ฐฝ์˜ ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ณ„์„ ๋ฟŒ๋ ค์ฃผ๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ, window๋ฅผ ์ฐธ์กฐํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ window is not defined ์—๋Ÿฌ๊ฐ€ ๋–ด๋‹ค. ์ฐพ์•„๋ณด๋‹ˆ nextjs๊ฐ€ ssr๋กœ ์„œ๋ฒ„์—์„œ ๋จผ์ €  HTML์„ ๊ทธ๋ ค๋†“๋Š”๋ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ window์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ๊ทธ๋ ค์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ์กฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ !!

 

 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด๋‹ˆ

1) ํƒ€์ž… ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๊ฑฐ๋‚˜,  2) useEffect๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์•„๋‹ˆ๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ 3) ssr์„ ๋น„ํ™œ์„ฑํ™”์‹œํ‚ค๋Š” ์˜ต์…˜์ด ์žˆ์—ˆ๋‹ค. 

// ssr ๋น„ํ™œ์„ฑํ™”
'use client'
 
import dynamic from 'next/dynamic'
 
const DynamicHeader = dynamic(() => import('../components/header'), {
  ssr: false,
})

 

 

๊ทธ ์ค‘์— ๋‚˜๋Š” useEffect๋กœ ์ž‘์„ฑํ•˜๋ฉด์„œ ๋‚ด๋ถ€์— ํƒ€์ž… ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ 2์ค‘ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

useEffect๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‚ด๋ถ€์— ์ž‘์„ฑํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š” ์‹œ์ ์— ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ssr ํ™˜๊ฒฝ์ด์–ด๋„ ์ž‘๋™์ด ๋œ๋‹ค.

 

 

์ตœ์ข…์œผ๋กœ ์ž‘์„ฑํ•œ ๋ฐฐ๊ฒฝ ์ปดํฌ๋„ŒํŠธ

"use client";
import { useState, useEffect } from "react";

export default function StarrySky() {
  const [stars, setStars] = useState([]);
  const style = ["w-[1px] h-[1px]", "w-[1.5px] h-[1.5px]", "w-[2px] h-[2px]"];
  const opacity = ["opacity-50", "opacity-100", "opacity-10", "opacity-50", "opacity-10"];
  const twinkle = ["animate-twinkle1", "animate-twinkle2", "animate-twinkle3", "animate-twinkle4"];

  const getRandomValue = (maxNum) => {
    return Math.floor(Math.random() * maxNum);
  };

  const maxNum = 300; // maxNum ์ž„์˜๋กœ ๋„ฃ์—ˆ๋Š”๋ฐ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
  
// ** useEffect => nextjs์˜ window ๊ฐ์ฒด ์ฐธ์กฐ ์˜ค๋ฅ˜!! ๊ด€๋ จํ•ด์„œ window ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด useEffect๋กœ ๋ฌถ๊ณ  ๊ทธ ์•ˆ์—์„œ ์‚ฌ์šฉ
  useEffect(() => {
      if (typeof window !== "undefined") {
        const browserWidth = window.screen.width;
        const browserHeight = window.screen.height;
        let starArr = [];
        for (let i = 0; i < maxNum; i++) {
          const x = getRandomValue(browserWidth);
          const y = getRandomValue(browserHeight);
          const starSize = style[getRandomValue(style.length)];
          const starOpacity = opacity[getRandomValue(opacity.length)];
          const starTwinkle = twinkle[getRandomValue(twinkle.length)];

          starArr.push({
            id: i,
            x,
            y,
            starSize,
            starOpacity,
            starTwinkle,
          });
        }
        setStars(starArr);
      }
    },
    []);
  return (
    <div className="absolute inset-0 overflow-hidden">
      {stars.map((star) => (
        <div
          key={star.id}
          className={`absolute rounded-full bg-white ${star.starSize} ${star.starOpacity} ${star.starTwinkle}`}
          style={{ left: star.x, top: star.y }}
        ></div>
      ))}
    </div>
  );
}

 

 

๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ tailwind.config.js ํŒŒ์ผ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค. 

 

// tailwind.config.js 
module.exports = {
  theme: {
    extend: {
      animation: {
        twinkle1: "twinkling 0.5s infinite",
        twinkle2: "twinkling 1.1s infinite",
        twinkle3: "twinkling 1.3s infinite",
        twinkle4: "twinklingWithoutBoxShadow 3s infinite",
      },
      keyframes: {
        twinkling: {
          "0%, 100%": {
            boxShadow: "0 0 10px 0px rgba(255, 255, 255, 0.1)",
          },
          "50%": {
            boxShadow: "0 0 10px 2px rgba(255, 255, 255, 0.6)",
          },
        },
        twinklingWithoutBoxShadow: {
          "0%": {
            backgroundColor: "#ffffff",
            boxShadow: "0 0 10px 0px rgba(255, 255, 255, 1)",
          },
          "20%": {
            backgroundColor: "#ffc4c4",
            boxShadow: "0 0 10px 0px rgba(255, 196, 196, 1)",
          },
          "80%": {
            backgroundColor: "#c4cfff",
            boxShadow: "0 0 10px 0px rgba(196, 207, 255, 1)",
          },
          "100%": {
            backgroundColor: "#ffffff",
            boxShadow: "0 0 10px 0px rgba(255, 255, 255, 0.2)",
          },
        },
      },
    },
  },
  plugins: [],
};

 

 

animation์—๋Š” keyframes์— ์ž‘์„ฑํ•  ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฆ„์„ ์ ์–ด์ฃผ๊ณ , css์—์„œ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  keyframes์—๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์ด๋ฆ„๊ณผ ํšจ๊ณผ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. ์œ„์ฒ˜๋Ÿผ 0%, 50%, 100%๋กœ ํผ์„ผํ‹ฐ์ง€๋กœ ๋‚˜๋ˆ ์„œ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ ๊ทธ๋ผ๋ฐ์ด์…˜ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ์ฒ˜๋Ÿผ from, to๋กœ ์จ๋„ ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

 

rgb์™€ rgba์˜ ์ฐจ์ด๋„ ์ด๋ฒˆ์— ๋ฐฐ์› ๋‹ค. ํˆฌ๋ช…๋„๋ฅผ ์ค„๊ฑฐ๋ฉด a๋ฅผ ๋ถ™์—ฌ์•ผํ•จ~!!! rgb + alpha(ํˆฌ๋ช…๋„)์ธ ๊ฒƒ์ด๋‹ค

alpha ๊ฐ’์€ 0~1๊นŒ์ง€์˜ ๊ฐ’์„ ๊ฐ€์ง€๊ณ , 0์— ๊ฐ€๊นŒ์šธ ์ˆ˜๋ก ํˆฌ๋ช…ํ•˜๋‹ค. 

 

 

์—ฌ๊ธฐ๊นŒ์ง€ ์ž‘์„ฑํ–ˆ์œผ๋ฉด ์ž˜ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒํ•˜๊ณ  dev ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œ์ผฐ๋Š”๋ฐ boxShadow ํšจ๊ณผ๊ฐ€ ์˜ˆ์ƒ์ฒ˜๋Ÿผ ์‹คํ–‰์ด ๋˜์ง€ ์•Š์•˜๋‹ค.

// ์ฒ˜์Œ์— ๋™์ž‘ ์•ˆ ๋˜๋˜ ์ฝ”๋“œ
  const twinkle = ["twinkle1", "twinkle2", "twinkle3", "twinkle4"];

// ๊ณ ์น˜๊ณ  ๋™์ž‘๋˜๋Š” ์ฝ”๋“œ
  const twinkle = ["animate-twinkle1", "animate-twinkle2", "animate-twinkle3", "animate-twinkle4"];

 

animation์—์„œ ์ž‘์„ฑํ•œ ๊ทธ๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ์— ํด๋ž˜์Šค๋ช…์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ž‘์ด ์•ˆ๋œ๋‹ค !!!

๋ฐ˜๋“œ์‹œ 'animation-' ์„ ์ ‘๋‘์‚ฌ๋กœ ๋ถ™์—ฌ์„œ ์ปดํฌ๋„ŒํŠธ์— ํด๋ž˜์Šค๋ช…์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘๋œ๋‹ค. (ใ… .,ใ… )

 

์ด๋ ‡๊ฒŒ ํ•˜๊ณ  root์˜ layout ํŒŒ์ผ์— ๋„ฃ์–ด์ฃผ๋ฉด ๋ชจ๋“  ํŽ˜์ด์ง€์— ์ ์šฉ์ด ๋œ๋‹ค.

์ฐธ๊ณ ๋กœ ๋ฐฐ๊ฒฝ์˜ ๊ทธ๋ผ๋ฐ์ด์…˜ ์ปฌ๋Ÿฌ๋Š” globals.css > body > background์— ์ปฌ๋Ÿฌ๋ฅผ ์ง€์ •ํ•ด์คฌ๋‹ค.

 

 


 

ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… !!

์œ„์ฒ˜๋Ÿผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ  ๋‹ค๋ฅธ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์„ ํ•˜๋ ค๊ณ  ์ž„์‹œ๋กœ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ์กฐ์ฐจ ๋˜์ง€ ์•Š์•˜๋‹ค.

๋ญ๊ฐ€ ๋ฌธ์ œ์ธ์ง€ ๋ชฐ๋ž์—ˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค.

export default async function RootLayout({ children }) {
  const session = await getServerSession();

  return (
    <html lang="en">
      <body className={inter.className}>
        <Providers session={session}>
           <StarrySky /> // ์—ฌ๊ธฐ๊ฐ€ ๋งž๋Š” ์œ„์น˜
          {children}
         // <StarrySky /> ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด ์ด์œ . 
        </Providers>
      </body>
    </html>
  );
}

 

์šฐ์„ ์ˆœ์œ„์— ๋ฐ€๋ ค์„œ ๋‹ค๋ฅธ ๋…€์„๋“ค์ด ๊น”๋ฆฐ ๊ฑฐ ์˜€๋‹ค !!! (ใ…œ.,ใ…œ) ์ „์—ญ์œผ๋กœ ์„ค์ •ํ•ด์ฃผ๋ ค๋ฉด {children}์˜ ์ƒ๋‹จ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค..

 

'What I Learn' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

OSSCA : setting the Continue at vscode & Overview  (0) 2024.09.23
์ „์—ญ์—์„œ ๋ชจ๋‹ฌ ์ƒํƒœ๊ด€๋ฆฌํ•˜๊ธฐ (redux-toolkit)  (1) 2024.09.20
Make Calendar without Calendar library (@date-fns)  (0) 2024.09.13
Separate Next.js Root Layout from 404 Page Layout  (0) 2024.09.01
picture, source, img ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•œ ๋ฐ˜์‘ํ˜• ์ด๋ฏธ์ง€ ๊ตฌํ˜„ (CSS)  (0) 2024.08.25
'What I Learn' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • OSSCA : setting the Continue at vscode & Overview
  • ์ „์—ญ์—์„œ ๋ชจ๋‹ฌ ์ƒํƒœ๊ด€๋ฆฌํ•˜๊ธฐ (redux-toolkit)
  • Make Calendar without Calendar library (@date-fns)
  • Separate Next.js Root Layout from 404 Page Layout
nuew
nuew
๐Ÿคธ ์žฌ์ฃผ ๋„˜๋Š” ์ค‘
  • nuew
    bloggg. . .๐Ÿฆ–๐Ÿ’ฅ
    nuew
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (88)
      • issue (10)
      • baekjoon (41)
      • lecture recap (11)
      • What I Learn (26)
      • retrospective (0)
      • maeil-mail (0)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
    • ๋ฐฉ๋ช…๋ก
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    TailwindCSS
    Study
    ์•Œ๊ณ ๋ฆฌ์ฆ˜
    ํ•œ์ž…ํฌ๊ธฐ๋กœ์ž˜๋ผ๋จน๋Š”ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ
    Baekjoon
    Algorithm
    TypeScript
    Node.js
    ํ•œ์ž…ํฌ๊ธฐ๋กœ ์ž˜๋ผ๋จน๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ
    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ
    issue
    what i learn
    css
    ์ฝ”๋”ฉํ…Œ์ŠคํŠธ
    js
    media-query
    JavaScript
    ๋ฐฑ์ค€
    zustand
    modal
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
nuew
์‚ฌ์šฉ์ž ์ •์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋ณ„์ด ๋ฐ˜์งโœจ๋ฐฐ๊ฒฝ ๋งŒ๋“ค๊ธฐ (tailwindCSS)
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”