Skip to content

2025 덕성여자대학교 컴퓨터공학전공 졸업프로젝트 TopHat 팀 프론트엔드 repo

Notifications You must be signed in to change notification settings

ds-TopHat/TopHat-client

Repository files navigation

🎩 MAPI

2025 덕성여자대학교 컴퓨터공학과 졸업프로젝트 TopHat 팀프론트엔드 레포지토리입니다.

멀티모달 AI 기반 인터랙티브 수학 문제 풀이 서비스

깃1 깃2

본 프로젝트는 멀티모달 AI를 활용하여 학습자의 손글씨 풀이를 실시간 인식·분석하는 인터랙티브 수학 학습 서비스입니다.
문제 이미지를 텍스트로 변환하고, AI가 풀이 과정과 정답을 자동 생성하여 단계별로 안내합니다.

학습자의 풀이 중단 지점을 감지하고, 부족한 개념과 다음 풀이 방향을 맞춤형으로 제공하여
학습자의 논리적 사고력과 자기주도 학습 능력을 효과적으로 지원합니다.

기존 정답 제공 중심 서비스와 달리, 학습자가 막힌 지점에서 맞춤형 피드백과 단계별 해설을 제공하며
문제 해결 과정 전반을 학습할 수 있도록 설계되었습니다.

  • 전체/단계별 풀이
    문제 이미지 또는 문제+풀이 이미지를 업로드하면 AI가 풀이와 단계별 해설 제공

  • 개인 맞춤 학습
    마이페이지에서 질문했던 문제 확인 및 부족한 개념 안내

  • PDF 추출
    풀이 결과를 PDF로 저장하고 복습/공유 가능

🎈 프론트엔드

한수정
@hansoojeongsj

🛠 기술 스택 및 선정 이유 (Tech Stack)

역할 기술 선정 이유
Library React 동적인 사용자 경험과 빠른 인터랙션에 중점을 두고 있기 때문에 CSR 기반으로 작동하며, 초기 렌더링 이후 모든 페이지가 클라이언트에서 동작하도록 설계할 수 있는 SPA 중심 개발을 할 수 있는 리액트를 선택
Programming Language TypeScript 타입을 보장하여 코드의 안정성을 높이고 자동 완성을 통한 유지 보수를 좋게 하기 위해 선택
Styling Vanilla Extract CSS CSS-in-TS 방식으로 타입 안전성을 제공하며, 빌드 시 정적 CSS 추출과 zero-runtime 장점을 활용할 수 있어 선택
Data Fetching Axios TanStack Query Axios: HTTP 요청 처리와 JSON 파싱을 효율적으로 지원하며, 토큰 기반 인증 인터셉터 구현이 용이하여 선택
TanStack Query: 캐싱과 서버 상태 관리 기능을 제공하며, API 요청 규격화를 통해 가독성과 유지보수성을 높이기 위해 선택
Formatting ESLint Prettier 코드 일관성을 유지하고, 가독성을 높이며, 스타일 컨벤션을 통합적으로 관리하기 위해 선택
Package Manager Pnpm 기존에 사용하던 yarn의 node_modules에 패키지가 중복 저장되어 용량이 절감되는 문제를 해결할 수 있으며, 의존성 설치 없이 (zero-install) 사용하게 되면서 빌드와 배포 시간을 크게 단축시켜주어 선택
Version Control Git GitHub 협업 환경에서 버전 관리와 코드 이력을 효율적으로 관리할 수 있어 선택
Deployment Vercel 짧은 기간에 배포하기 위해 러닝 커브가 작고 초기 배포에 적합한 플랫폼이기 때문에 선택

📢 Git/GitHub 컨벤션

Git 브랜치 전략 (GIit Flow)

  1. main(=master) : 오직 배포를 위한 브랜치 → 특별한 상황이 아니라면 배포만 진행
  2. develop : 작업한 내용을 취합하는 곳 (default branch)
  3. feat(=feature) : 각 작업물을 분기해 새로 만들어 사용할 브랜치
