
생성형 AI와 2주간의 논의를 거쳐 2일 만에 구현 및 공개 ─ sql.js × Go × PostgreSQL로 만드는 SQL 학습 서비스
요약
생성형 AI와의 설계 논의를 통해 2일 만에 구현한 SQL 학습 서비스 'kufu:SQL'의 개발 사례를 소개합니다. sql.js와 WebAssembly를 활용해 브라우저 내에서 SQL을 실행함으로써 서버 부하와 보안 리스크를 최소화한 아키텍처를 제안합니다.
핵심 포인트
- sql.js(WebAssembly)를 활용한 클라이언트 사이드 SQL 실행 구조
- 서버 부하 및 보안 리스크를 줄이는 하이브리드 아키텍처 설계
- EventBridge를 이용한 EC2 스케줄링으로 인프라 비용 절감
- 생성형 AI를 활용한 아이디어 구체화 및 빠른 구현 프로세스
최근 3개월 정도, PostgreSQL 16~18의 튜닝에 대해 실전 사례를 곁들여 기사로 정리해 왔습니다. 그 과정에서 다시금 「SQL을 직접 작성하며 연습할 수 있는 곳」이 필요하다고 느껴, 학습 서비스 kufu:SQL을 개발했습니다.
이런 분들이 읽어주셨으면 하는 기사입니다.
- SQL을 직접 손으로 움직이며 배우고 싶은 분 (서비스 이용자로서)
- 개인 개발에서 저비용 인프라 구성을 찾고 있는 분
- 생성형 AI를 사용한 개발이 실제로 어떻게 진행되는지 알고 싶은 분
컨셉, 아키텍처, 채택할 프로그래밍 언어(당초에는 Scala를 검토했습니다)에 대해서는 2주 정도 생성형 AI와 벽치(壁打ち, 아이디어 논의)를 거듭하며 설계를 확정했습니다. 벽치 단계에서는 구현에도 2개월 정도 걸릴 것이라고 예상했으나, 막상 착수하니 설계가 이미 확정되어 있었던 덕분에 구현 자체는 2일 정도 만에 동작하는 상태까지 완성되었고, 그대로 본방 공개까지 진행할 수 있었습니다.
가상의 SaaS 기업 「Kufu Cloud」에 입사한 신입 데이터 애널리스트로서, 각 부서로부터의 의뢰를 SQL로 해결해 나간다――는 설정으로 Lv.1~70의 문제를 준비했습니다. 본 기사에서는 이 서비스를 어떤 구성으로 만들었는지, 그리고 생성형 AI를 어떻게 사용했는지를 정리합니다.
-
서비스 URL: https://kufusql.sanpo-insight.com
-
GitHub (OSS 공개): https://github.com/matsutomu/kufu-sql
-
브라우저 상에서 SQL을 실행할 수 있는 메커니즘 (sql.js / SQLite on WebAssembly)의 사용법
-
서버 부하를 억제하는 하이브리드 구성 (클라이언트 실행 + Go API)의 사고방식
-
EC2의 자동 기동·정지에 의한 비용 절감 설계
-
70개의 문제 데이터를 정답 SQL의 실행 결과로부터 자동 생성하는 메커니즘
-
개발에 있어 생성형 AI와 인간이 각각 무엇을 담당했는가
| 항목 | 내용 |
|---|---|
| 서비스명 | kufu:SQL |
| ... | |
| SQL 학습 서비스라고 하면, 「사용자가 입력한 SQL을 서버 측 DB에서 실행하는」 구성이 일반적입니다. 다만 이 방식은 사용자 수가 늘어날수록 서버 부하가 높아질 뿐만 아니라, 임의의 SQL을 서버 측에서 실행하게 되므로 보안 측면의 리스크도 안게 됩니다. |
kufu:SQL에서는 사용자가 입력한 SQL을 브라우저 내의 sql.js (SQLite on WebAssembly)에서 실행하고, 채점이나 진척도 저장 등 필요한 처리만을 Go API로 보내는 구성으로 했습니다. SQL 실행 처리는 서버 측에서 발생하지 않으며, API 서버 측에서 임의의 SQL을 실행하는 리스크도 피할 수 있습니다.
sql.js는 SQLite를 WebAssembly로 컴파일한 라이브러리로, 브라우저 내에서 완결되어 SQL을 실행할 수 있습니다. 최소 구성은 다음과 같습니다.
import initSqlJs from "sql.js";
const SQL = await initSqlJs({
locateFile: (file) => `https://sql.js.org/dist/${file}`,
...
이것만으로 서버를 전혀 거치지 않고 테이블 생성, 데이터 투입, SELECT까지 동작합니다. 학습 용도와 같이 「사용자마다 독립된 작은 DB가 있으면 된다」는 케이스에는 매우 궁합이 좋은 메커니즘입니다.
학습 서비스라는 특성상 심야나 이른 아침의 액세스는 거의 기대할 수 없습니다. 그래서 EventBridge로 EC2의 기동·정지 스케줄을 짜서, 서비스 제공 시간을 8시~19시로 한정하고 있습니다. 개인 개발에서 러닝 코스트를 억제하고 싶을 때 유효한 수단 중 하나입니다.
EC2 정지 중에도 Elastic IP 유지나 EBS 스토리지 과금은 발생하기 때문에 완전히 무료가 되는 것은 아닙니다. 어디까지나 「가동 시간만큼의 컴퓨팅 비용을 억제하는」 시책입니다.
| 리소스 | 월간 예상 비용 |
|---|---|
| EC2 (주간에만 가동) | 약 5~7달러 |
| ... | 합계 |
| 약 8~10달러/월 |
가상의 SaaS 기업 「Kufu Cloud」에 신입 데이터 애널리스트로 입사하여 각 부서의 의뢰를 해결해 나간다는 스토리 형식으로 70문제를 구성하고 있습니다.
| 카테고리 | 문제 수 | 내용 | 상정 부서 |
|---|---|---|---|
| SQL 기초 | 10문항 | SELECT・WHERE・ORDER BY・LIMIT | 영업부・경리부 |
| ... |
실제 문제 화면은 이러한 이미지입니다. 문제문・SQL 에디터・실행 결과가 한 화면에 들어와 있어, 브라우저만으로 학습이 완결됩니다.
70문항분의 기대 결과(result_json)는 수작업으로 준비하지 않았습니다. 각 문제마다 DDL・시드 데이터(Seed Data)・정답 SQL을 JavaScript 객체로서 정의하고, 프론트엔드와 동일한 sql.js (SQLite on WASM)로 실제로 실행한 결과를 그대로 마이그레이션 SQL로 출력하는 구조로 만들었습니다.
문제 정의는 대략 다음과 같은 이미지입니다 (실제 코드를 간략화한 예시입니다).
const problem = {
id: 1,
categoryId: 1,
...
이 방식에는 다음과 같은 이점이 있습니다.
- 정답 SQL에 문법 오류가 있다면, 생성 시점에 검지할 수 있다
- 기대 결과를 수동으로 작성하는 번거로움이나 전기(Transcription) 실수가 없어진다
- 문제 데이터를 변경해도, 생성 스크립트를 재실행하는 것만으로 정합성을 유지할 수 있다
나아가, 생성 후에는 다음과 같은 검증 단계를 추가하고 있습니다.
- 모든 문제의
answer_sql이 중복되지 않았는지 체크 - 힌트 안에 정답 SQL의 핵심 부분이 그대로 포함되어 있지 않은지 체크
- 각 카테고리 내에서 난이도(easy/medium/hard)의 흐름이 부자연스럽지 않은지 체크
- 실행 결과가 의도치 않게 0건이 되는 문제가 없는지 체크
70문항 규모의 콘텐츠라도, 수작업 리뷰에 너무 의존하지 않고 일정 수준의 품질을 담보할 수 있는 구조로 되어 있습니다.
kufu:SQL은 당초 인프라 구축부터 β 공개까지 12주 정도를 예상하고 계획했습니다. 실제로는 2주간의 설계 페이즈를 거친 후, 구현 자체는 2일 정도 만에 본방 가동(Production)까지 도달했습니다.
요인을 엄격하게 구분하기는 어렵지만, 다음과 같은 점들이 영향을 미쳤다고 생각됩니다.
- 설계 페이즈에서 컨셉・아키텍처・기술 선정을 미리 확정해 두었다는 점
- 인프라 구성을 심플한 하이브리드형(클라이언트 실행 + 최소한의 API)으로 유지했다는 점
- 문제 데이터의 생성・검증을 자동화하여 수작업 리뷰 공수를 줄였다는 점
- 구현・인프라 구축의 일부에 AI 코딩 어시스턴트를 활용했다는 점
이 짧은 기간에 대해서는, 생성형 AI를 사용한 본격적인 신규 개발을 통해 이른바 '산업 혁명'이라는 단어로 이야기되는 변화의 감각을 처음으로 실감했다는 것이 솔직한 인상입니다.
한편으로, 인간의 역할이 불필요해졌다고는 느끼지 않습니다. 이번 개발을 통해 현시점에서의 인간의 역할은 다음의 3가지로 집약되지 않을까 생각합니다.
- 실현하고 싶은 것을 명확히 하는 것
- 아키텍처를 명확히 하는 것
- 만들어진 것을 반드시 비판적으로 확인하는 것
본 프로젝트에서는 구현부터 인프라 구축까지 폭넓게 Claude Code를 활용했습니다. 다만, 모든 것을 전적으로 맡긴 것은 아니며 역할은 다음과 같이 나뉘어 있습니다.
AI가 담당한 것
- 프론트엔드・백엔드 구현 코드 생성
- 보안 개선(CORS 설정・에러 응답 재검토・유효성 검사 강화) 구현
- AWS CLI 명령어 구성
- 배포 시 발생한 에러 메시지를 통한 원인 분류
인간이 판단・리뷰한 것
- 실현하고 싶은 기능・사양, 컨셉의 결정
- 아키텍처 전체의 설계 판단
- 생성된 코드의 내용 확인 및 채택 여부 판단
- 운영 환경 반영 및 실행에 대한 최종적인 의사 결정
생성된 코드나 명령어는 그대로 채택하는 것이 아니라, 내용을 확인한 후에 반영하는 운용 방식을 취하고 있습니다. 개인 개발에 있어 구현부터 인프라 구축까지 혼자서 담당할 경우, AI 코딩 어시스턴트와 조합함으로써 개발 속도를 높일 수 있는 가능성을 느꼈습니다.
kufu:SQL은 OSS로 공개하고 있습니다. 5.2에서 소개한 것처럼, 문제는 「DDL・시드 데이터・정답 SQL」을 JavaScript 객체 하나로 정의하기만 하면 추가할 수 있는 구조이기 때문에, 문제 추가 및 개선의 허들이 비교적 낮습니다.
다음과 같은 형태의 참여를 환영합니다.
- 문제 추가 및 개선을 위한 Pull Request: 새로운 문제의 추가나, 기존 문제의 문제문·힌트 개선
- Issue를 통한 보고: 오타, 난이도 밸런스의 어색함, 동작 오류 등 발견한 점이 있다면 언제든 편하게
- 요청(Request)만이라도 환영: "이런 문제가 있었으면 좋겠다", "이 SQL 구문의 카테고리를 늘려달라"와 같은 요구사항도 Issue로 남겨주시면 검토하겠습니다
리포지토리를 살펴보시고 "재미있겠다"라고 느끼셨다면, Star를 눌러주시는 것이 개발에 큰 힘이 됩니다.
- 브라우저 내에서 SQL을 실행하는 sql.js와, 채점·진척도 관리만을 담당하는 Go API를 조합함으로써 서버 부하를 억제하면서 SQL 학습 서비스를 구축할 수 있습니다.
- EventBridge를 통한 EC2의 자동 시작·정지는 개인 개발의 러닝 코스트 (Running Cost)를 절감하는 유효한 수단 중 하나입니다.
- DDL·시드 데이터(Seed Data)·정답 SQL로부터 result_json을 자동 생성하는 메커니즘을 통해, 70문항 규모의 콘텐츠에서도 품질을 유지하기 쉽습니다.
- 2주간의 설계 (Design) 단계를 거친 후 구현에 들어간 것이, 구현 자체를 2일로 단축할 수 있었던 요인 중 하나라고 생각합니다.
- AI 코딩 어시스턴트 (AI Coding Assistant)에게는 구현·인프라 구축을 맡기되, 사양 결정·설계 판단·최종 리뷰는 인간이 담당하는 역할 분담이 이번 개발에서 효과적으로 작동했습니다.
서비스는 8시~19시에 가동됩니다. SQL을 습득하는 장소로서 꼭 활용해 주시기 바랍니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기