Skip to content
/ workroot Public

FE9-2νŒ€) 🌳 "일"을 톡해 μžμ‹ μ˜ 뿌리λ₯Ό 내리며 "μ„±μž₯"ν•˜λŠ” ꡬ인ꡬ직 μ‚¬μ΄νŠΈ

License

Notifications You must be signed in to change notification settings

FE9-2/workroot

Repository files navigation

μ½”λ“œμž‡ ν”„λ‘ νŠΈμ—”λ“œ 9κΈ° 2νŒ€ μ›Œν¬λ£¨νŠΈ(WorkRoot) ν”„λ‘œμ νŠΈ

배포 μ‚¬μ΄νŠΈ: https://www.workroot.life

ν”„λ‘œμ νŠΈ μ†Œκ°œ

  • WorkRoot μ†Œκ°œ: 🌳 "일"을 톡해 μžμ‹ μ˜ 뿌리λ₯Ό 내리며 "μ„±μž₯"ν•˜λŠ” ꡬ인ꡬ직 μ‚¬μ΄νŠΈ
  • 개발 κΈ°κ°„: 2024. 11. 21 ~ 2024. 12. 30
  • 개발 인원: 4λͺ…
김원 κΉ€μ˜ˆμ§€ κΉ€νƒœμ€€ ν™μ˜ˆλ¦Ό
cccwon2 yyezzzy imtaejunk hongggyelim
  • μ—­ν• 
    • 김원: νŒ€μž₯, λ ˆν¬μ§€ν† λ¦¬ μ„ΈνŒ…, 둜그인/νšŒμ›κ°€μž…, λ§ˆμ΄νŽ˜μ΄μ§€, 곡고 λͺ©λ‘ νŽ˜μ΄μ§€, κ²Œμ‹œνŒ λͺ©λ‘ νŽ˜μ΄μ§€, 곡고 μΉ΄λ“œ μ»΄ν¬λ„ŒνŠΈ, λͺ¨λ‹¬ μ»΄ν¬λ„ŒνŠΈ, SEO μ„€μ •, 지도 API 연동, Supabase 연동, 회의둝 μž‘μ„±
    • κΉ€μ˜ˆμ§€: μ†Œμ…œλ‘œκ·ΈμΈ/νšŒμ›κ°€μž…, μ•Œλ°”νΌ μƒμ„ΈνŽ˜μ΄μ§€, 둜고, λžœλ”©νŽ˜μ΄μ§€ λ””μžμΈ 및 기획, 곡톡 λ²„νŠΌ μ»΄ν¬λ„ŒνŠΈ, μŠ€ν† λ¦¬λΆ μ„ΈνŒ…, ν¬λ‘œλ§€ν‹± 배포 μ„ΈνŒ…
    • κΉ€νƒœμ€€: λžœλ”© νŽ˜μ΄μ§€, κ²Œμ‹œνŒ 상세 νŽ˜μ΄μ§€, κ²Œμ‹œνŒ μΉ΄λ“œ μ»΄ν¬λ„ŒνŠΈ, μ „μ—­ μ—λŸ¬ νŽ˜μ΄μ§€, 404 νŽ˜μ΄μ§€
    • ν™μ˜ˆλ¦Ό: 곡고 μž‘μ„± νŽ˜μ΄μ§€, 곡고 μˆ˜μ • νŽ˜μ΄μ§€, 곡톡 인풋 μ»΄ν¬λ„ŒνŠΈ, 데이터피컀 μ»€μŠ€ν…€, 마우슀 μ»€μ„œ μ»€μŠ€ν…€, κΉƒν—™ μ•‘μ…˜ CI μ„ΈνŒ…

기술 μŠ€νƒ

μ£Όμš” μ˜μ‘΄μ„±

Next.js React TypeScript TailwindCSS

μƒνƒœ 관리 & 데이터 페칭

React Query Zustand Axios Supabase

폼 & μœ νš¨μ„± 검사

React Hook Form Zod HookForm Resolvers

UI/UX

Framer Motion React DatePicker React Icons React Hot Toast Yet Another React Lightbox Hello Pangea DnD

지도 & μ†Œμ…œ

React Kakao Maps SDK Next Auth Channel Talk

개발 도ꡬ

ESLint Prettier Storybook React Query DevTools

개발 ν™˜κ²½ μ„€μ •

ESLint μ„€μ •

