'use server'; import { unstable_rethrow } from 'next/navigation'; import { revalidatePath } from 'next/cache'; import { verifySession } from '@/lib/auth/dal'; import { createMerchant } from '@/lib/data/repositories/merchant-repository'; import { validateMerchant, type MerchantFormState, } from '@/lib/domain/merchant-form'; import { MERCHANTS_PATH } from '@/lib/domain/merchant-query'; const SAVE_FAILED_MESSAGE = '저장하지 못했습니다. 잠시 후 다시 시도해 주세요.'; function readString(formData: FormData, key: string): string { const value = formData.get(key); return typeof value === 'string' ? value : ''; } export async function saveMerchantAction( _prevState: MerchantFormState, formData: FormData ): Promise { await verifySession(); const validation = validateMerchant({ id: readString(formData, 'id'), brandName: readString(formData, 'brandName'), memo: readString(formData, 'memo'), name: readString(formData, 'name'), categoryCode: readString(formData, 'categoryCode'), businessNumber: readString(formData, 'businessNumber'), ownerName: readString(formData, 'ownerName'), phoneNumber: readString(formData, 'phoneNumber'), address: readString(formData, 'address'), addressDetail: readString(formData, 'addressDetail'), postalCode: readString(formData, 'postalCode'), latitude: readString(formData, 'latitude'), longitude: readString(formData, 'longitude'), isVisible: readString(formData, 'isVisible') === 'Y', }); if (!validation.ok) { return { status: 'error', errors: validation.errors }; } // TODO(백엔드): 수정 API가 없다(`/api/v1/mngr/voc`는 목록·등록 둘뿐). 생기면 여기서 가른다. try { await createMerchant(validation.values); } catch (error) { // 이슈: 세션이 밀렸을 때 backendFetch가 던지는 redirect를 이 catch가 삼키면 안 된다. unstable_rethrow(error); return { status: 'error', message: SAVE_FAILED_MESSAGE }; } revalidatePath(MERCHANTS_PATH); return { status: 'success' }; }