Skip to content

Daily1Hour/PickMe-Review-Application

Repository files navigation

면접 회고 마이크로 프론트엔드

Single-Spa Application 구성

🚩 목차

🛠️ 기술 스택

React Vite TypeScript
React-Query React-Router React-Hook-Form Zustand
Chakra-UI Zod
Single-SPA Steiger ESLint

💁 소개

본 서비스는 사용자가 면접 경험을 체계적으로 기록하고, 손쉽게 관리할 수 있도록 다양한 기능을 제공합니다. 면접 준비부터 회고까지의 전 과정을 하나의 플랫폼 내에서 관리할 수 있도록 설계되어, 사용자 스스로 면접 경험을 분석하고 다음 면접을 보다 효과적으로 준비할 수 있도록 지원합니다.

🔗 리뷰 페이지 바로가기
🔗 배포된 통합 웹 사이트 바로가기

새 창 열기 : CTRL+Click (Windows and Linux) / CMD+Click (MacOS)

🎥 데모

Title.-.Chrome.2025-04-24.15-49-50.mp4

💡 주요 기능

주요 기능 내용
면접 회고 추가 면접 정보, 사전 준비, 진행 과정, 질문과 답변, 의사소통, 면접 분석, 다음 면접 준비 등으로 구성된 템플릿을 제공하여 사용자가 면접 경험을 체계적으로 기록할 수 있도록 지원합니다.
면접 회고 조회 사용자가 작성한 면접 회고를 조회할 수 있는 기능을 제공합니다.
면접 회고 수정 사용자가 기존에 작성한 면접 회고의 내용을 수정할 수 있도록 합니다.
면접 회고 삭제 사용자가 작성한 면접 회고를 삭제할 수 있는 기능을 제공합니다.
회고 리스트 사이드바 사용자가 작성한 회고 목록을 화면 좌측 사이드바에 회사명과 면접 유형 형식으로 표출하여, 손쉽게 목록을 확인하고 접근할 수 있도록 합니다.
섹션 바 화면 우측에 위치한 섹션 바를 통해 면접 정보, 사전 준비, 진행 과정, 질문과 답변, 의사소통, 면접 분석, 다음 면접 준비 섹션으로 신속하게 이동할 수 있도록 지원합니다.

🧩 컴포넌트 구성

📘 TypeDoc 문서 보러가기

Image

📊 상태 전이 다이어그램

stateDiagram-v2
    state "ReviewPage" as RP {
        RP/Fetching: Fetching
        RP/Empty: Empty
        RP/Loaded: Loaded
        state if_exist_id <<choice>>
        state if_fetch <<choice>>
        state join_state <<join>>

        [*] --> if_exist_id: useParams()
        if_exist_id --> RP/Fetching: id 있음
        if_exist_id --> RP/Empty: id 없음

        RP/Fetching --> if_fetch: useQuery()
        if_fetch --> RP/Empty: fetch 실패
        if_fetch --> RP/Loaded: fetch 성공

        RP/Empty --> join_state
        RP/Loaded --> join_state

        note right of RP/Fetching
            API를 통해 비동기로 데이터를 패칭해 업데이트
        end note
    }

    state "Zustand Store" as Store {
        Store/Updated: Updated
        Store/Notifier: Notifier

        [*] --> Dispatcher: 상태 초기화<br>setRecord(Empty)
        Dispatcher --> Reducer: 내부 로직 처리
        Reducer --> Store/Updated: 상태 갱신
        Store/Updated --> Store/Notifier: 구독자들에게 알림


    }
    note left of Store
            Flux 방식의 상태저장소
            단방향 데이터 구조
    end note

    state "ReviewForm" as RF {
        RF/Rendering: Rendering
        RF/Submitting: Submitting
        RF/Send: Send

        [*] --> RF/Rendering: 상태 구독<br>useReviewStore()
        RF/Submitting --> RF/Send: 전송<br>useMutation(review)
    }

    state "FormProvider" as FP {
        FP/Updated: Updated
        FP/Notifier: Notifier

        [*] --> FP/Updated: 상태 초기화
        FP/Updated --> FP/Notifier: 구독자들에게 알림
    }

    note left of FP
        react-hook-form의
        폼 상태 컨텍스트 전달자
    end note

    state "ReviewFields" as RFS {
        RFS/InputField: InputField
        [*] --> RFS/InputField

        state RFS/InputField {
            IF/Rendering: Rendering
            IF/Updated: Updated

            [*] --> IF/Rendering: 상태 구독<br>useFormContext()
            IF/Rendering --> IF/Updated: 렌더링 완료
        }
    }

    state "QuestionsAnswers" as QA {
        QA/Rendering: Rendering
        QA/Updated: Updated

        [*] --> QA/Rendering: 상태 구독<br>useFieldArray()
        QA/Rendering --> QA/Updated: 렌더링 완료
    }

    join_state --> Dispatcher: 발송<br>setReview(Data)
    Store/Notifier --> RF/Rendering: 알림<br>review
    FP/Notifier --> RF/Submitting: 제출<br>onSubmit(review)
    FP/Notifier --> IF/Rendering: 알림<br>review
    FP/Notifier --> QA/Rendering: 알림<br>review
    RF/Rendering --> FP/Updated: 폼 갱신<br>useForm(review)
