FrontEnd Develop/Project : Wallet Guardians

프로젝트 Wallet Guardians의 프론트 개발자로서 했던 몇가지 고민 Part #1.

Frisbeen 2025. 2. 17. 19:13

노션에다 틈틈히 정리했던 내용을 포스팅한다.

 

1️⃣ 프론트엔드 개발 과정에서의 고민

📌 디자인과 개발 간의 협업

  • 디자인 설계 → AI 도구 활용 없이 수작업 조정이 많았음
  • 사용자가 봤을때 이쁜것 집중
  • 협업의 효율성을 위해 UI 표준화와 재사용성 향상을 고민

📌 미디어 쿼리와 Sidebar (Navbar) 설계

  • Context API를 활용하여 Sidebar 상태 관리
  • 브라우저를 과도하게 줄였을때 겹쳐진다거나 어색한 부분을 최대한 배제했음.

📌 백엔드와 프론트엔드 간의 진도 차이 해결

  • 백엔드 API 완성 전에 프론트엔드를 개발해야 하는 문제 발생
  • 해결책: JSON Server를 활용한 Mock API 구축 → 백엔드 없이도 개발 가능

📌 공통 레이아웃과 보안 처리 (Navbar, Footer, Header, FriendModal ..etc)

  • 공통 레이아웃 구성:
    • Navbar: 로그인 후 접근 가능한 페이지에서 유지되는 네비게이션 바
    • Footer: 페이지 하단 공통 정보 제공
    • Header: 유저 정보를 표시하는 영역
  • 라우팅에서 보안 처리:
    • 공통 레이아웃을 적용한 AuthenticatedComponent를 생성하여 로그인된 사용자만 특정 페이지에 접근 가능하도록 설정
    • JWT 기반 인증 방식을 적용하여 비인가 사용자의 접근 차단
    • 로그인 여부에 따라 리다이렉트 처리 (예: 로그인하지 않은 사용자가 대시보드 접근 시 로그인 페이지로 이동)

2️⃣ 스타일링 관련 고민

📌 SCSS 선택 이유 (CSS-in-JS 대신)

  • 가독성과 유지보수성: CSS-in-JS 방식보다 스타일 계층 구조 관리가 용이
  • 퍼포먼스 고려: CSS-in-JS는 런타임에서 스타일 생성 → 성능 저하 가능성 존재
  • 팀원 및 장기 유지보수 고려: SCSS가 보다 표준적이고 확장성 높음
  • 그러나… Emotion을 차후 사용할 계획 (참고 블로그)

📌 스타일 재사용 여부

  • 초반에는 불필요한 코드 복잡성 방지를 위해 재사용 최소화
  • 프로젝트 후반부에서는 일관된 UI 유지와 생산성 향상을 위해 공통 스타일 필요성을 느낌

3️⃣ 상태 관리와 최적화

📌 Context API vs Redux 선택

  • 퍼포먼스 이슈: Context API는 깊은 상태 트리에서 불필요한 리렌더링 발생 가능성 존재
  • 그러나 해당 프로젝트에서는 영향이 적어 Redux 대신 Context API 선택 → 간결한 유지보수 가능