{
  "extends": [
    "next",
    "next/core-web-vitals",
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier"
  ],
  "plugins": ["@typescript-eslint", "prettier"],
  "parser": "@typescript-eslint/parser",
  "rules": {
    "import/no-anonymous-default-export": "off",
    "@typescript-eslint/no-explicit-any": "off",
    "prettier/prettier": [
      "error",
      {
        "endOfLine": "lf"
      }
    ],
    "linebreak-style": ["error", "unix"],
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": "warn"
  }
}

Prettier μ„€μ •

{
  "printWidth": 120, // ν•œ μ€„μ˜ μ΅œλŒ€ 길이λ₯Ό 120자둜 μ œν•œ
  "tabWidth": 2, // λ“€μ—¬μ“°κΈ° μ‹œ μ‚¬μš©ν•  곡백 문자 수
  "useTabs": false, // νƒ­ 문자 λŒ€μ‹  곡백 문자 μ‚¬μš©
  "semi": true, // λ¬Έμž₯ 끝에 μ„Έλ―Έμ½œλ‘  μΆ”κ°€
  "singleQuote": false, // λ¬Έμžμ—΄μ— μž‘μ€λ”°μ˜΄ν‘œ λŒ€μ‹  ν°λ”°μ˜΄ν‘œ μ‚¬μš©
  "quoteProps": "as-needed", // 객체 속성에 λ”°μ˜΄ν‘œ μ‚¬μš© 방식 (ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©)
  "trailingComma": "es5", // 객체, λ°°μ—΄ λ“±μ˜ λ§ˆμ§€λ§‰ ν•­λͺ© 뒀에 μ‰Όν‘œ μΆ”κ°€
  "bracketSpacing": true, // 객체 λ¦¬ν„°λŸ΄μ˜ κ΄„ν˜Έ 사이에 곡백 μΆ”κ°€
  "arrowParens": "always", // ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό 항상 κ΄„ν˜Έλ‘œ 감싸기
  "proseWrap": "preserve", // λ§ˆν¬λ‹€μš΄ ν…μŠ€νŠΈμ˜ μ€„λ°”κΏˆ 처리 방식
  "endOfLine": "lf", // 쀄 끝 문자λ₯Ό LF(Line Feed)둜 톡일
  "plugins": [
    "prettier-plugin-tailwindcss" // Tailwind CSS 클래슀 μžλ™ μ •λ ¬ ν”ŒλŸ¬κ·ΈμΈ
  ]
}

TailwindCSS μ„€μ •

import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
    "./stories/**/*.{js,ts,jsx,tsx}",
    "./src/app/globals.css",
    "./src/stories/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      colors: {
        foreground: "var(--foreground)",
        black: {
          100: "#6B6B6B",
          200: "#525252",
          300: "#373737",
          400: "#1F1F1F",
          500: "#040404",
        },
        grayscale: {
          50: "#FFFFFF",
          100: "#DEDEDE",
          200: "#C4C4C4",
          300: "#ABABAB",
          400: "#999999",
          500: "#808080",
        },
        primary: {
          orange: {
            50: "#fbfffd",
            100: "#8ab08c",
            200: "#64a466",
            300: "#388e3c",
            400: "#156719",
          },
          blue: {
            100: "#535779",
            200: "#3E415B",
            300: "#2A2C3D",
          },
        },
        background: {
          100: "#FCFCFC",
          200: "#F7F7F7",
          300: "#EFEFEF",
        },
        line: {
          100: "#F2F2F2",
          200: "#E6E6E6",
        },
        state: {
          error: "#FC4100",
        },
      },
      fontFamily: {
        nexon: ["var(--font-nexon)", "sans-serif"],
        hakgyo: ["var(--font-hakgyo)", "sans-serif"],
        sans: ["Pretendard", "sans-serif"],
      },
    },
  },
};

export default config;

μ‹œμž‘ν•˜κΈ°

  1. μ €μž₯μ†Œ 클둠:
git clone [repository-url]
  1. ν™˜κ²½ λ³€μˆ˜ μ„€μ •: ν”„λ‘œμ νŠΈ λ£¨νŠΈμ— .env νŒŒμΌμ„ μƒμ„±ν•˜κ³  λ‹€μŒ λ‚΄μš©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€:
# ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ
NEXT_PUBLIC_API_URL=your-api-url
NEXT_PUBLIC_TEAM_ID=your-team-id

# μ„œλ²„ μ‚¬μ΄λ“œ
CHROMATIC_PROJECT_TOKEN=your-chromatic-project-token

# 도메인
NEXT_PUBLIC_DOMAIN_URL=your-domain-url