git flow

커밋 네이밍 컨벤션

Commit 메시지 종류 설명

제목 내용
feat 퍼블리싱 및 모든 새로운 기능
setting 패키지 설치, 개발 설정
fix 버그 수정
chore 빌드 테스트 업데이트, 패키지 매니저 설정, 그 외 기타 수정
style CSS 등 사용자 UI 디자인 변경
refactor 프로덕션 코드 리팩토링 및 QA 반영
deploy 배포 작업
!HOTFIX 급하게 치명적인 버그 수정
!BREAKING CHANGE 커다란 API 변경


🗂️ 폴더 구조

|-- 📁 node_modules
|-- 📁 public
    |-- 📁 svg
|-- 📁 src
    |-- 📁 shared
      |-- 📁 apis
      |-- 📁 asset
          |-- 📁 svgs
          |-- 📁 images
      |-- 📁 components (공통 컴포넌트)
          |-- 📁 Button (예시 컴포넌트)
              |-- Button.tsx
              |-- Button.style.ts
      |-- 📁 hooks (커스텀 훅을 담아두는 폴더)
      |-- 📁 styles ( global.ts, theme.ts )
      |-- 📁 types
      |-- 📁 utils ( 재사용이 높은 함수모음 폴더 )
          |-- 📁 constants
          |-- 📁 mocks
  |-- 📁 pages
      |-- 📁onboarding
          |-- 📁components
          |-- 📁types
          |-- 📁hooks
          |-- Onboarding.tsx
          |-- Onboarding.style.ts
  |-- 📁 routes
      |-- routePath.ts
      |-- Layout.ts
      |-- pageRoutes.ts
|-- App.tsx
|-- main.tsx
|-- .eslintrc.json
|-- .gitignore
|-- .prettierignore
|-- .prettierrc
|-- README.md
|-- package.json
|-- tsconfig.json
|-- vite.config.ts

📢 네이밍 컨벤션

자세히보기 ### 1. 기본 (Default)
  1. 컴포넌트 / class PascalCase
  2. 폴더명 carmelCase
  3. 파일 명 (컴포넌트 제외) carmelCase
  4. 변수, 함수 carmelCase
  5. 파라미터 carmelCase
  6. 상수 BIG_SNAKE_CASE

