액션(Action): 데이터 변경 처리하기
액션(Action): 데이터 변경 처리하기
라우트에서 데이터를 읽는 건 로더가 맡는다면, 데이터를 바꾸는 일은 액션(action)이 맡아요. 액션은 서버 전용 함수로, 데이터 변경(mutation)과 그 밖의 동작을 처리해요. 라우트에 GET이 아닌 요청(DELETE, PATCH, POST, PUT)이 들어오면 로더가 호출되기 전에 액션이 먼저 불려요. 재미있는 점은 액션이 로더와 API가 똑같다는 거예요 — 호출되는 시점만 다를 뿐이죠.
데이터 읽기·쓰기·그리기를 한 파일에
액션이 로더와 같은 API를 쓰기 때문에, 한 데이터셋에 관한 모든 것을 하나의 라우트 모듈에 함께 둘 수 있어요. 데이터를 읽는 로더, 그 데이터를 그리는 컴포넌트, 데이터를 쓰는 액션이 한곳에 모이는 거죠.
import type { ActionFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json, redirect } from "@remix-run/node"; // or cloudflare/deno
import { Form } from "@remix-run/react";
import { TodoList } from "~/components/TodoList";
import { fakeCreateTodo, fakeGetTodos } from "~/utils/db";
export async function action({ request }: ActionFunctionArgs) {
const body = await request.formData();
const todo = await fakeCreateTodo({
title: body.get("title"),
});
return redirect(`/todos/${todo.id}`);
}
export async function loader() {
return json(await fakeGetTodos());
}
export default function Todos() {
const data = useLoaderData<typeof loader>();
return (
<div>
<TodoList todos={data} />
<Form method="post">
<input type="text" name="title" />
<button type="submit">Create Todo</button>
</Form>
</div>
);
}
<Form method="post">로 폼을 제출하면 POST 요청이 해당 라우트로 가고, 액션이 request.formData()로 제출된 값을 읽어 새 데이터를 만들고, 완료되면 redirect로 목록 페이지로 보내는 흐름이에요.
액션은 어느 라우트로 가는가
URL에 POST가 일어날 때, 라우트 계층에서 여러 라우트가 그 URL과 매칭돼요. 하지만 GET 로더와 달리(로더는 화면을 그리려고 전부 호출되죠) 액션은 하나만 호출돼요. 매칭된 라우트 중 가장 깊은 라우트가 호출되는데, 그 깊은 라우트가 index 라우트면 예외가 있어요. index 라우트와 부모는 같은 URL을 공유하니까, 이 경우엔 부모 라우트로 POST가 가요.
index 라우트에 POST를 보내고 싶다면 액션 URL에 ?index를 쓰면 돼요. <Form action="/accounts?index" method="post" />처럼요.
| action url | 라우트 액션 |
|---|---|
/accounts?index |
app/routes/accounts._index.tsx |
/accounts |
app/routes/accounts.tsx |
그리고 action prop이 없는 폼(<Form method="post">)은 자신이 렌더링된 같은 라우트로 자동으로 POST돼요. 그래서 ?index 파라미터로 부모·index 라우트를 구분할 필요가 있는 건, index 라우트가 아닌 다른 곳에서 index 라우트로 보낼 때뿐이에요. 자기 자신으로 보낼 땐 <Form action>을 아예 생략해도 돼요.
더 알아보기
- 공식 문서 (1차): Remix — action, Remix — Form
- 관련 문서: 로더 · 데이터 로딩 · 라우팅