공개 실습 예제 · v1 · 2026-09-06
AI와 만드는 할 일 앱
할 일을 저장한 뒤 화면을 새로고침해도 내용이 남는 앱을 만듭니다. 화면, 서버, 데이터베이스가 맡는 일을 구분하고 AI가 제안한 코드를 테스트로 확인합니다.
AI의 도움을 받아 작성한 수업용 참고 구현입니다. 학생 작품이나 수강 성과 사례가 아닙니다. 실제 이름과 연락처를 입력하지 마세요. 예제 서버는 개인 컴퓨터에서만 실행합니다.
대상: 간단한 HTML·Python을 읽고 터미널에서 명령을 실행할 수 있는 중·고등학생. 처음 접하는 학생은 튜터와 함께 파일과 명령부터 확인합니다. Python 3.10 이상과 브라우저가 필요하며 실행에 유료 AI 도구나 API 키는 필요하지 않습니다.
1. 저장한 내용이 다시 보이나요?
압축을 풀고 task-board 폴더에서 터미널을 엽니다. 먼저 테스트를 실행한 뒤 서버를 켜고 http://127.0.0.1:8766에 접속합니다. Windows에서는 설치 환경에 따라 python3 대신 py -3를 사용합니다.
python3 -m unittest -v
python3 server.py --db tasks.sqlite3
첫 명령은 코드가 약속대로 동작하는지 확인합니다. 두 번째 명령은 이 컴퓨터에서만 서버를 열고 tasks.sqlite3 파일에 내용을 저장합니다. 종료는 Ctrl+C입니다. 같은 파일로 다시 실행하면 이전 내용이 남아 있어야 합니다.
만들기 전에 정할 명세
- 제목은 앞뒤 공백을 제외하고 1~80자입니다.
- 새 할 일은 미완료 상태이며 완료 표시를 바꿀 수 있습니다.
- 빈 제목은 저장하지 않고 오류를 알려 줍니다.
- 서버를 껐다 켜도 저장한 내용이 남습니다.
- 저장에 실패하면 성공했다고 표시하지 않습니다.
이 목록이 명세입니다. AI에게 “예쁜 앱을 만들어 줘”라고만 요청하기 전에 저장 규칙과 실패할 때의 동작을 적어 둡니다.
2. 화면·API·데이터베이스의 역할
| 구성 요소 | 예제 파일 | 맡은 일 |
|---|---|---|
| 프론트엔드: 사용자 화면 | index.html, app.js | 제목을 받고 저장 요청을 보냅니다. 응답을 확인한 뒤 목록을 다시 그립니다. |
| 백엔드: 요청 처리 서버 | server.py | API라는 정해진 요청 규칙으로 입력을 받고 제목 길이를 검사합니다. |
| 데이터베이스: 기록 저장소 | tasks.sqlite3 | 번호, 제목, 완료 여부를 파일에 보관합니다. 새로고침해도 기록이 남습니다. |
cursor = db.execute("INSERT INTO tasks (title) VALUES (?)", (title,))
server.py의 이 줄은 제목을 별도의 값으로 전달합니다. SQL은 데이터베이스에 보내는 명령 언어이며 ? 자리에 제목을 넣으면 입력 내용을 SQL 명령과 구분할 수 있습니다.
| 요청 | 보내는 내용 | 결과 |
|---|---|---|
GET /api/tasks | 없음 | 200: 저장된 목록 |
POST /api/tasks | {"title":"테스트 작성"} | 201: 저장한 항목 / 400: 잘못된 입력 |
PATCH /api/tasks/1 | {"done":true} | 200: 완료 처리 / 404: 없는 번호 |
브라우저 개발자 도구의 Network 탭에서 저장 요청과 응답을 확인해 보세요. 응답의 done은 0 또는 1이고 완료 요청에는 true를 보냅니다. 숫자와 참·거짓 값을 혼동하면 API 약속이 어긋납니다.
3. AI가 작성한 코드 확인하기
요청 예시: “먼저 명세와 파일 역할을 읽고 변경 계획을 설명해 줘. 빈 제목을 API로 직접 보내는 테스트를 추가해 줘. 관련 없는 파일은 수정하지 말고 실제 테스트 결과와 남은 한계를 알려 줘.” Codex나 Claude Code 등 사용하는 도구에 이 요청을 전달한 뒤 제안한 변경을 직접 읽습니다.
if (!response.ok) throw new Error(data.error || "Request failed.");
app.js에서 서버의 성공 여부를 확인하는 줄입니다. 화면의 버튼이 눌렸다는 사실만으로 저장 성공을 판단하지 않습니다.
튜터 피드백 예시와 수정 연습
“화면의 필수 입력 표시만으로 API를 보호할 수는 없습니다. 공백만 직접 전송하는 테스트를 보여 주세요.”
참고 구현에는 서버 검사와 DB 제약 조건이 모두 있습니다. 별도 복사본에서 두 검사를 제거하면 빈 제목 테스트가 어떻게 실패하는지 확인한 뒤 원래 코드를 복원합니다. 실제 출력만 기록하세요. 이 문장은 연습용 피드백이며 실제 학생의 수정 이력이 아닙니다.
테스트 7개는 저장·조회, 빈 값과 길이 검사, SQL처럼 생긴 제목, 완료 처리, 재시작 후 보존, 요청 출처·형식 검사, 과도한 크기의 입력을 다룹니다. 테스트 통과만으로 공개 서비스의 안전성이 입증되지는 않습니다.
상황 퀴즈: 답을 생각한 뒤 해설을 여세요
1. 새로고침하니 할 일이 사라졌습니다. CSS와 저장 경로 중 어디를 먼저 확인할까요?
저장 경로입니다. POST 응답, GET 결과, DB 파일 위치를 차례로 확인합니다. CSS는 모양을 바꾸지만 데이터를 보존하지 않습니다.
2. 화면에서 빈 입력을 막았습니다. 서버 검사도 필요한가요?
필요합니다. 화면을 거치지 않고 API에 요청할 수 있습니다. 공백만 보냈을 때 400 응답과 DB에 새 항목이 없는지를 함께 확인합니다.
3. DB 저장이 실패했는데 화면은 성공이라고 합니다. 어디를 고칠까요?
서버의 저장 완료 시점과 화면의 응답 검사를 모두 봅니다. 트랜잭션은 여러 DB 작업을 성공 또는 실패로 묶는 단위입니다. 서버가 저장을 확정한 뒤 성공을 보내고 화면은 응답 상태를 확인해야 합니다.
4. 로컬 테스트가 통과했습니다. 서버 주소만 바꾸면 공개해도 될까요?
아직 안 됩니다. 이 예제에는 로그인과 사용자별 접근 권한이 없습니다. 실제 배포 전에는 운영용 서버, HTTPS, 백업·복구와 접근 권한을 따로 검토합니다.
4. 기존 데이터를 지키며 기능 추가하기
숙제: 할 일에 낮음·보통·높음 우선순위를 추가합니다. 기존 항목이 있는 DB를 어떻게 바꿀지 먼저 계획하고 AI에게 구현을 요청합니다. 데이터 마이그레이션은 기존 기록을 유지하면서 저장 구조를 바꾸는 작업입니다.
self.assertEqual(self.request("GET", "/api/tasks")[1][0]["title"], "Survive restart")
test_server.py에서 재시작 후 제목이 남아 있는지 확인하는 줄입니다. 숙제에서는 구조 변경 후에도 같은 확인을 추가합니다.
제출물: 명세, 코드 변경 내용, 수정 전후 테스트 출력, 기존 항목이 남아 있는 화면, AI 제안 중 채택·거절한 내용과 이유. 빈 목록, 오류 안내, 키보드 조작도 확인합니다.
| 항목 | 2점 기준 |
|---|---|
| 명세 | 허용 값과 실패 동작을 명확히 적음 |
| 기존 데이터 | 변경 전 항목이 보존됨을 테스트로 확인 |
| API와 테스트 | 정상·오류 입력을 서버에서 검사 |
| 접근 가능한 화면 | 레이블, 키보드, 결과 안내를 확인 |
| AI 작업 검토 | 직접 내린 판단과 남은 한계를 설명 |
튜터용 제안: 총 8점 이상이며 데이터 보존과 입력 검사는 각 2점일 때 다음 확장으로 진행합니다. 이 예제의 평가 제안이며 학원 전체 성적 기준은 아닙니다.
튜터 진행안과 공개 배포 전 점검
60~90분 진행 제안: 실행·예측 10분, 요청 흐름 확인 15분, 테스트 20분, AI와 기능 확장 15~30분, 설명 10분. 실제 소요 시간은 준비도에 따라 조정합니다.
예제 서버를 외부에 공개하거나 터널로 연결하지 마세요. 공개 서비스는 운영용 서버, 로그인·사용자별 권한, HTTPS, 비밀값 관리, 마이그레이션, 백업 복원, 요청량 제한, 오류 감시와 이전 버전 복구를 튜터가 검토한 뒤 별도 환경에서 연습합니다.
기술 근거: Python 공식 문서는 http.server를 운영용으로 권장하지 않습니다. 값 전달과 저장 규칙은 sqlite3 문서에서 확인할 수 있습니다.
다음 학습 경로
국제학교 AI·EC 포트폴리오 · 과고·영재고 AI 포트폴리오
학생의 준비도와 수업 범위는 상담 예약에서 확인할 수 있습니다.