Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- reliability
- frontend
- 버전관리
- version-control
- CI
- architecture
- database
- Operations
- Kubernetes
- Microservices
- Debugging
- aws
- JavaScript
- Performance
- auth
- Infra
- Ops
- web
- Security
- backend
- 성능
- HTTP
- observability
- API
- DevOps
- CSS
- NextJS
- SRE
- react
- Git
Archives
- Today
- Total
고민보단 실천을
Next.js Server Actions 실전: 폼 처리, 에러 처리, 중복 제출 방지 패턴 본문
Next.js Server Actions 실전: 폼 처리, 에러 처리, 중복 제출 방지 패턴
Server Actions는 API 라우트 없이 서버에서 mutation을 처리할 수 있어 검색 수요가 빠르게 늘고 있습니다. 실무에서 중요한 건 폼 에러를 안정적으로 보여주고, 중복 제출을 막고, 권한 체크를 서버에서 확실히 하는 것입니다.
옵션/핵심 요소(3~6개)
| 항목 | 의미 | 언제 쓰는지(실무 상황) |
|---|---|---|
'use server' | 서버 실행 표시 | DB 접근/비밀키 사용을 action으로 이동 |
| 서버 검증 | 최종 입력 검증 | 클라 검증은 UX, 서버 검증은 보안/정합성 |
useActionState | 에러/상태 관리 | 필드 에러/전역 에러를 안정적으로 렌더링 |
| 중복 제출 방지 | 동시 실행 제어 | 버튼 disable + 서버 idempotency 조합 |
| 권한 체크 | 인증/인가 | action도 API처럼 권한 체크가 필요 |
예시 코드
// app/posts/[id]/actions.ts
'use server'
type ActionState = { ok: boolean; message?: string }
export async function createComment(prev: ActionState, formData: FormData): Promise<ActionState> {
const postId = String(formData.get('postId') || '')
const body = String(formData.get('body') || '')
if (!postId || body.trim().length < 2) return { ok: false, message: '댓글을 2자 이상 입력하세요.' }
// TODO: 인증/인가 체크
// TODO: DB 저장
return { ok: true }
}
// app/posts/[id]/comment-form.tsx
import { useActionState } from 'react'
import { createComment } from './actions'
export function CommentForm({ postId }: { postId: string }) {
const [state, action, pending] = useActionState(createComment, { ok: false })
return (
<form action={action}>
<input type='hidden' name='postId' value={postId} />
<textarea name='body' />
<button type='submit' disabled={pending}>등록</button>
{state.message ? <p>{state.message}</p> : null}
</form>
)
}문제 상황(정확히 1개)
상황: 버튼을 두 번 누르면 동일 요청이 두 번 처리되어 데이터가 2번 생성된다
원인: 클라이언트 disable만으로는 네트워크 재시도/중복 요청을 완전히 막지 못하고, 서버가 idempotency를 제공하지 않는다
해결: 클라이언트는 pending 동안 submit을 막고, 서버는 유니크 제약 또는 idempotency 키로 중복을 차단한다
예방 팁: Server Actions도 '중복/권한/검증'을 API 수준으로 설계하고, 중복 요청 시나리오를 테스트 케이스로 포함한다
참고/출처
Comments
