
Next.js 프로젝트에서 react-hook-form, zod, Supabase를 사용해서 일기 작성 폼을 구현하던 중
폼과 데이터베이스 타입 간 불일치 문제가 발생했다.
그중 `string enum`과 `number` 타입 간 충돌을 타입 변환 처리를 통해 해결한 과정을 정리했다.
문제 상황
수영 일기 작성 흐름은 아래와 같다 :
사용자 입력
↓
React Hook Form (SwimFormData, zod 스키마 검사)
↓
변환 함수 (toSwimLog)
↓
SwimLog 구조로 전환 (중첩 구조 포함)
↓
Supabase 저장 (insertSwimLog), zustand 저장 (setLog)
react-hook-form을 통해 수집된 폼 데이터는 SwimFormData 타입으로 들어오며, 이 타입은 zod로 검증된다.
여기서 lane 필드는 `'25' | '50' | '기타'`중 하나의 문자열(enum)이고,
`'기타'` 선택 시 `customLane` 필드를 통해 사용자가 직접 레인 단위를 입력할 수 있다.
| SwimFormData (React hook form + zod 스키마 검사) |
SwimLog (DB 저장용 타입) |
Supabase 테이블 컬럼 (swim_logs) |
| lane: '25' | '50' | '기타'; customLane?: string; |
lane: number; | lane: integer not null; |
💡 SwimFormData 스키마는 src/ schemas/ logSchema.ts 에서 관리
💡 SwimLog 타입은 src/ types /log.ts 에서 관리
→ time, heartRate, pace 등의 중첩 객체로 구성됨
→ 해당 타입은 폼 데이터를 DB에 저장하는 insertSwimLog 함수에서 사용
오류 발생

하지만 Supabase에 데이터를 저장하는 과정에서 lane 필드의 타입 불일치로 인해 오류가 발생했다.
원인 분석
- `SwimFormData.lane`은 문자열 ('25', '50', '기타')
- `SwimLog.lane` 및 DB 컬럼은 숫자 (integer) 타입
- 변환 함수 `toSwimLog()`에서 lane 값의 타입 변환이 빠짐
- 결과적으로 `insertSwimLog()` 호출 시 타입 오류 발생
해결 방법
타입 불일치를 해결하기 위해 `toSwimLog()` 함수에서 다음과 같이 조건부 변환 로직을 추가했다.
[SwimFormData → SwimLog 구조 변환 함수]
export const toSwimLog = (data: SwimFormData): SwimLog => {
const lane =
data.lane === '기타' && data.customLane
? Number(data.customLane) // 기타 선택 시 사용자 입력값(customLane) 사용
: Number(data.lane); // 나머지는 string → number 변환
return {
date: data.date,
lane,
// ...
};
};
💡 변환 로직 src/ utils / format.ts 에서 관리 중
이제 변환된 lane 값은 SwimLog 타입에 맞게 정상적으로 Supabase 테이블에 저장된다.
결과
- 타입 불일치 오류 해결
- Supabase에 데이터 정상 저장
- 레인 토글 그룹에서 '기타' 선택 시 사용자가 원하는 숫자 레인을 기록할 수 있음
- 타입 시스템에 맞춘 구조 설계의 중요성
회고
타입스크립트의 친절함🙃- 프론트엔드 ↔ 백엔드 간 데이터 스키마 일치는 정말 중요하다!!
- 특히 form 데이터는 문자열이 많기 때문에 중간에서 타입을 변환해 주는 함수(toSwimLog)가 핵심 역할을 함
- 구현 중 `shadcn/ui`를 도입하면서 `Form`컴포넌트가 `react-hook-from`과 `zod` 기반이라는 사실을 알게 되었음
- 나중에 UI 폼 전체를 shadcn/ui 컴포넌트로 리팩토링해보자!
'Insights > Troubleshooting' 카테고리의 다른 글
| [SwimX] Next.js 서버 컴포넌트와 인증 분리로 NextAuth 에러 해결 🛠️ (0) | 2025.04.03 |
|---|---|
| [동네zip] React 모달창 버튼 클릭 오류, 알고 보니 이벤트 버블링?! 🫧 (0) | 2025.03.05 |