Skip to content

[회의록] #6

@yoorli

Description

@yoorli

회의 개요

  • 날짜: 2025.12.02(화)
  • 회의 안건
    • SVG 아이콘 처리 방식(SVGR, Turbopack) 정리
    • TanStack Form + Zod 기반 폼·밸리데이션 패턴 논의
    • 재사용 가능한 FormInput 컴포넌트 구조 합의
    • 하단 GNB 탭·URL 네이밍 확정
    • 타이포그래피 유틸·CSS 네이밍 컨벤션 공유
    • Git 머지/배럴 파일, Figma 권한 등 협업 방식 논의

회의 내용 요약

  1. SVG 아이콘 처리
    • 현재 프로젝트는 @svgr/webpack 기반 설정이 이미 들어가 있으며, src 경로 SVG는 컴포넌트로 바로 import하는 방식 유지.
    • public 경로 자산, 스프라이트 사용 여부는 Turbopack·Next 16 환경을 고려해 추가로 조사.
  2. TanStack Form 폼 구조·재사용 전략
    • form 스키마 안에 종속된 필드 컴포넌트는 다른 폼에서 재사용이 사실상 불가하다는 점을 확인.
    • 최종 패턴: 폼별로 form.Field를 사용하고, 공통 UI는 FormInput 같은 프리젠테이셔널 컴포넌트 한 개로 통일해 field만 props로 넘겨 재사용.
  3. Zod + TanStack Form 밸리데이션 & 리렌더링 이슈
    • validators.onChangez.object(...) 스키마를 직접 넘기면, 한 필드에서 에러가 나도 다른 필드까지 불필요하게 리렌더링되는 문제 확인.
    • 해결책: Zod는 각 필드용 함수로만 쓰고, 일반 객체 형태의 validators를 만들어 onChange에 넘기되 z.object는 사용하지 않기로 합의.
  4. 라우팅·GNB 네이밍 정리
    • 하단 네비 탭 이름 및 경로 논의:
      • 2번째 탭: 기존 “캘린더” 대신 Schedule/Schedules 명명으로 정리.
      • 모임 생성: Post 계열 명칭 사용 (/post, /post-meetup 등), 상세는 /meetup/[id] 형태 히든 경로.
      • 채팅: 라우트는 chat보다 messages가 더 자연스럽다고 보고 /messages, /messages/[id] 방향으로 합의.
      • 마지막 탭: GNB는 /mypage (내 정보·설정), 타인 프로필은 /profile/[id] 히든 경로로 분리.
  5. 협업·툴 관련 논의
    • Figma: 여러 사람이 수정하면서 프레임이 틀어질 수 있어, 락·권한 설정 방법 추가로 확인하기로 함.
    • Git/배럴 파일: index.ts 배럴에서 충돌은 피하기 어렵다고 보고, 실제 머지/컴플릭트 경험을 쌓는 방향으로 수용.
    • Storybook: w-full 버튼 컴포넌트는 스토리에서 부모 컨테이너 width를 지정해 미리보기 폭을 제어하는 방식으로 사용.

회의 내용 상세

1. SVG 아이콘 처리 방식

  • 현재:
    • @svgr/webpack을 활용해 src 하위 .svgReact 컴포넌트처럼 import해서 사용하는 구조.
    • 예: import TwitterIcon from '@/assets/twitter.svg' 형태로 바로 JSX에서 <TwitterIcon /> 사용.
  • 논의 내용:
    • public 경로 SVG는 정적 자산이라 동일 방식으로 사용하기 어렵고, 스프라이트 기법 적용 시 Turbopack 환경에서 설정 복잡도가 상승.
    • Next 16부터 Turbopack이 기본 빌드로 승격된 만큼, Webpack 기반 예제 설정을 그대로 가져오기엔 한계가 있어 추가 조사 필요.
  • 결론:
    • 단기: 이미 적용된 SVGR 설정을 유지, src 기준 컴포넌트 import 방식 사용.
    • 중기: Turbopack 공식 SVG/스프라이트 지원 여부·베스트 프랙티스 리서치 후 필요 시 마이그레이션.

2. TanStack Form 구조 및 필드 재사용

  • 문제 인식:
    • TanStack Form에서 스키마를 폼 레벨에 정의하면, 그 안에서 선언한 필드 컴포넌트가 해당 폼 타입에 종속되어 다른 폼에서 재사용이 안 됨.
    • 우리가 원하던 구조는 “NicknameField 하나 만들어서 로그인·회원가입·프로필 수정 등에서 공통으로 쓰기”였으나, 폼에 타입이 갇혀 실패.
  • 검토한 대안:
    • 제네릭 폼 컴포넌트, props 드릴링으로 form 전달 등 여러 패턴을 시도했으나, TanStack Form 타입 지원 한계로 인해 form 객체를 외부로 깔끔하게 빼기 어려움.
  • 최종 패턴:
    • UI와 폼 로직 분리:
      • form.Field name='email' 안에서 render-props로 field를 받고,
      • FormInput 같은 공통 컴포넌트에 fieldlabel, placeholder 등만 넘겨서 사용.
    • 즉, 폼별 필드 선언은 각 페이지에 두되, 시각적 인풋·레이블·에러 UI는 전역 공유 컴포넌트로 재사용하는 구조를 채택.