📌 useCallback, useMemo 최적화 고민

  • 무조건적인 최적화가 아니라, 필요한 곳에만 적용하는 것이 더 중요
  • 최적화 진행 예정 (컴포넌트가 많아지다 보니, 확실히 약간 서버

📌 상태(state)가 너무 많아져서 가독성이 저하된 문제

  • 프로젝트 진행 중 상태가 점점 많아지면서 관리가 어려워지는 문제 발생
  • 컴포넌트마다 개별적인 useState가 많아져서 코드가 난잡해지고, 상태 흐름을 파악하기 어려워짐

useMemo 적용 대상

연산 비용이 높은 데이터 필터링, 정렬, 계산 로직 (ex. 그래프 데이터 변환, 큰 배열 연산 등)

자주 변경되지 않는 값들을 메모이제이션하여 불필요한 연산 방지

useCallback 적용 대상

불필요한 함수 재생성을 방지하여 성능 향상 (ex. 이벤트 핸들러, API 호출 핸들러 등)

props로 전달되는 콜백 함수가 리렌더링 시 매번 새로 생성되는 문제 해결


4️⃣ API 연동 및 배포 과정의 문제 해결

📌 토큰의 기본적인 개념 파악 - 관련 포스팅 6개 작성

https://wonbin109.tistory.com/99

https://wonbin109.tistory.com/85

https://wonbin109.tistory.com/86

https://wonbin109.tistory.com/87

https://wonbin109.tistory.com/88

https://wonbin109.tistory.com/89

📌 API 호출 방식

  • Axios Instance 활용 → API 호출 패턴 단순화

https://wonbin109.tistory.com/98

  • Vite + CORS 해결을 위해 proxy 설정 적용 (로컬 한정)

📌 Vercel 배포

  • .env 파일을 활용하여 백엔드 API 연동
  • 배포 후에는 Vercel 환경변수 직접 추가 (env는 깃에 push하지 않기에)

📌 예상치 못한 오류와 해결 과정

  • 배포 환경에서만 발생하는 모듈 불러오기 오류
  • 대소문자 문제 (Linux vs Mac OS 차이)
  • 해결법: 문제가 되는 파일 삭제 후 commit + push로 정상화

API 통신 구조 - 삼권분립 원칙

API 통신을 더욱 깔끔하게 하기 위해 3단계 구조를 적용함

https://wonbin109.tistory.com/106

📌 1) API Instance (axios 인스턴스 설정)

  • 공통된 API 요청 형식을 만들기 위해 axios 인스턴스를 따로 설정
  • 기능:
    • 기본 API URL 설정
    • 요청/응답 인터셉터 활용
    • 공통적인 헤더(Authorization 등) 적용

📌 2) API 함수 (실제 API 호출 메서드 분리)

  • 각 API 호출을 함수로 분리하여 관리 (예: userApi.jsx, budgetApi.jsx, expenseApi.jsx 등)
  • 핵심 개념:
    • API 호출을 모듈별로 따로 관리하여 코드 재사용성을 높임
    • 비즈니스 로직과 API 호출 로직을 분리하여 가독성 증가

📌 3) 핸들러 (UI와 API의 연결 담당)

  • 핸들러 함수에서 API 함수를 호출하여 UI와 연결
  • API 호출 성공/실패 시 UI 피드백 처리 (ex. 로딩, 에러 메시지 표시 등)
  • 핵심 개념:
    • API 요청 결과에 따른 상태 업데이트 처리
    • 에러 핸들링을 일관되게 적용 가능

🔹 이러한 삼권분립 구조를 적용하여 API 통신이 깔끔하게 분리되었으며, 유지보수성이 크게 향상됨


5️⃣ 이미지를 제외하고 72개의 파일 .. 너무 많다

  • 프로젝트의 볼륨이 커진 것도 있지만, 개인적으로 재사용을 더욱 더 적극적으로 했으면
  • 디렉토리 정리의 이슈
