블로그 릴레이 - Amplify Gen2 + React로 CRUD 구축해 보기
안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다.
본 블로그는 당사의 한국어 블로그 릴레이의 열한 번째 블로그입니다.
이번 블로그는 이전 작성한 「Amplify Gen2 + React 인증 기능까지 심플 구축해 보기」에 이어서
「Amplify Gen2 + React로 CRUD 구축해 보기」를 주제로 작성해 보았습니다.
Frontend Backend 추가
Frontend와 Backend 리소스 추가에 대해서는 이전 작성한 블로그를 참고해 주세요.
CRUD 구축
STEP1.
코드는 이전 블로그에서 이어서 작성해 보겠습니다.
이전에 작성해둔 Data 리소스에 아래의 코드를 추가해줍니다.
amplify/data/resource.ts
const schema = a.schema({
Todo: a
.model({
title: a.string(),
content: a.string(),
})
.authorization((allow) => [allow.publicApiKey()]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'apiKey',
apiKeyAuthorizationMode: { expiresInDays: 30 }
}
});
그 후 아래 커맨드를 통해 리소스를 생성해 줍니다.
npx ampx sandbox
실행이 완료된 후 AWS 콘솔에서 확인해 보시면 내부적으로는 AppSync 와 DynamoDB가 생성된 것을 확인할 수 있습니다.
실제 Amplify Gen2 - Set up Amplify Data의 설명을 보면
This API is powered by AWS AppSync and connected to an Amazon DynamoDB database.
와 같이 AppSync와 DynamoDB를 통해 구성된다는 것을 확인할 수 있습니다.
추가로 인증을 커스텀을 하고 싶은 경우에는 아래 Document를 참고해 주세요.
Amplify Gen2 - Customize your auth rules
기본적으로 아래의 설명으로 볼 때 아무 설정이 없다면 API가 거부되는 듯합니다.
Authorization rules operate on the deny-by-default principle
STEP2.
그럼 간단하게 CRUD를 만들어보겠습니다.
App.tsx
...
import { Schema } from "../amplify/data/resources";
Amplify.configure(config);
const client = generateClient<Schema>();
function Todos() {
const [todos, setTodos] = useState<Schema>([]);
const [loading, setLoading] = useState(true);
const fetchTodos = useCallback(async () => {
const { data } = await client.models.Todo.list();
setLoading(false);
setTodos(data);
}, []);
const createTodo = useCallback(async () => {
const { data } = await client.models.Todo.create({
title: "new todo title",
content: "new todo content",
});
setTodos([...todos, data]);
}, [todos]);
const deleteTodo = useCallback(
async (id: string) => {
await client.models.Todo.delete({
id,
});
setTodos(todos.filter((todo: Schema) => todo.id !== id));
},
[todos]
);
const updateTodo = useCallback(
async (id: string) => {
const { data } = await client.models.Todo.update({
id,
title: "updated title",
content: "updated content",
});
setTodos(
todos.map((todo: Schema) => {
if (todo.id === id) return data;
return todo;
})
);
},
[todos]
);
useEffect(() => {
fetchTodos();
}, [fetchTodos]);
if (loading) return <div>...loading</div>;
return (
<div>
<button onClick={createTodo}>new todo</button>
{todos.map((todo: Schema) => (
<div key={todo.id}>
<p>{todo.id}</p>
<p>{todo.title}</p>
<p>{todo.content}</p>
<button onClick={() => deleteTodo(todo.id)}>delete</button>
<button onClick={() => updateTodo(todo.id)}>update</button>
</div>
))}
</div>
);
}
function App() {
return (
<Authenticator>
{({ signOut, user }) => (
...
<Todos />
...
이상으로 간단한 CRUD를 구축해 보았습니다.
추가로 위의 코드에서는 에러 핸들링과 같은 처리를 넣지 않았습니다만,
혹시 에러 핸들링을 구현해 보고 싶으시다면 GraphQL의 에러 핸들링에 대해서 알아보시면 좋을 것 같습니다.
AppSync의 경우에는 내부적으로 GraphQL을 활용하고 있습니다.
AppSync의 경우 errors 배열을 통해 에러 메세지를 받게 되므로 아래와 같은 구조가 필요하게 됩니다.
추가로 적으로 서버 에러의 경우에는 마찬가지로 Catch를 통한 에러 핸들링이 필요합니다.
예시)
try{
const { data, errors } = ...
if (response.errors) {
...
}
} catch(error){
...
}
마무리
이상으로 한국어 블로그 릴레이의 열한 번째 블로그 「Amplify Gen2 + React로 CRUD 구축해 보기」 편이었습니다.
이번 블로그에서 간단히 CRUD를 만들어 보았습니다.
다음 제 순번의 블로그 릴레이에서는 조금 더 복잡한 백엔드 구성에 관해서도 소개해 보겠습니다.
다음 열두 번째 블로그 릴레이는 9월 두 번째 주에 공개됩니다.
참고자료
Amplify Gen2 - Data section
Amplify Gen2 - Set up Amplify Data
Amplify Gen2 - Customize your auth rules