3. Zod 밸리데이션 & 리렌더링 제어

  • 발견된 이슈:
    • validators.onChange: zodSchema처럼 z.object(...) 스키마를 통째로 넘기면,
      • A 필드에서 에러가 나도 연관 없는 B 필드 컴포넌트까지 함께 리렌더링되는 현상 발생.
    • 동일 이슈가 TanStack Form GitHub 이슈에도 보고되어 있음.
  • 해결책:
    • Zod는 계속 사용하되,
      • const schema = { title: z.string().min(3), ... } 같이 일반 객체 안에 Zod 규칙만 담고,
      • validators.onChange = schema 형태로 넘김. (단 z.object({ ... })는 사용하지 않음).
    • 이 방식이면 해당 필드에서 에러가 발생한 컴포넌트만 리렌더되고, 나머지 필드는 그대로 유지되는 것을 확인.
  • 추가 대안:
    • 각 필드에 validate를 직접 거는 field-level validation도 가능하지만, 모든 필드에 개별로 작성해야 해 관리성이 떨어져 공통 validators 객체 패턴을 우선 사용.

4. 라우팅·GNB 구조 및 네이밍

  • 하단 GNB 탭 구성·네이밍:
    1. 홈: /
    2. 모임 스케줄: Schedule/Schedules (경로 예: /schedule)
    3. 모임 생성: Post 또는 Post meetup (경로 예: /post, /post-meetup)
    4. 채팅: Messages (경로 예: /messages, 상세는 /messages/[id])
    5. 내 정보: My page (경로 예: /mypage)
  • 히든 경로:
    • 모임 상세: /meetup/[id] (목록에는 노출되지 않는 상세 전용 경로).
    • 타인 프로필: /profile/[id] (GNB에는 없고, 리스트/카드에서 링크로 진입).
  • My page vs Profile:
    • *GNB의 마지막 탭은 My page*로, 내 정보·설정·테마 등 편집 기능 포함.
    • /profile/[id]는 누구의 프로필이든 “읽기 전용 뷰”로,
      • 내 아이디로 직접 접근하는 경우에는
        • 리다이렉트로 /mypage로 보내거나,
        • 동일 정보라도 수정 버튼 없는 리드온리 뷰만 제공하는 방향 중 택일.

5. 협업·툴 운영

  • Figma 권한·락:
    • 여러 사람이 동시에 작업하면서 프레임·컴포넌트가 1px씩 어긋나는 등의 문제가 발생할 수 있어,
      • 오너/팀 관리자 권한에서 락·권한 설정 방법을 추가로 찾아보기로 함.
  • Git & 배럴 파일:
    • index.ts에서 barrel export를 여러 명이 만지는 구조라 merge conflict는 필연이라고 보고,
      • 실제 충돌을 겪어 보며 해결 경험을 쌓는 것을 학습 기회로 삼기로 함.
  • Storybook:
    • 버튼이 w-full인 구조로 바뀌면서 스토리 상에서는 폭이 너무 좁게 보이는 이슈 발생.
    • 해결: 스토리에서 부모 컨테이너에 적절한 width를 지정하고, 버튼은 그 안에서 w-full로 채우도록 구성.

정리된 결론 / 후속 액션

  1. SVG 아이콘
    • 현 SVGR 설정 유지, src 기준 컴포넌트 import 사용.
    • Turbopack 환경에서의 스프라이트/아이콘 관리 베스트 프랙티스는 추후 별도 리서치.
  2. 폼·밸리데이션 구조
    • 공통 FormInput 컴포넌트를 shared 단에서 한 번만 정의하고, 모든 페이지 폼에서 재사용.
    • validators.onChange에는 일반 객체 + Zod 함수 조합만 사용하고, z.object 기반 스키마는 사용하지 않도록 컨벤션 확정.
  3. 라우팅 & GNB
    • GNB 탭과 경로를
      • Home(/), Schedules(/schedules), Post(/post or /post-meetup), Messages(/messages), My page(/mypage)로 정리.
    • 모임 상세(/meetup/[id]), 프로필(/profile/[id])은 히든 경로로 운용.
  4. 디자인 시스템·협업
    • 타이포그래피 클래스는 text-display-*, text-text-* 패턴으로 사용.
    • Figma 권한·락 설정, barrel 파일 merge 전략 등은 실제 작업 중 생기는 이슈를 기반으로 추가 룰을 보완해 나가기로 함.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions