Repository: Seoul-InterViewer/InterViewer
Pull request #19: INTER-222-HeaderComponent-공용 컴포넌트 헤더 구현
Author: login: mulgko
Labels: name: 🔮 Feature
description: 새로운 기능 추가
name: 💄 Style
description: 스타일 추가
Created: 2025-05-22T03:39:42Z | Merged: 2025-05-27T11:16:41Z

## PR 본문

### 반영 브랜치

INTER-222-HeaderComponent -> dev

### PR 타입(하나 이상의 PR 타입을 선택해주세요)

- [x] 기능 추가
- [ ] 기능 삭제
- [ ] 버그 수정
- [ ] 의존성, 환경 변수, 빌드 관련 코드 업데이트

### 작업 내용

- 이번 PR에서 작업한 내용을 간략히 설명해주세요. (이미지 첨부 가능)
- 헤더 컴포넌트 구현 

### 스크린샷 (선택)
<img width="1488" alt="image" src="https://github.com/user-attachments/assets/af5596f7-7bf6-465f-93cc-4a0c7fa1eaa8" />

https://github.com/user-attachments/assets/7c1e926b-4411-4e10-80af-696f591b0599


Diff:
diff --git a/src/app/components/header/Header.tsx b/src/app/components/header/Header.tsx
new file mode 100644
index 0000000..e522e26
--- /dev/null
+++ b/src/app/components/header/Header.tsx
@@ -0,0 +1,261 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import {
+  headerVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+} from "./header.variants";
+import { motion, useScroll, useMotionValueEvent } from "framer-motion";
+
+const { header, navMenu, createMenu, login } = headerVariants();
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+  { name: "Php", href: "/php" },
+  { name: "Python", href: "/python" },
+  { name: "Java", href: "/java" },
+  { name: "C#", href: "/csharp" },
+  { name: "C++", href: "/cpp" },
+  { name: "Ruby", href: "/ruby" },
+  { name: "Swift", href: "/swift" },
+];
+
+export const Header = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+
+  const [isCondensed, setIsCondensed] = useState(false);
+  const { scrollY } = useScroll();
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  useMotionValueEvent(scrollY, "change", (latest) => {
+    const previous = scrollY.getPrevious() ?? 0;
+    if (latest > previous && latest > 50) {
+      setIsCondensed(true);
+    } else if (latest < previous) {
+      setIsCondensed(false);
+    }
+  });
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <motion.header
+        className={header()}
+        animate={{
+          height: isCondensed ? "60px" : "80px",
+        }}
+        transition={{ duration: 0.3 }}
+      >
+        <div className="mx-auto flex justify-between items-center h-full">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-0 md:gap-2">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <motion.div
+                className="flex items-center gap-2 md:gap-4"
+                animate={{
+                  scale: isCondensed ? 0.8 : 1,
+                }}
+                transition={{ duration: 0.3 }}
+              >
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })}  px-[0px] py-[0px]`}
+                  onClick={() => setSidebarOpen(true)}
+                >
+                  <Icon name="menu" className="w-10 h-10 md:w-13 md:h-13" />
+                </Button>
+              </motion.div>
+              {/* 로고 (홈페이지 링크) */}
+              <motion.div
+                animate={{
+                  scale: isCondensed ? 0.8 : 1,
+                }}
+                transition={{ duration: 0.3 }}
+              >
+                <Link href="/">
+                  <img src="/images/logo.svg" alt="logo" className="w-24 h-auto md:w-33" />
+                </Link>
+              </motion.div>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <div className="hidden md:block">
+              <motion.nav
+                initial={{ opacity: 0 }}
+                animate={{
+                  opacity: isCondensed ? 0 : 1,
+                  x: isCondensed ? -20 : 0,
+                  display: isCondensed ? "none" : "block",
+                }}
+                transition={{ duration: 0.3 }}
+              >
+                <ul className="flex items-center gap-4">
+                  {navMenuItems.map((item) => (
+                    <li key={item.href} className={navMenu()}>
+                      <Link href={item.href}>{item.name}</Link>
+                    </li>
+                  ))}
+                </ul>
+              </motion.nav>
+            </div>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center justify-end gap-2 md:gap-4 h-full">
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <motion.div
+                className="flex items-center gap-2 md:gap-4"
+                animate={{
+                  opacity: isCondensed ? 0 : 1,
+                  x: isCondensed ? 20 : 0,
+                  visibility: isCondensed ? "hidden" : "visible",
+                }}
+              >
+                <div className="relative flex items-center gap-2 md:gap-4">
+                  <Button
+                    type="button"
+                    className={`${buttonVariants({ color: "white" })}`}
+                    onClick={() => setCreateMenuOpen(!createMenuOpen)}
+                  >
+                    <Icon name="createNew" className="w-6 h-6 md:w-8 md:h-8 cursor-pointer" />
+                  </Button>
+                  <Link href="/setting">
+                    <Icon name="setting" className="w-6 h-6 md:w-8 md:h-8 cursor-pointer" />
+                  </Link>
+
+                  {/* 드롭다운 메뉴 */}
+                  {createMenuOpen && (
+                    <div className={createMenu()}>
+                      <ul className="py-2">
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-question" className="block w-full">
+                            질문올리기
+                          </Link>
+                        </li>
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-game" className="block w-full">
+                            게임만들기
+                          </Link>
+                        </li>
+                      </ul>
+                    </div>
+                  )}
+                </div>
+              </motion.div>
+            ) : (
+              // 비로그인 상태 - 로그인 버튼 표시
+              <motion.div
+                className="flex items-center"
+                animate={{
+                  opacity: isCondensed ? 0 : 1,
+                  x: isCondensed ? 20 : 0,
+                  visibility: isCondensed ? "hidden" : "visible",
+                }}
+                transition={{ duration: 0.3 }}
+              >
+                <Button type="button" className={`${buttonVariants({ color: "white" })}`}>
+                  <div className={login()}>Login</div>
+                </Button>
+              </motion.div>
+            )}
+
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <motion.div
+              className="flex items-center"
+              animate={{
+                scale: isCondensed ? 0.8 : 1,
+              }}
+            >
+              <Button
+                type="button"
+                className={`${buttonVariants({ color: "white", icon: true })} `}
+              >
+                <Icon name="search" className="w-6 h-6 md:w-8 md:h-8" />
+              </Button>
+            </motion.div>
+          </div>
+        </div>
+      </motion.header>
+
+      {/* 사이드바 오버레이 (사이드바가 열려있을 때만 표시) */}
+      {sidebarOpen && (
+        <div
+          className={modalOverlayVariants({ type: "sidebar" })}
+          onClick={() => setSidebarOpen(false)}
+        />
+      )}
+
+      {/* 사이드바 (왼쪽에서 슬라이드 인) */}
+      <div className={sidebarVariants({ isOpen: sidebarOpen })}>
+        <div className="p-4 h-screen flex flex-col">
+          {/* 사이드바 헤더: 제목과 닫기 버튼 */}
+          <div className="flex justify-between items-center">
+            <h2 className="font-sb-24">메뉴</h2>
+            <button className="p-2 cursor-pointer" onClick={() => setSidebarOpen(false)}>
+              <Icon name="close" className="w-6 h-6 md:w-8 md:h-8" />
+            </button>
+          </div>
+
+          {/* 사이드바 메뉴 항목들 */}
+          <nav className="mt-8 flex-1 overflow-y-auto">
+            {/* 사이트 제목/로고 */}
+            <h1 className="mb-4">
+              <div className={sidebarMenuItemVariants({ type: "title" })}>InterViewer</div>
+            </h1>
+            {/* 메뉴 항목 목록 (배열에서 동적 생성) */}
+            <ul className="space-y-4">
+              {defaultMenuItems.map((item) => (
+                <li key={item.href}>
+                  <Link href={item.href} className={sidebarMenuItemVariants({ type: "menuItem" })}>
+                    {item.name}
+                  </Link>
+                </li>
+              ))}
+            </ul>
+          </nav>
+        </div>
+      </div>
+    </>
+  );
+};
diff --git a/src/app/components/header/header.type.ts b/src/app/components/header/header.type.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/header/header.variants.ts b/src/app/components/header/header.variants.ts
new file mode 100644
index 0000000..3e1b571
--- /dev/null
+++ b/src/app/components/header/header.variants.ts
@@ -0,0 +1,54 @@
+import { tv } from "tailwind-variants";
+
+export const headerVariants = tv({
+  slots: {
+    header:
+      "border-b border-gray-200 mx-auto px-4 fixed w-full top-0 left-0 right-0 bg-white z-40 transition-all duration-300",
+    navMenu: "font-regular-18  md: font-regular-16 hover:text-main hover:font-sb-24",
+    createMenu:
+      "absolute right-0 top-full mt-2 w-40 bg-white border border-gray-200 rounded-md shadow-lg z-50 transform origin-top-right transition-all duration-200",
+    login: "font-sb-14 md:font-sb-24",
+  },
+});
+
+export const sidebarVariants = tv({
+  base: "fixed top-0 left-0 bottom-0 w-64 bg-white z-50 transform transition-transform duration-300 ease-in-out shadow-lg",
+  variants: {
+    isOpen: {
+      default: false,
+      true: "translate-x-0",
+      false: "-translate-x-full",
+    },
+  },
+});
+
+export const modalOverlayVariants = tv({
+  base: "fixed inset-0 z-40 transition-opacity duration-300 cursor-pointer",
+  variants: {
+    type: {
+      sidebar: "bg-black/60",
+      search: "bg-black/70",
+    },
+  },
+  defaultVariants: {
+    type: "sidebar",
+  },
+});
+
+export const sidebarMenuItemVariants = tv({
+  base: "block py-2 transition-colors rounded-md px-2",
+  variants: {
+    type: {
+      title: "font-sb-14 md:font-sb-18 hover:text-main hover:bg-gray-50 ",
+      menuItem: "font-regular-14 md:font-regular-18 text-font-gray hover:text-main",
+    },
+    state: {
+      default: "",
+      active: "text-main",
+    },
+  },
+  defaultVariants: {
+    type: "menuItem",
+    state: "default",
+  },
+});
diff --git a/src/app/components/header/index.ts b/src/app/components/header/index.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/header/page.tsx b/src/app/components/header/page.tsx
new file mode 100644
index 0000000..f2acfc1
--- /dev/null
+++ b/src/app/components/header/page.tsx
@@ -0,0 +1,12 @@
+import React from "react";
+
+import { Header } from "./Header";
+
+export default function HeaderPage() {
+  return (
+    <div className="w-full h-[2000px]">
+      {/* isLoggedin props를 받아서 처리할 수 있음 */}
+      <Header isLoggedIn={true} />
+    </div>
+  );
+}
diff --git a/src/app/components/icon/page.tsx b/src/app/components/icon/page.tsx
index 554188c..be71f24 100644
--- a/src/app/components/icon/page.tsx
+++ b/src/app/components/icon/page.tsx
@@ -55,7 +55,12 @@ export default function IconGalleryPage() {
           {iconNames.map((name) => (
             <div key={name} className="flex-center flex-col border p-4 rounded">
               <div className="flex items-center justify-center h-12">
-                <Icon name={name} fill="var(--color-correct)" stroke="var(--color-incorrect)" strokeWidth={1} />
+                <Icon
+                  name={name}
+                  fill="var(--color-correct)"
+                  stroke="var(--color-incorrect)"
+                  strokeWidth={1}
+                />
               </div>
               <span className="--font-sb-14 text-gray-700 mt-2">{name}</span>
             </div>
@@ -78,10 +83,34 @@ export default function IconGalleryPage() {
           <Icon name="report" width={50} height={50} stroke="var(--color-incorrect)" />
           <Icon name="plus" width={50} height={50} fill="var(--color-border)" />
           <Icon name="chevronDown" width={50} height={50} fill="var(--color-border)" />
-          <Icon name="chevronUp" width={50} height={50} fill="var(--color-border)" stroke="var(--color-main)" />
-          <Icon name="search" width={50} height={50} fill="var(--color-border)" stroke="var(--color-main)" />
-          <Icon name="user" width={50} height={50} fill="var(--color-border)" stroke="var(--color-main)" />
-          <Icon name="verticalElipsis" width={50} height={50} fill="var(--color-border)" stroke="var(--color-main)" />
+          <Icon
+            name="chevronUp"
+            width={50}
+            height={50}
+            fill="var(--color-border)"
+            stroke="var(--color-main)"
+          />
+          <Icon
+            name="search"
+            width={50}
+            height={50}
+            fill="var(--color-border)"
+            stroke="var(--color-main)"
+          />
+          <Icon
+            name="user"
+            width={50}
+            height={50}
+            fill="var(--color-border)"
+            stroke="var(--color-main)"
+          />
+          <Icon
+            name="verticalElipsis"
+            width={50}
+            height={50}
+            fill="var(--color-border)"
+            stroke="var(--color-main)"
+          />
         </div>
       </div>
     </div>
diff --git a/src/app/globals.css b/src/app/globals.css
index 8251c7b..b270c28 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -4,6 +4,7 @@
 @import "../styles/variables.css";
 @import "../styles/mixins.css";
 
-html, body{
+html,
+body {
   font-family: "Pretendard" !important;
-}
\ No newline at end of file
+}
diff --git a/src/styles/theme.css b/src/styles/theme.css
index d5943a9..05257ba 100644
--- a/src/styles/theme.css
+++ b/src/styles/theme.css
@@ -49,4 +49,4 @@
   /* Container */
   --container-pc: 1260px;
   --container-mobile: 768px;
-}
\ No newline at end of file
+}


Reviews:
user: login: GiToon10100011
body: 고생많으셨습니다. 요청사항 수정 후 재 커밋 부탁드리겠습니다!
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T04:34:23Z
user: login: GiToon10100011
body: 추가 수정 부탁드립니다
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T05:06:58Z
user: login: GiToon10100011
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T11:25:14Z
user: login: GiToon10100011
body: 수정하느라 고생이 많으십니다. 파이팅!
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T01:54:42Z
user: login: mulgko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T02:16:02Z

Review comments:
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: Link경로들은 전부 추후 수정이 필요할 것 같습니다. (우선은 병합 진행)
created_at: 2025-05-22T03:43:25Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: px단위에 대한 arbitrary class는 되도록 사용하지 않습니다. w-6이나, w-7 / h-6, h-7과 같은 방법으로 수정해주세요. tailwind는 rem기반으로 움직입니다. 단위 일관성을 위해 수정 부탁드립니다.
created_at: 2025-05-22T04:24:27Z
author_association: COLLABORATOR
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: 스크롤 하면 헤더가 접히는 로직도 있으면 좋을 것 같습니다
created_at: 2025-05-22T04:26:14Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+              </Button>
+            </div>
+
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <>
+                <div className="relative create-menu-container">
+                  <button onClick={() => setCreateMenuOpen(!createMenuOpen)}>
+                    <Icon
+                      name="createNew"
+                      className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                    />
+                  </button>
+
+                  {/* 드롭다운 메뉴 */}
+                  {createMenuOpen && (
+                    <div className={createMenuVariants()}>
+                      <ul className="py-2">
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-question" className="block w-full">
+                            질문올리기
+                          </Link>
+                        </li>
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-game" className="block w-full">
+                            게임만들기
+                          </Link>
+                        </li>
+                      </ul>
+                    </div>
+                  )}
+                </div>
+                <Link href="/setting">
+                  <Icon
+                    name="setting"
+                    className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                  />
+                </Link>
+              </>
+            ) : (
+              // 비로그인 상태 - 로그인 버튼 표시
+              <button>
+                <Link href="#">
+                  <div className={loginButtonVariants()}>Login</div>
+                </Link>
+              </button>
+            )}
+          </div>
+        </div>
+      </header>
+
+      {/* 사이드바 오버레이 (사이드바가 열려있을 때만 표시) */}
+      {sidebarOpen && (
+        <div
+          className={modalOverlayVariants({ type: "sidebar" })}
+          onClick={() => setSidebarOpen(false)}
+        />
+      )}
+
+      {/* 사이드바 (왼쪽에서 슬라이드 인) */}
+      <div className={sidebarVariants({ isOpen: sidebarOpen })}>
+        <div className="p-4">
+          {/* 사이드바 헤더: 제목과 닫기 버튼 */}
+          <div className="flex justify-between items-center">
+            <h2 className="font-sb-24">메뉴</h2>
+            <button className="p-2 cursor-pointer" onClick={() => setSidebarOpen(false)}>
+              <Icon name="close" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+            </button>
+          </div>
+
+          {/* 사이드바 메뉴 항목들 */}
+          <nav className="mt-8">
+            {/* 사이트 제목/로고 */}
+            <h1 className="mb-4">
+              <Link href="/" className={sidebarMenuItemVariants({ type: "title" })}>
+                InterViewer
+              </Link>
+            </h1>
+            {/* 메뉴 항목 목록 (배열에서 동적 생성) */}
+            <ul className="space-y-4">
+              {defaultMenuItems.map((item) => (
+                <li key={item.href}>
+                  <Link href={item.href} className={sidebarMenuItemVariants()}>
+                    {item.name}
+                  </Link>
+                </li>
+              ))}
+            </ul>
+          </nav>
+        </div>
+      </div>
+
+      {/* 검색 모달 (검색 버튼 클릭 시 표시) */}
+      {searchModalOpen && (
+        <>
+          {/* 검색 모달 오버레이 - 클릭하면 모달 닫힘 */}
+          <div
+            className={modalOverlayVariants({ type: "search" })}
+            onClick={() => setSearchModalOpen(false)}
+          />
+
+          {/* 검색 모달 컨텐츠 영역 - 화면 중앙에 배치하고 오버레이와 이벤트 분리 */}
+          <div
+            className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 w-full max-w-2xl px-4 md:px-0"
+            onClick={(e) => e.stopPropagation()}
+          >
+            <div className="bg-white rounded-lg shadow-xl transform transition-all duration-300 scale-100">
+              <div className="p-5">
+                {/* 모달 헤더: 제목과 닫기 버튼 */}
+                <div className="flex items-center justify-between mb-4">
+                  <h2 className="text-xl font-bold">검색</h2>
+                  <button
+                    className="p-1 hover:bg-gray-100 rounded-full transition-colors"
+                    onClick={() => setSearchModalOpen(false)}
+                  >
+                    <svg
+                      xmlns="http://www.w3.org/2000/svg"
+                      className="h-6 w-6"
+                      fill="none"
+                      viewBox="0 0 24 24"
+                      stroke="currentColor"
+                    >
+                      <path
+                        strokeLinecap="round"
+                        strokeLinejoin="round"
+                        strokeWidth={2}
+                        d="M6 18L18 6M6 6l12 12"
+                      />
+                    </svg>
+                  </button>
+                </div>
+
+                {/* 검색 입력 필드 (아이콘 포함) */}
+                <div className="relative">
+                  <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+                    <svg
+                      xmlns="http://www.w3.org/2000/svg"
+                      className="h-5 w-5 text-gray-400"
+                      fill="none"
+                      viewBox="0 0 24 24"
+                      stroke="currentColor"
+                    >
+                      <path
+                        strokeLinecap="round"
+                        strokeLinejoin="round"
+                        strokeWidth={2}
+                        d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
+                      />
+                    </svg>
+                  </div>
+                  <input
+                    ref={searchInputRef}
+                    type="text"
+                    className="block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-main focus:border-transparent"
+                    placeholder="검색어를 입력하세요..."
+                  />
+                </div>
+
+                {/* 검색 섹션 */}
+                <div className="mt-4">
+                  <h3 className="text-sm font-medium text-gray-500 mb-2"> 검색어</h3>
+                  <div className="flex flex-wrap gap-2">
+                    <button className="px-3 py-1 bg-gray-100 rounded-full text-sm hover:bg-gray-200 transition-colors">
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: Button 컴포넌트를 사용해주세요. 
created_at: 2025-05-22T04:27:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+              </Button>
+            </div>
+
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <>
+                <div className="relative create-menu-container">
+                  <button onClick={() => setCreateMenuOpen(!createMenuOpen)}>
+                    <Icon
+                      name="createNew"
+                      className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                    />
+                  </button>
+
+                  {/* 드롭다운 메뉴 */}
+                  {createMenuOpen && (
+                    <div className={createMenuVariants()}>
+                      <ul className="py-2">
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-question" className="block w-full">
+                            질문올리기
+                          </Link>
+                        </li>
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-game" className="block w-full">
+                            게임만들기
+                          </Link>
+                        </li>
+                      </ul>
+                    </div>
+                  )}
+                </div>
+                <Link href="/setting">
+                  <Icon
+                    name="setting"
+                    className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                  />
+                </Link>
+              </>
+            ) : (
+              // 비로그인 상태 - 로그인 버튼 표시
+              <button>
+                <Link href="#">
+                  <div className={loginButtonVariants()}>Login</div>
+                </Link>
+              </button>
+            )}
+          </div>
+        </div>
+      </header>
+
+      {/* 사이드바 오버레이 (사이드바가 열려있을 때만 표시) */}
+      {sidebarOpen && (
+        <div
+          className={modalOverlayVariants({ type: "sidebar" })}
+          onClick={() => setSidebarOpen(false)}
+        />
+      )}
+
+      {/* 사이드바 (왼쪽에서 슬라이드 인) */}
+      <div className={sidebarVariants({ isOpen: sidebarOpen })}>
+        <div className="p-4">
+          {/* 사이드바 헤더: 제목과 닫기 버튼 */}
+          <div className="flex justify-between items-center">
+            <h2 className="font-sb-24">메뉴</h2>
+            <button className="p-2 cursor-pointer" onClick={() => setSidebarOpen(false)}>
+              <Icon name="close" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+            </button>
+          </div>
+
+          {/* 사이드바 메뉴 항목들 */}
+          <nav className="mt-8">
+            {/* 사이트 제목/로고 */}
+            <h1 className="mb-4">
+              <Link href="/" className={sidebarMenuItemVariants({ type: "title" })}>
+                InterViewer
+              </Link>
+            </h1>
+            {/* 메뉴 항목 목록 (배열에서 동적 생성) */}
+            <ul className="space-y-4">
+              {defaultMenuItems.map((item) => (
+                <li key={item.href}>
+                  <Link href={item.href} className={sidebarMenuItemVariants()}>
+                    {item.name}
+                  </Link>
+                </li>
+              ))}
+            </ul>
+          </nav>
+        </div>
+      </div>
+
+      {/* 검색 모달 (검색 버튼 클릭 시 표시) */}
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: 검색 모달은 페이지 컴포넌트로 분리될 예정입니다. (추후에 분리 필요)
created_at: 2025-05-22T04:27:23Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+              </Button>
+            </div>
+
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <>
+                <div className="relative create-menu-container">
+                  <button onClick={() => setCreateMenuOpen(!createMenuOpen)}>
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: 마찬가지로 Button 컴포넌트 사용 부탁드립니다.
created_at: 2025-05-22T04:28:33Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+              </Button>
+            </div>
+
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <>
+                <div className="relative create-menu-container">
+                  <button onClick={() => setCreateMenuOpen(!createMenuOpen)}>
+                    <Icon
+                      name="createNew"
+                      className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                    />
+                  </button>
+
+                  {/* 드롭다운 메뉴 */}
+                  {createMenuOpen && (
+                    <div className={createMenuVariants()}>
+                      <ul className="py-2">
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-question" className="block w-full">
+                            질문올리기
+                          </Link>
+                        </li>
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-game" className="block w-full">
+                            게임만들기
+                          </Link>
+                        </li>
+                      </ul>
+                    </div>
+                  )}
+                </div>
+                <Link href="/setting">
+                  <Icon
+                    name="setting"
+                    className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                  />
+                </Link>
+              </>
+            ) : (
+              // 비로그인 상태 - 로그인 버튼 표시
+              <button>
+                <Link href="#">
+                  <div className={loginButtonVariants()}>Login</div>
+                </Link>
+              </button>
+            )}
+          </div>
+        </div>
+      </header>
+
+      {/* 사이드바 오버레이 (사이드바가 열려있을 때만 표시) */}
+      {sidebarOpen && (
+        <div
+          className={modalOverlayVariants({ type: "sidebar" })}
+          onClick={() => setSidebarOpen(false)}
+        />
+      )}
+
+      {/* 사이드바 (왼쪽에서 슬라이드 인) */}
+      <div className={sidebarVariants({ isOpen: sidebarOpen })}>
+        <div className="p-4">
+          {/* 사이드바 헤더: 제목과 닫기 버튼 */}
+          <div className="flex justify-between items-center">
+            <h2 className="font-sb-24">메뉴</h2>
+            <button className="p-2 cursor-pointer" onClick={() => setSidebarOpen(false)}>
+              <Icon name="close" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+            </button>
+          </div>
+
+          {/* 사이드바 메뉴 항목들 */}
+          <nav className="mt-8">
+            {/* 사이트 제목/로고 */}
+            <h1 className="mb-4">
+              <Link href="/" className={sidebarMenuItemVariants({ type: "title" })}>
+                InterViewer
+              </Link>
+            </h1>
+            {/* 메뉴 항목 목록 (배열에서 동적 생성) */}
+            <ul className="space-y-4">
+              {defaultMenuItems.map((item) => (
+                <li key={item.href}>
+                  <Link href={item.href} className={sidebarMenuItemVariants()}>
+                    {item.name}
+                  </Link>
+                </li>
+              ))}
+            </ul>
+          </nav>
+        </div>
+      </div>
+
+      {/* 검색 모달 (검색 버튼 클릭 시 표시) */}
+      {searchModalOpen && (
+        <>
+          {/* 검색 모달 오버레이 - 클릭하면 모달 닫힘 */}
+          <div
+            className={modalOverlayVariants({ type: "search" })}
+            onClick={() => setSearchModalOpen(false)}
+          />
+
+          {/* 검색 모달 컨텐츠 영역 - 화면 중앙에 배치하고 오버레이와 이벤트 분리 */}
+          <div
+            className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 w-full max-w-2xl px-4 md:px-0"
+            onClick={(e) => e.stopPropagation()}
+          >
+            <div className="bg-white rounded-lg shadow-xl transform transition-all duration-300 scale-100">
+              <div className="p-5">
+                {/* 모달 헤더: 제목과 닫기 버튼 */}
+                <div className="flex items-center justify-between mb-4">
+                  <h2 className="text-xl font-bold">검색</h2>
+                  <button
+                    className="p-1 hover:bg-gray-100 rounded-full transition-colors"
+                    onClick={() => setSearchModalOpen(false)}
+                  >
+                    <svg
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: svg는 Icon컴포넌트로 사용부탁드립니다.
created_at: 2025-05-22T04:29:36Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,12 @@
+// 메뉴 항목 인터페이스
+export interface IMenuItem {
+  name: string;
+  href: string;
+}
+
+// 헤더 컴포넌트 props 인터페이스
+export interface IHeaderProps {
+  isLoggedIn?: boolean;
path: src/app/components/header/header.type.ts
user: login: GiToon10100011
body: 전역상태를 통해 인증관리가 진행됨으로 인해 추후에 해당 인터페이스도 필요가 없어질 것 같습니다. (추후 변경, 일단 병합)
created_at: 2025-05-22T04:30:29Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,83 @@
+import { tv } from "tailwind-variants";
+
+export const headerVariants = tv({
+  base: "border-b border-gray-200",
+  variants: {
+    size: {
+      default: "mx-auto px-4 py-4",
+    },
+  },
+  defaultVariants: {
path: src/app/components/header/header.variants.ts
user: login: GiToon10100011
body: variants에 size만 있는데 불필요한 defaultVariants사용으로 보입니다. 
created_at: 2025-05-22T04:31:00Z
author_association: COLLABORATOR
path: src/app/components/header/header.variants.ts
user: login: GiToon10100011
body: navMenu, createMenu등은 headerVariants내의 variants로 사용해도 되지 않을까요? 리펙토링이 필요할 것 같습니다..! 또한 Button Variants들은 전부 Button 컴포넌트에 이미 정의가 되어있을거라고 판단되어 해당 variants도 필요없을 것 같습니다.
created_at: 2025-05-22T04:32:46Z
author_association: COLLABORATOR
path: src/app/layout.tsx
user: login: GiToon10100011
body: RootLayout에서는 헤더를 넣으면 안됩니다. 그룹 라우팅으로 헤더가 있고 없는 페이지들을 정의했기때문에 그룹 내의 layout.tsx에서 사용될 예정입니다. 테스트는 오직 테스트 페이지에서 부탁드립니다. 
created_at: 2025-05-22T04:33:55Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,315 @@
+"use client";
+import Link from "next/link";
+import React, { useState, useRef, useEffect } from "react";
+import IHeaderProps, { IMenuItem } from "./header.type";
+import {
+  headerVariants,
+  menuButtonVariants,
+  searchButtonVariants,
+  sidebarVariants,
+  modalOverlayVariants,
+  sidebarMenuItemVariants,
+  navMenuVariants,
+  loginButtonVariants,
+  createMenuVariants,
+} from "./header.variants";
+import { Button, buttonVariants } from "../button";
+import { Icon } from "../icon/Icon";
+
+// 사이드바에 표시될 기본 메뉴 항목 데이터
+const defaultMenuItems: IMenuItem[] = [
+  { name: "마이페이지", href: "/mypage" },
+  { name: "빈칸채우기", href: "/fill-blank" },
+  { name: "즐겨찾는 질문들", href: "/favorites" },
+  { name: "오답노트", href: "/wrong-answers" },
+  { name: "인기질문", href: "/popular-questions" },
+  { name: "React", href: "/react" },
+  { name: "JavaScript", href: "/javascript" },
+  { name: "Next.js", href: "/nextjs" },
+  { name: "Node.js", href: "/nodejs" },
+  { name: "Vue", href: "/vue" },
+  { name: "TypeScript", href: "/typescript" },
+];
+
+const Header = ({ isLoggedIn }: IHeaderProps) => {
+  // 상태 관리: 사이드바 및 검색 모달 표시 여부
+  const [sidebarOpen, setSidebarOpen] = useState(false);
+  const [searchModalOpen, setSearchModalOpen] = useState(false);
+  const [createMenuOpen, setCreateMenuOpen] = useState(false);
+  // 검색 입력란에 대한 참조 (포커스 설정에 사용)
+  const searchInputRef = useRef<HTMLInputElement>(null);
+
+  // 네비게이션 메뉴 항목 (PC 화면용)
+  const navMenuItems = [
+    { name: "마이페이지", href: "/mypage" },
+    { name: "빈칸채우기", href: "/fill-blank" },
+    { name: "즐겨찾는 질문들", href: "/favorites" },
+  ];
+
+  // 검색 모달이 열릴 때 자동으로 검색창에 포커스
+  useEffect(() => {
+    if (searchModalOpen && searchInputRef.current) {
+      searchInputRef.current.focus();
+    }
+  }, [searchModalOpen]);
+
+  // ESC 키를 누르면 검색 모달 닫기 (접근성 향상)
+  useEffect(() => {
+    const handleEsc = (event: KeyboardEvent) => {
+      if (event.key === "Escape") {
+        setSearchModalOpen(false);
+      }
+    };
+
+    // 이벤트 리스너 등록 및 클린업
+    window.addEventListener("keydown", handleEsc);
+    return () => {
+      window.removeEventListener("keydown", handleEsc);
+    };
+  }, []);
+
+  // 드롭다운 메뉴가 외부 클릭시 닫히도록 처리
+  useEffect(() => {
+    const handleOutsideClick = (event: MouseEvent) => {
+      const target = event.target as HTMLElement;
+      if (createMenuOpen && !target.closest(".create-menu-container")) {
+        setCreateMenuOpen(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleOutsideClick);
+    return () => {
+      document.removeEventListener("mousedown", handleOutsideClick);
+    };
+  }, [createMenuOpen]);
+
+  return (
+    <>
+      {/* 헤더 영역 */}
+      <header className={headerVariants()}>
+        <div className="mx-auto flex justify-between items-center">
+          {/* 헤더 좌측: 메뉴 버튼, 로고, 네비게이션 */}
+          <div className="flex items-center justify-between gap-4">
+            <div className="flex items-center gap-[8px] md:gap-[12px]">
+              {/* 햄버거 메뉴 버튼 (클릭 시 사이드바 표시) */}
+              <div className={menuButtonVariants()} onClick={() => setSidebarOpen(true)}>
+                <Button
+                  type="button"
+                  className={`${buttonVariants({ color: "white" })} !border-0 px-[0px] py-[0px]`}
+                >
+                  <Icon name="menu" className="w-[30px] h-[30px] md:w-[52px] md:h-[52px]" />
+                </Button>
+              </div>
+              {/* 로고 (홈페이지 링크) */}
+              <Link href="/">
+                <img src="/images/logo.svg" alt="logo" className="w-[77px] h-auto md:w-[133px]" />
+              </Link>
+            </div>
+
+            {/* PC 화면에서만 표시되는 네비게이션 메뉴 (768px 이상) */}
+            <nav className="hidden md:block">
+              <ul className="flex items-center gap-4">
+                {navMenuItems.map((item) => (
+                  <li key={item.href} className={navMenuVariants()}>
+                    <Link href={item.href}>{item.name}</Link>
+                  </li>
+                ))}
+              </ul>
+            </nav>
+          </div>
+
+          {/* 헤더 우측: 검색 버튼, 로그인 */}
+          <div className="flex items-center gap-[12px] md:gap-[29px]">
+            {/* 검색 버튼 (클릭 시 검색 모달 표시) */}
+            <div
+              className={searchButtonVariants({ state: "hover" })}
+              onClick={() => setSearchModalOpen(true)}
+            >
+              <Button type="button" className={`${buttonVariants({ color: "white" })} !border-0`}>
+                <Icon name="search" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+              </Button>
+            </div>
+
+            {isLoggedIn ? (
+              // 로그인 된 상태 - 아이콘 두 개 추가
+              <>
+                <div className="relative create-menu-container">
+                  <button onClick={() => setCreateMenuOpen(!createMenuOpen)}>
+                    <Icon
+                      name="createNew"
+                      className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                    />
+                  </button>
+
+                  {/* 드롭다운 메뉴 */}
+                  {createMenuOpen && (
+                    <div className={createMenuVariants()}>
+                      <ul className="py-2">
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-question" className="block w-full">
+                            질문올리기
+                          </Link>
+                        </li>
+                        <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer font-regular-16">
+                          <Link href="/create-game" className="block w-full">
+                            게임만들기
+                          </Link>
+                        </li>
+                      </ul>
+                    </div>
+                  )}
+                </div>
+                <Link href="/setting">
+                  <Icon
+                    name="setting"
+                    className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
+                  />
+                </Link>
+              </>
+            ) : (
+              // 비로그인 상태 - 로그인 버튼 표시
+              <button>
+                <Link href="#">
+                  <div className={loginButtonVariants()}>Login</div>
+                </Link>
+              </button>
+            )}
+          </div>
+        </div>
+      </header>
+
+      {/* 사이드바 오버레이 (사이드바가 열려있을 때만 표시) */}
+      {sidebarOpen && (
+        <div
+          className={modalOverlayVariants({ type: "sidebar" })}
+          onClick={() => setSidebarOpen(false)}
+        />
+      )}
+
+      {/* 사이드바 (왼쪽에서 슬라이드 인) */}
+      <div className={sidebarVariants({ isOpen: sidebarOpen })}>
+        <div className="p-4">
+          {/* 사이드바 헤더: 제목과 닫기 버튼 */}
+          <div className="flex justify-between items-center">
+            <h2 className="font-sb-24">메뉴</h2>
+            <button className="p-2 cursor-pointer" onClick={() => setSidebarOpen(false)}>
+              <Icon name="close" className="w-[26px] h-[26px] md:w-[33px] md:h-[33px]" />
+            </button>
+          </div>
+
+          {/* 사이드바 메뉴 항목들 */}
+          <nav className="mt-8">
+            {/* 사이트 제목/로고 */}
+            <h1 className="mb-4">
+              <Link href="/" className={sidebarMenuItemVariants({ type: "title" })}>
+                InterViewer
+              </Link>
+            </h1>
+            {/* 메뉴 항목 목록 (배열에서 동적 생성) */}
+            <ul className="space-y-4">
+              {defaultMenuItems.map((item) => (
+                <li key={item.href}>
+                  <Link href={item.href} className={sidebarMenuItemVariants()}>
+                    {item.name}
+                  </Link>
+                </li>
+              ))}
+            </ul>
+          </nav>
+        </div>
+      </div>
+
+      {/* 검색 모달 (검색 버튼 클릭 시 표시) */}
+      {searchModalOpen && (
+        <>
+          {/* 검색 모달 오버레이 - 클릭하면 모달 닫힘 */}
+          <div
+            className={modalOverlayVariants({ type: "search" })}
+            onClick={() => setSearchModalOpen(false)}
+          />
+
+          {/* 검색 모달 컨텐츠 영역 - 화면 중앙에 배치하고 오버레이와 이벤트 분리 */}
+          <div
+            className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 w-full max-w-2xl px-4 md:px-0"
+            onClick={(e) => e.stopPropagation()}
+          >
+            <div className="bg-white rounded-lg shadow-xl transform transition-all duration-300 scale-100">
+              <div className="p-5">
+                {/* 모달 헤더: 제목과 닫기 버튼 */}
+                <div className="flex items-center justify-between mb-4">
+                  <h2 className="text-xl font-bold">검색</h2>
+                  <button
+                    className="p-1 hover:bg-gray-100 rounded-full transition-colors"
+                    onClick={() => setSearchModalOpen(false)}
+                  >
+                    <svg
+                      xmlns="http://www.w3.org/2000/svg"
+                      className="h-6 w-6"
+                      fill="none"
+                      viewBox="0 0 24 24"
+                      stroke="currentColor"
+                    >
+                      <path
+                        strokeLinecap="round"
+                        strokeLinejoin="round"
+                        strokeWidth={2}
+                        d="M6 18L18 6M6 6l12 12"
+                      />
+                    </svg>
+                  </button>
+                </div>
+
+                {/* 검색 입력 필드 (아이콘 포함) */}
+                <div className="relative">
+                  <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+                    <svg
+                      xmlns="http://www.w3.org/2000/svg"
+                      className="h-5 w-5 text-gray-400"
+                      fill="none"
+                      viewBox="0 0 24 24"
+                      stroke="currentColor"
+                    >
+                      <path
+                        strokeLinecap="round"
+                        strokeLinejoin="round"
+                        strokeWidth={2}
+                        d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
+                      />
+                    </svg>
+                  </div>
+                  <input
+                    ref={searchInputRef}
+                    type="text"
+                    className="block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-main focus:border-transparent"
+                    placeholder="검색어를 입력하세요..."
+                  />
+                </div>
+
+                {/* 검색 섹션 */}
+                <div className="mt-4">
+                  <h3 className="text-sm font-medium text-gray-500 mb-2"> 검색어</h3>
+                  <div className="flex flex-wrap gap-2">
+                    <button className="px-3 py-1 bg-gray-100 rounded-full text-sm hover:bg-gray-200 transition-colors">
+                      React
+                    </button>
+                    <button className="px-3 py-1 bg-gray-100 rounded-full text-sm hover:bg-gray-200 transition-colors">
+                      JavaScript
+                    </button>
+                    <button className="px-3 py-1 bg-gray-100 rounded-full text-sm hover:bg-gray-200 transition-colors">
+                      Next.js
+                    </button>
+                    <button className="px-3 py-1 bg-gray-100 rounded-full text-sm hover:bg-gray-200 transition-colors">
+                      TypeScript
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </>
+      )}
+    </>
+  );
+};
+
+export default Header;
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: page.tsx와 같은 테스트 페이지말고는 index.ts를 통한 재 export가 이루어지기 때문에 export default가 아닌 export const Header로 수정 부탁드립니다.
created_at: 2025-05-22T05:06:04Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,12 @@
+// 메뉴 항목 인터페이스
+export interface IMenuItem {
+  name: string;
+  href: string;
+}
+
+// 헤더 컴포넌트 props 인터페이스
+export interface IHeaderProps {
+  isLoggedIn?: boolean;
+}
+
+export default IHeaderProps;
path: src/app/components/header/header.type.ts
user: login: GiToon10100011
body: 여기 부분도 제거 부탁드립니다. 
created_at: 2025-05-22T05:06:27Z
author_association: COLLABORATOR
diff_hunk: @@ -119,27 +117,28 @@ const Header = ({ isLoggedIn }: IHeaderProps) => {
           </div>
 
           {/* 헤더 우측: 검색 버튼, 로그인 */}
-          <div className="flex items-center gap-[12px] md:gap-[29px]">
+          <div className="flex items-center gap-ᆻ md:gap-6">
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: gap 오타가 난것으로 보입니다.
created_at: 2025-05-22T11:18:11Z
author_association: COLLABORATOR
diff_hunk: @@ -160,19 +159,14 @@ const Header = ({ isLoggedIn }: IHeaderProps) => {
                   )}
                 </div>
                 <Link href="/setting">
-                  <Icon
-                    name="setting"
-                    className="w-[26px] h-[26px] md:w-[33px] md:h-[33px] cursor-pointer"
-                  />
+                  <Icon name="setting" className="w-6] h-6 md:w-8 md:h-8 cursor-pointer" />
path: src/app/components/header/Header.tsx
user: login: GiToon10100011
body: 대괄호 오타가 있는것으로 보입니다.
created_at: 2025-05-22T11:18:37Z
author_association: COLLABORATOR
path: src/app/components/header/header.variants.ts
user: login: GiToon10100011
body: 제가 의도 했던건 

```ts
export const headerVariants = tv({
 slots: {
  base: "border-b border-gray-200",
  navMenu: ""font-regular-24 hover:text-main hover:font-sb-24 transition-all",
  createMenu: "absolute right-0 top-full mt-2 w-40 bg-white border border-gray-200 rounded-md shadow-lg z-50 transform origin-top-right transition-all duration-200",
// ...이하
}

 //..variants필요하면 추가
});
```

와 같은 방식으로 리펙토링을 하여, import할거를 최소화 시키고, tailwind-variants가 의도하는 컴포넌트 쪼개는 패턴에 더 맞게 수정을 요청드린거였습니다.  또한 저번 리뷰때 버튼은 어차피 Button컴포넌트에서 variants가 정의되었기에 이에 대한 button 스타일링이 header variants에 필요없을 것 같다고 했는데 유지시킨 이유가 따로 있을까요?
created_at: 2025-05-22T11:23:49Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,12 @@
+// 메뉴 항목 인터페이스
+export interface IMenuItem {
+  name: string;
+  href: string;
+}
+
+// 헤더 컴포넌트 props 인터페이스
+export interface IHeaderProps {
+  isLoggedIn?: boolean;
+}
+
+export default IHeaderProps;
path: src/app/components/header/header.type.ts
user: login: GiToon10100011
body: 이 부분도 제거 부탁드립니다.
created_at: 2025-05-23T01:54:19Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,12 @@
+// 메뉴 항목 인터페이스
+export interface IMenuItem {
+  name: string;
+  href: string;
+}
+
+// 헤더 컴포넌트 props 인터페이스
+export interface IHeaderProps {
+  isLoggedIn?: boolean;
+}
+
+export default IHeaderProps;
path: src/app/components/header/header.type.ts
user: login: mulgko
body: 넵 확인하느라 고생이 많으십니다 화이팅
created_at: 2025-05-23T02:16:02Z
author_association: COLLABORATOR

PR comments:
user: login: GiToon10100011
created_at: 2025-05-25T11:38:58Z
body: 확인해보니 헤더가 position이 fixed, sticky 어느것도 아니어서 스크롤시 안 따라오던데 포지션 수정도 부탁드리겠습니다! 스크롤 시 헤더 접히는걸 추천드리긴했는데 이에 대해 어떻게 생각하시는지에 대한 의견도 함께 물어보고싶습니다

기타 수정사항들은 전부 확인했습니다. 수고하셨습니다.
author_association: COLLABORATOR
user: login: GiToon10100011
created_at: 2025-05-27T04:03:41Z
body: 사이드 메뉴 요소를 더 넣어보고 테스트 결과, 현재 사이드 메뉴 y 스크롤이 발생하고 있지 않습니다. 또한, 사이드바 메뉴의 폰트사이즈도 조금 줄여주시면 감사하겠습니다! 모바일은 수정사항 없어보입니다.
author_association: COLLABORATOR
user: login: mulgko
created_at: 2025-05-27T06:45:36Z
body: > 사이드 메뉴 요소를 더 넣어보고 테스트 결과, 현재 사이드 메뉴 y 스크롤이 발생하고 있지 않습니다. 또한, 사이드바 메뉴의 폰트사이즈도 조금 줄여주시면 감사하겠습니다! 모바일은 수정사항 없어보입니다.

아래와 같이 수정하였습니다! y-scroll과 font크기 조정하였습니다
<img width="286" alt="image" src="https://github.com/user-attachments/assets/fe565061-a4aa-4bb1-94fc-c52834f971fc" />
author_association: COLLABORATOR
user: login: GiToon10100011
created_at: 2025-05-27T07:07:32Z
body: LGTM!
author_association: COLLABORATOR