Loading

🚀 실행 방법

$ npm install
$ npm run dev

📂 폴더 구조

PickMe-Review-Application
├─ .env
├─ .env.sample
├─ .env.single-spa
├─ .prettierrc
├─ index.html
├─ package-lock.json
├─ package.json
├─ README.md
├─ setup.ps1
├─ setup.zsh
├─ src
│  ├─ app
│  │  ├─ App.tsx
│  │  ├─ application.tsx
│  │  ├─ main.tsx
│  │  ├─ parcel.tsx
│  │  └─ router.tsx
│  ├─ entities
│  │  └─ review
│  │     └─ model
│  │        └─ review.ts
│  ├─ features
│  │  ├─ review
│  │  │  ├─ api
│  │  │  │  ├─ deleteReviewApi.ts
│  │  │  │  ├─ getReviewApi.ts
│  │  │  │  ├─ index.ts
│  │  │  │  ├─ initialFormData.ts
│  │  │  │  ├─ postReviewApi.ts
│  │  │  │  ├─ putReviewApi.ts
│  │  │  │  └─ reviewDTOList.ts
│  │  │  ├─ hook
│  │  │  │  └─ useReviewMutation.ts
│  │  │  ├─ index.tsx
│  │  │  ├─ schema
│  │  │  │  └─ reviewSchema.ts
│  │  │  ├─ service
│  │  │  │  ├─ dtoToReview.ts
│  │  │  │  └─ reviewToDto.ts
│  │  │  ├─ store
│  │  │  │  └─ useReviewStore.ts
│  │  │  ├─ ui
│  │  │  │  ├─ ActionButton.tsx
│  │  │  │  ├─ DynamicReviewFields.tsx
│  │  │  │  ├─ index.ts
│  │  │  │  ├─ InputField.tsx
│  │  │  │  ├─ InterviewReviewParts.tsx
│  │  │  │  ├─ QuestionsAnswers.tsx
│  │  │  │  ├─ ReviewForm.tsx
│  │  │  │  ├─ ReviewSkeleton.tsx
│  │  │  │  ├─ SectionBar.tsx
│  │  │  │  └─ TextAreaField.tsx
│  │  │  └─ util
│  │  │     ├─ getFieldKeyMap.ts
│  │  │     └─ safeReadDictionary.ts
│  │  └─ side
│  │     ├─ api
│  │     │  ├─ getSideDTO.ts
│  │     │  └─ sideApi.tsx
│  │     ├─ index.tsx
│  │     ├─ store
│  │     │  └─ useSideStore.ts
│  │     └─ ui
│  │        ├─ SearchBar.tsx
│  │        ├─ side.tsx
│  │        └─ SideSkeleton.tsx
│  ├─ pages
│  │  └─ review
│  │     └─ index.tsx
│  └─ shared
│     ├─ api
│     │  ├─ client.ts
│     │  ├─ index.ts
│     │  ├─ router.ts
│     │  └─ tokens.ts
│     ├─ chakra-ui
│     │  ├─ close-button.tsx
│     │  ├─ color-mode.tsx
│     │  ├─ drawer.tsx
│     │  ├─ field.tsx
│     │  └─ provider.tsx
│     └─ data
│        └─ ReviewDict.ts
├─ steiger.config.ts
├─ styleguide-types.d.ts
├─ tsconfig.app.json
├─ tsconfig.json
├─ tsconfig.node.json
├─ typedoc.json
├─ vite-env.d.ts
└─ vite.config.ts

About

면접 회고 마이크로 프론트엔드

Topics

Resources

Stars

Watchers

Forks

Contributors 2

  •  
  •