'use server';// 이 함수 내부의 로직(DB 접근 등)은 절대 클라이언트로 유출되지 않습니다.export async function submitForm(formData: FormData) { const apiKey = process.env.API_KEY; // 서버 환경 변수 await saveToDb(formData, apiKey); return { success: true };}
'use client';import { useOptimistic, useRef } from 'react';import { sendMessage } from './actions';export default function MessageList({ messages }: { messages: string[] }) { // [핵심] useOptimistic 훅 사용 // optimsticMessages: 화면에 보여줄 임시 상태 // addOptimisticMessage: 임시 상태를 추가하는 함수 const [optimisticMessages, addOptimisticMessage] = useOptimistic( messages, (state, newMessage: string) => [...state, newMessage] ); async function action(formData: FormData) { const message = formData.get('message') as string; // 1. 서버 요청을 보내기 전에 화면에 먼저 표시 (낙관적 업데이트) addOptimisticMessage(message); // 2. 실제 서버 요청 (실패 시 React가 알아서 상태를 롤백해 줍니다) await sendMessage(message); } return ( <div> {optimisticMessages.map((m, i) => <div key={i}>{m}</div>)} <form action={action}> <input name="message" /> <button type="submit">Send</button> </form> </div> );}