2. 타입 (Type)

  1. interface는 필수로 PascalCase 사용
  2. Props 타입 → 컴포넌트명+Types
    • 예시
      interface PostPagePropTypes {
      		title: string | undefined;
      		setTitle: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
      		tempContent: string;
      		editContent: string;
      		setEditorContent: (content: string) => void;
      		setContentWithoutTag: (content: string) => void;
      }
      
      const PostPage = (props: PostPagePropTypes) => {
      		const {title, setTitle, tempContent, editContent, setEditorContent,
      		setContentWithoutTag
      		...
      }
  3. 일반 타입 → … + Types

3. 스타일 (Style)

  1. semantic tag는 적극 활용!
    1. **aria-label**도 적극적으로 활용할 수 있게 노력
  2. SVG 파일 사용시
    1. svgr로 컴포넌트화 후 사용하므로 svg이름을 그대로 변환하여 사용

4. 함수

  1. 이벤트 핸들러 네이밍 handle + 기능 + 이벤트

    • 예시
      const handleBtnClick = () => {};
      const handleTabChange = () => {};

    → props로 넘길 때 key값은 on + 이벤트

    • 예시
      const BoxComponent = () => {
        return <memoComponent onClick={handleBtnClick} />;
      };
  2. 유틸(utils) 함수 네이밍 동사(기능) + 명사(대상)

  3. 값이 boolean일 경우는 is + 상태 (default)

    • 예시
      const [isLogined, setIsLogined] = useState(false);

    → 추가적으로 can / should / has 정도를 상황에 맞게 추가

  4. api 함수 HTTP 메서드 + 명사

    • 예시
      const getList = () => {};
      const getMovie = () => {};

5. 기타

  1. assets (Icon이나 Img)의 경우 피그마 네이밍을 적극 활용

    Ic + 피그마 네이밍 (icon의 경우)으로 사용

  2. URL, HTML 같은 범용적인 대문자 약어는 대문자 그대로 사용

  3. 변수/최대한 직관적으로 작성하여 네이밍을 보고도 무슨 데이터, 행위인지 바로 유추할 수 있도록 작성

    • 주석이 필요한 경우에는 어떤 역할을 하는지 다른 사람이 이해할 수 있도록 작성
    • 변수/함수 명은 20자 미만, 주석으로 변수 설명
  4. 주석은 작성하려고 하는 대상 바로 위에 작성



📢 개발 컨벤션

자세히보기 ### 변수
  • var 금지
  • constlet 순서로 위부터 선언
  • 변수를 조합하여 문자열 생성시 “+ “ 금지. → 리터럴 사용(백틱 ```)
  • 변수명 : 의미를 확실히 나타낼 수 있도록
    • 예시 : 배열에 Arr 보다는 변수s = fruits, userlists 등등
  • 줄임말 쓰지말기. 이름이 길어지더라도 어떤 변수인지 정확하게
    • 예시 : Btn X → Button으로 사용
  • map 사용시 변동되는 리스트라면 key값을 고유하게 잘 설정해주기 index 사용 금지
    • 서버에서 내려주는 id값 or uuid 사용
  • 전역 변수는 되도록 사용하지 않기

함수

  • 화살표 함수 사용, function 키워드 사용하지 않기
  • 중복함수는 utils 폴더에 모아서 재사용할 수 있도록 노력
  • 변수/함수 명은 20자 미만
    • 최대한 네이밍에 의미를 담아서 작성하고 필요 시에 주석으로 설명 추가
  • 필요하다면 early return 패턴을 적극적으로 활용
    • 예시
      **// early return 패턴**
      function processUser(user) {
        if (!user || !user.isActive) return; // **조건이 맞지 않으면 일찍 반환**
        // 나머지 처리 코드...
      }

컴포넌트

  • rafce → 고정
  • 의미없는 div 또는 컴포넌트 최상단은 fragment 사용
const InfoText = () => {
  return (
    <>
      <h1>Welcome!</h1>
      <p>This our new page, we're glad you're are here!</p>
    </>
  );
};
  • children이 불필요할 땐 selfClosing사용 <Component/>
  • children 적극적으로 활용

타입

  • object → interface
  • 단일 변수 → type alias
  • 컴포넌트 인자에 대한 타입은 컴포넌트 상단에
  • 그 외의 타입들은 types 폴더에
  • api response 타입명은 OOOResponseTypes

메소드

  • 배열 복사 시 → 스프레드 연산자(…) 사용

    • const copys = […originals]
  • for 보단, forEach/map을 사용

  • 구조 분해 할당을 적극 이용

    interface userDataProps {
      userName: string;
      userBirth: string;
    }
    
    function checkIsUser({ userName, userBirth }: userDataProps) {}
  • 불필요한 반복문 지양 : filter, array.include() 등

    • 조건부로 데이터를 확인하거나 뽑아야하는 로직을 사용할 때에는 Map 이나 Object처럼 key값을 이용해서 원소를 찾는 자료형을 이용하는것을 고려해보거나, 배열을 순회하지 않고 index로 바로 접근할 수 있는 방법이 없는지 고려

Style

mozila 추천 css 순서 (참고)

기타

  • button 태그에 **type**은 명시적으로 작성

  • 비교 연산자는 **===**와 **!==**만을 사용

  • axios 안에서 then/catch 대신 async/await 지향

About

2025 덕성여자대학교 컴퓨터공학전공 졸업프로젝트 TopHat 팀 프론트엔드 repo

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published