AI 웹 개발 교실

05 · 화면과 서버 연결하기

React의 상태와 이벤트를 복습하고 정상·지연·실패 API 응답을 처리합니다.

이 단원의 실습 파일 82 KB ZIP 다운로드

만들 결과물: 학습 목표를 입력하면 할 일 목록이 나오고, 각 항목을 완료 체크하는 학습 플래너.

화면과 서버 실습 ZIP 다운로드 · 실습 준비

API 키 없이 시작합니다. 기본 연습 모드는 준비된 데이터를 반환하며 실제 AI를 호출하지 않습니다. 서버 요청과 화면 상태를 배우기 위한 응답입니다. 이 단원에서는 데이터베이스 저장이나 로그인까지 제공하지 않습니다.

먼저 완성 예제 사용하기

압축을 푼 실습 폴더에서 실행합니다.

npm ci
npm run dev

로컬 수업 홈을 열어 완성 앱을 먼저 사용합니다. 실습은 내 컴퓨터에서 진행하며 사이트 자료실 화면 자체가 실행 중인 앱은 아닙니다.

예제 경로볼 코드배울 것
/examples/01-inputsrc/examples/day-01/01-input.tsx입력과 state
/examples/02-listsrc/examples/day-01/02-list.tsx배열·map·key
/examples/03-togglesrc/examples/day-01/03-toggle.tsx한 항목의 상태 변경
/examples/04-componentssrc/examples/day-01/04-components.tsxprops·콜백
/examples/05-asyncsrc/examples/day-01/05-async.tsx정상·지연·실패 응답
/examples/06-plannersrc/examples/day-01/06-planner.tsx전체 흐름

예제는 작동하는 완성 코드입니다. /practice만 의도적으로 미완성인 학생 실습이며, 수정할 파일은 src/exercises/day-01/starter.tsx입니다. day-01은 예제 내부 경로 이름이며 하루 안에 끝내라는 뜻은 아닙니다.

워밍업 · 세 줄 찾기

01-input.tsx에서 입력값을 기억하는 줄, 타이핑할 때 실행되는 줄, 값을 화면에 보여 주는 줄을 찾습니다.

직접 변경: 목표가 10자 미만이면 “조금 더 구체적으로 적어볼까요?”를 표시합니다. 저장 후 화면에 반영되는지 확인합니다.

TODO 1 · 배열 전체를 목록으로

/practice에서 “목록 불러오기”를 누르면 처음에는 한 항목만 보입니다.

starter.tsx의 tasks[0] 표시 부분을 tasks.map(...)으로 바꾸고, 각 li의 key에 해당 항목의 id를 사용합니다.

성공 조건: 세 항목이 모두 표시되고 각 체크박스가 자기 항목의 ID와 연결됩니다.

힌트: map에서 무엇을 반환하나요?

02-list.tsx에서 배열의 각 항목을 JSX로 바꾸는 부분을 봅니다. 반복 중인 항목을 사용해야 모든 체크박스가 같은 항목을 가리키지 않습니다.

TODO 2 · 한 항목만 완료 처리

toggleTask(id)에서 기존 tasks를 map으로 순회합니다. ID가 같은 항목만 새 객체로 복사해 done을 반대로 바꾸고, 나머지는 그대로 반환합니다. 그 새 배열을 상태에 반영합니다.

성공 조건: 두 번째 체크박스를 누르면 두 번째 항목만 바뀌고, 다시 누르면 되돌아옵니다.

아래는 비교용으로 일부러 잘못 적은 코드입니다. 어떤 배열과 객체를 직접 수정하고 있나요?

tasks[0].done = true;
setTasks(tasks);

완료 항목의 취소선은 선택 과제입니다. 먼저 상태 변화가 올바른지 확인합니다.

TODO 3 · API 결과를 화면에 연결

제공 함수는 다음처럼 사용합니다.

import { generatePlan } from "@/lib/generate-plan";

const nextTasks = await generatePlan(goal);

handleSubmit을 async 함수로 바꿉니다. 공백뿐인 입력은 거절하고, 응답으로 받은 배열을 setTasks에 전달합니다. 새 목록은 기존 목록을 교체합니다.

성공 조건: 내 목표를 포함한 연습 계획이 표시됩니다. 공백만 입력했을 때는 서버 요청이 발생하지 않습니다.

제출 이벤트 → generatePlan → POST /api/plan
→ 서버 입력 확인 → 응답 → setTasks → 목록 표시

브라우저 개발자 도구의 Network에서 요청을 찾고, src/lib/generate-plan.ts, src/app/api/plan/route.ts, src/lib/server/plan-handler.ts를 따라가 봅니다.

TODO 4 · 기다림과 실패도 화면에 표시

isLoading과 error 상태를 추가합니다.

  • 요청 전에는 로딩을 시작하고 이전 오류를 지웁니다.
  • 성공하면 새 목록을 표시합니다.
  • 실패하면 오류 안내를 표시하고 이전 목록을 유지합니다.
  • 성공·실패 모두 로딩을 끝내 다시 요청할 수 있게 합니다.

로딩 중에는 생성 버튼을 비활성화하고 “계획을 만드는 중…”으로 표시합니다. 아래 모드를 하나씩 사용해 결과를 확인합니다.

await generatePlan(goal, "mock");  // 약 0.6초 뒤 연습 데이터
await generatePlan(goal, "slow");  // 약 3초 뒤 연습 데이터
await generatePlan(goal, "error"); // 의도적으로 실패

error는 학습용 실패 응답입니다. 실패를 성공한 것처럼 표시하지 않습니다. 확인 후 mock으로 되돌립니다.

힌트: 오류가 나면 버튼이 계속 잠겨 있어요

성공 경로에서만 로딩을 끝내고 있지 않은지 봅니다. try, catch, finally가 각각 어떤 상황에서 실행되는지 05-async.tsx와 비교합니다.

짝과 검증하기

행동기대 결과
공백 입력 후 생성요청 없이 안내
정상 목표 생성새 목록으로 교체
두 번째 항목 체크해당 항목만 변경
지연 응답대기 중 버튼 비활성화
오류 응답안내 표시·이전 목록 유지·버튼 복구
오류 뒤 정상 요청다시 생성 성공
새로고침저장 기능이 없어 상태 초기화

더 바꾸고 싶다면

완료 개수 표시, 완료한 항목 숨기기, 제목 수정 중 하나를 선택합니다. 완료 개수처럼 기존 tasks에서 계산할 수 있는 값은 왜 별도 상태가 없어도 되는지 설명해 보세요.

실제 AI 연결은 별도 설정이 필요한 선택 활동입니다. 기본 실습에는 키를 입력하거나 개인 계정을 만들 필요가 없습니다. 브라우저 코드와 서버 코드의 실행 위치를 먼저 구분합니다.

수정한 코드와 실행 화면, 직접 확인한 정상·실패 사례를 남깁니다. 다음 학습 목표는 데이터 저장과 관계입니다.

이 페이지에서