📦 프로젝트 루트
├── 🎨 App.css
├── ⚛️ App.jsx
├── 📂 IMG  # 이미지 파일 저장소
│   ├── 🖼️ accountingIMG.png
│   ├── 🖼️ backbutton.png
│   ├── 🖼️ receipt1.jpg
│   ├── 🖼️ receipt2.jpg
│   ├── 🖼️ walletGuardians.png
│   ├── 🖼️ walletGuardiansLogo.png
│   └── 🖼️ walletGuardiansLogoReal.png
├── 🌐 api  # API 요청 및 데이터 핸들링
│   ├── 🔗 apiClient.jsx
│   ├── 🔐 authApi.jsx
│   ├── 💰 budgetApi.jsx
│   ├── 📊 expenseApi.jsx
│   ├── 👫 friendApi.jsx
│   ├── 🔑 passwordChangeApi.jsx
│   ├── 🧾 receiptApi.jsx
│   ├── 👤 userApi.jsx
│   ├── ❌ userDeleteApi.jsx
│   └── 📸 userImgApi.jsx
├── 🔒 auth  # 인증 관련 컴포넌트
│   └── 🔑 AuthenticatedComponent.jsx
├── 🏗️ components  # UI 컴포넌트
│   ├── 🦶 Footer.jsx
│   ├── 👫 FriendBtn.jsx
│   ├── 💬 FriendModal.jsx
│   ├── 🌎 GlobalModalMesaage.jsx
│   ├── 🍔 HamburgerBtn.jsx
│   ├── 🏠 Layout.jsx
│   ├── ⏳ LoadingIndicator.jsx
│   ├── 🔄 LoadingSpinner.jsx
│   ├── 🛠️ Navbar.jsx
│   ├── 🚨 ProfileDeleteModal.jsx
│   ├── 🔑 ProfilePwModal.jsx
│   ├── 👤 UserInfo.jsx
│   ├── 🖼️ profileImgModal.jsx
│   └── 🎨 style  # 스타일 관련 파일
│       ├── 📊 IncomeChartStyle.jsx
│       └── 📑 TableStyle.jsx
├── 🌍 context  # 전역 상태 관리 (React Context API)
│   ├── 👫 FriendContext.jsx
│   ├── 🎯 GoalContext.jsx
│   └── 📌 SidebarContext.jsx
├── 🎨 index.css
├── 🚀 main.jsx
├── 📜 pages  # 주요 페이지
│   ├── 📝 BudgetEditModal.jsx
│   ├── 📊 ExpensePage.jsx
│   ├── 👫 FriendAddModal.jsx
│   ├── 🎯 GoalSettingPage.jsx
│   ├── 📉 GraphPage.jsx
│   ├── 💰 IncomePage.jsx
│   ├── 🚀 InitialPage.jsx
│   ├── 📝 InputEntryModal.jsx
│   ├── 📝 InputEntryPage.jsx
│   ├── 🔐 LoginPage.jsx
│   ├── 🏡 MainPage.jsx
│   ├── ❌ NotFoundPage.jsx
│   ├── 👤 ProfilePage.jsx
│   ├── 🧾 ReceiptAddModal.jsx
│   ├── 📸 ReceiptPicPage.jsx
│   ├── ✍️ SignupPage.jsx
│   └── 🚀 StartPage.jsx
└── 🎨 style  # 스타일 파일 (SCSS)
    ├── 🎯 BudgetEditModal.scss
    ├── 🦶 Footer.scss
    ├── 👫 FriendIcon.scss
    ├── 💬 FriendModal.scss
    ├── 🎯 GoalSettingPage.scss
    ├── 📉 GraphPage.scss
    ├── 🍔 HamburgerBtn.scss
    ├── 💰 IncomeExpensePage.scss
    ├── 🚀 InitialPage.scss
    ├── 📝 InputEntryModal.scss
    ├── 📝 InputEntryPage.scss
    ├── 🔐 LoginPage.scss
    ├── 🏡 MainPage.scss
    ├── 🛠️ Navbar.scss
    ├── ❌ NotFoundPage.scss
    ├── 🚨 ProfileDeleteModal.scss
    ├── 🖼️ ProfileImgModal.scss
    ├── 👤 ProfilePage.scss
    ├── 🔑 ProfilePwModal.scss
    ├── 📸 ReceiptPicPage.scss
    ├── ✍️ SignupPage.scss
    └── 🚀 StartPage.scss

6️⃣ 최종 회고: 난 무엇을 느꼈나?

기술 트렌드를 따르는 것도 중요하지만, 프로젝트의 특성과 팀 환경을 고려한 최적의 선택이 필요하다.

  • 소통이 제일 중요했다.
  • 공부할게 정말 많았고 많을 것 같다.
  • 디자인은 심플할 수록 좋다.
  • 프론트엔드가 정말 생각보다 할 일이 많다.
  • 자바스크립트 실력이 매우 중요하다.
  • 건축의 도면을 그리듯 설계 과정이 필요하다. (뭐든)