# ν…ŒμŠ€νŠΈ 계정(μ§€μ›μž)
NEXT_PUBLIC_TEST_APPLICANT_ID=your-test-applicant-id
NEXT_PUBLIC_TEST_APPLICANT_PASSWORD=your-test-applicant-password

# ν…ŒμŠ€νŠΈ 계정(사μž₯λ‹˜)
NEXT_PUBLIC_TEST_OWNER_ID=your-test-owner-id
NEXT_PUBLIC_TEST_OWNER_PASSWORD=your-test-owner-password

# 페이슀뢁
NEXT_PUBLIC_FB_APP_ID=your-facebook-app-id

# 카카였맡
NEXT_PUBLIC_KAKAO_APP_KEY=your-kakao-app-key

# 수파베이슀
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key

# 카카였 ν΄λΌμ΄μ–ΈνŠΈ 아이디
NEXT_PUBLIC_KAKAO_CLIENT_ID=your-kakao-client-id

# ꡬ글 ν΄λΌμ΄μ–ΈνŠΈ 아이디
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-google-client-id

# 채널톑 ν”ŒλŸ¬κ·ΈμΈ ν‚€
NEXT_PUBLIC_CHANNEL_IO_PLUGIN_KEY=your-channel-io-plugin-key

# ꡬ글 μ• λ„λ¦¬ν‹±μŠ€
NEXT_PUBLIC_GA_ID=your-google-analytics-id
  1. μ˜μ‘΄μ„± μ„€μΉ˜:
npm install
  1. 개발 μ„œλ²„ μ‹€ν–‰:
npm run dev

ν”„λ‘œμ νŠΈ ꡬ쑰

src/
β”œβ”€β”€ app/                    # Next.js 14+ App Router
β”‚   β”œβ”€β”€ (auth)/            # 인증 κ΄€λ ¨ 라우트 (둜그인, νšŒμ›κ°€μž…)
β”‚   β”œβ”€β”€ (home)/            # ν™ˆ νŽ˜μ΄μ§€ κ΄€λ ¨ 라우트
β”‚   β”œβ”€β”€ (pages)/           # μ£Όμš” νŽ˜μ΄μ§€ 라우트
β”‚   β”‚   β”œβ”€β”€ (workform)/    # μ›Œν¬νΌ κ΄€λ ¨ νŽ˜μ΄μ§€
β”‚   β”‚   β”œβ”€β”€ my-workform/   # 마이 μ›Œν¬νΌ νŽ˜μ΄μ§€
β”‚   β”‚   └── work-talk/     # μ›Œν¬ν†‘ κ²Œμ‹œνŒ νŽ˜μ΄μ§€
β”‚   └── components/        # 곡톡 μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ animation/     # μ• λ‹ˆλ©”μ΄μ…˜ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ button/        # λ²„νŠΌ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ card/          # μΉ΄λ“œ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ chip/          # μΉ© μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ input/         # μž…λ ₯ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ layout/        # λ ˆμ΄μ•„μ›ƒ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”œβ”€β”€ loading-spinner/ # λ‘œλ”© μŠ€ν”Όλ„ˆ μ»΄ν¬λ„ŒνŠΈ
β”‚       └── pagination/    # νŽ˜μ΄μ§€λ„€μ΄μ…˜ μ»΄ν¬λ„ŒνŠΈ
β”œβ”€β”€ constants/             # μƒμˆ˜ μ •μ˜
β”œβ”€β”€ hooks/                 # μ»€μŠ€ν…€ ν›…
β”‚   └── queries/          # React Query κ΄€λ ¨ ν›…
β”œβ”€β”€ lib/                   # μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
β”œβ”€β”€ schemas/              # Zod μŠ€ν‚€λ§ˆ μ •μ˜
β”œβ”€β”€ store/                # μƒνƒœ 관리 (Zustand)
β”œβ”€β”€ types/                # TypeScript νƒ€μž… μ •μ˜
└── utils/                # μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜

λΌμ΄μ„ μŠ€

이 ν”„λ‘œμ νŠΈλŠ” MIT λΌμ΄μ„ μŠ€λ₯Ό λ”°λ¦…λ‹ˆλ‹€.

License: MIT

About

FE9-2νŒ€) 🌳 "일"을 톡해 μžμ‹ μ˜ 뿌리λ₯Ό 내리며 "μ„±μž₯"ν•˜λŠ” ꡬ인ꡬ직 μ‚¬μ΄νŠΈ

Topics

Resources

License

Stars

Watchers

Forks