AI 모델이 생성한 문항이 일회성 대화창의 답변으로 휘발되지 않고 교육 현장에서 지속 가능한 자산이 되기 위해서는 견고한 데이터 엔지니어링이 필수적입니다. 온유 리본(Onew Reborn)은 지문 라이브러리 → 출제 청사진 → 상태 머신 기반 생성 이력 → Supabase RLS 보안 → 이원화 PDF 렌더링으로 이어지는 통합 백엔드 파이프라인을 구축하여 신뢰도 높은 학생용 맞춤 학습지 생성 환경을 완성했습니다.
교육 현장에서 매 시험 기간마다 반복되는 학생용 맞춤 학습지 생성 작업은 단순한 텍스트 출력을 넘어, 지문과 출제 규칙 및 검증 기록이 유기적으로 연결될 때 비로소 완성됩니다.
지난 6편에서는 내신 서술형의 대표 유형인 요약문 빈칸 완성형에서 환각(Hallucination) 현상을 차단하기 위해 지문 근거 검증과 구조화된 JSON 모드를 결합하는 방법을 다루었습니다. 하지만 아무리 AI가 훌륭한 문항 초안을 생성하더라도, 그 결과가 화면에서 일회성으로 소비되고 끝난다면 교사는 다음 시험 대비 기간에 같은 프롬프트 엔지니어링을 처음부터 다시 반복해야 합니다.
문항 데이터는 지문 원본, 학교별 출제 조건, 생성 당시의 모델 파라미터, 품질 검증 로그와 함께 묶여 **‘추적 가능한 교육 자산’**으로 보존되어야 합니다. 본 글에서는 온유 리본이 1인 개발 환경에서 실제 운영 중인 학생용 맞춤 학습지 생성 백엔드 데이터 아키텍처와 데이터베이스 설계 노하우를 상세히 공유합니다.
1. 학생용 맞춤 학습지 생성을 위한 데이터 연결의 필요성
현장에서 교사가 체감하는 완성도 높은 학생용 맞춤 학습지 생성은 단순히 LLM의 응답 창에서 텍스트를 복사해 한글(HWP)이나 워드 파일에 붙여넣는 일회성 보조 도구와는 본질적으로 다릅니다.
학원이나 학교의 내신 대비 수업은 매 학기마다 같은 지문이 다른 학교의 시험 범위로 재등장하고, 같은 학교라도 학년에 따라 서술형 배점과 감점 기준이 달라집니다. 따라서 지속 가능한 시스템이 되려면 다음 4가지 핵심 질문에 시스템이 즉시 답할 수 있어야 합니다.
반복 가능한 교육 시스템이 갖추어야 할 4대 데이터 연결 고리
- 지문 원본 추적성(Source Traceability): 이 문항은 어떤 원문 지문(EBS 수능특강, 고1~2 학평 기출, 교과서)에서 파생되었는가?
- 학교별 규칙 재현성(Rule Reproducibility): 특정 고등학교에서 요구하는 단어 수 제한, 어형 변화 허용 여부, 필수 포함 문법 조건이 정확히 적용되었는가?
- 엔지니어링 텔레메트리(Engineering Telemetry): 생성 당시 어떤 모델(Gemini 1.5 Pro, LLaMA-3), 프롬프트 버전, Temperature 파라미터가 사용되었는가?
- 검증 이력과 피드백 루프(Validation History): 품질 게이트의 단어 일치율과 환각 점수를 어떻게 통과했으며, 교사가 사후에 수정한 문구(Diff)는 무엇인가?
온유 리본은 관계형 데이터의 엄격한 참조 무결성을 유지하면서도, 개별 교사의 작업 공간을 안전하게 격리하기 위해 Supabase의 PostgreSQL 단일 데이터베이스 계층을 채택했습니다.
2. [지문 라이브러리] SHA-256 해시 기반 중복 제어와 시험 범위 격리
문항 생성 파이프라인의 모든 데이터는 원문 지문(Passage)에서 출발합니다. 지문 라이브러리는 텍스트 자체뿐 아니라 출처 분류, 연도, 학년, 그리고 해당 지문이 배정된 학교별 시험 범위 메타데이터를 통합 관리합니다.
지문 테이블 DDL 및 SHA-256 정규화 해시 설계
교사가 여러 차례에 걸쳐 같은 모의고사 지문을 등록하더라도 데이터베이스에 무의미한 중복 레코드가 쌓이지 않도록, 본문 공백과 줄바꿈을 정규화(Normalize)한 뒤 content_hash를 생성하여 유니크 제약을 적용합니다.
-- 지문 라이브러리 테이블 스키마 예시
CREATE TABLE passages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
content_hash CHAR(64) NOT NULL, -- SHA-256 해시값
source_type VARCHAR(50) NOT NULL, -- 'EBS', 'MOCK_EXAM', 'TEXTBOOK'
grade_level SMALLINT NOT NULL, -- 1 (고1), 2 (고2), 3 (고3)
is_archived BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT uq_user_passage_hash UNIQUE (user_id, content_hash)
);
CREATE INDEX idx_passages_user_lookup ON passages(user_id, is_archived);
학교별 시험 범위 분리와 소프트 아카이브(Soft Archive) 원칙
지문은 개인 마스터 라이브러리에 안전하게 보관되며, passage_assignments 매핑 테이블을 통해 A 고등학교 또는 B 고등학교의 특정 학기 중간·기말고사 시험 범위로 다대다(N:M) 연결됩니다. 이를 통해 한 학교의 작업 목록이 다른 학교의 문제 출제 범위와 섞이는 문제를 원천적으로 방지합니다.
또한 시험이 끝난 후 지문을 정리할 때도 is_archived = true 플래그를 통한 소프트 아카이브 방식을 적용합니다. 지문 레코드를 물리 삭제(Hard Delete)하지 않으므로, 과거에 생성된 학생용 맞춤 학습지 생성 결과물의 근거 원본을 언제든지 온전하게 열람하고 재인쇄할 수 있습니다.
3. [출제 청사진] 학생용 맞춤 학습지 생성의 핵심 규칙 추상화와 스냅샷
기출문제의 지문과 문항을 그대로 복제하는 방식은 저작권 침해 우려가 있을 뿐 아니라, 매번 지문이 바뀌는 학교 내신 시험에 유연하게 대응하기 어렵습니다. 온유 리본은 기출문제에서 재사용 가능한 출제 논리와 제약 조건을 추상화하여 ‘출제 청사진(Question Blueprint)’으로 자산화합니다.
청사진(Blueprint) 데이터 구조와 제약 조건 스키마
출제 청사진은 문제의 뼈대 역할을 하며, LLM이 문항을 생성할 때 엄격한 시스템 프롬프트 제약 조건으로 변환되어 주입됩니다.
{
"blueprint_id": "bp_gwangmyeong_g2_summary_v2",
"title": "광명지역 고2 1학기 기말 요약문 빈칸 완성형",
"question_type": "SUMMARY_BLANK_COMPLETION",
"status": "APPROVED",
"constraints": {
"target_blank_count": 2,
"blank_labels": ["(A)", "(B)"],
"word_count_limit": { "min": 14, "max": 22 },
"allow_form_change": true,
"required_syntax": ["분사구문", "관계대명사"],
"banned_direct_copies": true
},
"scoring_guide": {
"total_points": 6.0,
"partial_points": [
{ "condition": "철자 오류 1개당", "deduction": -1.0 },
{ "condition": "어형 미변형 시", "deduction": -2.0 }
]
}
}
스냅샷(Snapshot) 동결을 통한 재현성과 불변성 보장
청사진은 교사의 검토를 거쳐 승인(Approved) 상태가 된 것만 실제 문항 생성 파이프라인에 사용됩니다. 특히 문항 생성이 실행되는 순간, 당시 적용된 청사진 JSON 전체가 생성 작업 테이블(generation_jobs)에 **불변 스냅샷(Immutable Snapshot)**으로 기록됩니다.
향후 교사가 내년도 시험을 위해 청사진의 단어 수 제한을 수정하더라도, 과거에 출제되었던 문항 세트가 어떤 기준에서 생성되었는지는 영구히 변하지 않습니다. 이는 시스템의 책임 추적성과 엔지니어링 재현성을 보장하는 핵심 설계입니다.
4. [생성 이력 및 텔레메트리] 4단계 상태 머신과 품질 게이트 로깅
AI 기반 문항 생성은 단일 비동기 요청으로 끝나지 않으며, 네트워크 실패나 모델 지연, 품질 기준 미달에 대응할 수 있는 견고한 상태 머신(State Machine)으로 관리되어야 합니다.
생성 작업의 4단계 라이프사이클
QUEUED(대기): 교사가 지문과 청사진을 선택하고 요청을 생성한 상태GENERATING(생성 중): LLM 엔진이 Structured Output(JSON) 형태로 문항 초안을 작성 중인 상태VALIDATING(검증 중): 다단계 품질 게이트가 정답 유일성, 어휘 일치율, 글자 수 제약을 정밀 판정하는 상태COMPLETED/RETRYING: 모든 기준을 통과하여 저장되었거나, 기준 미달로 자동 재생성을 시도하는 상태
-- 생성 작업 및 검증 텔레메트리 테이블
CREATE TABLE generation_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id),
passage_id UUID NOT NULL REFERENCES passages(id),
blueprint_snapshot JSONB NOT NULL,
model_name VARCHAR(100) NOT NULL, -- 'gemini-1.5-pro', 'llama-3.3-70b'
prompt_version VARCHAR(50) NOT NULL, -- 'v2.4.1-subjective'
generated_payload JSONB, -- 생성된 문항, 보기, 정답 데이터
validation_metrics JSONB, -- 품질 게이트 점수 (환각 점수, 제약 준수율)
status VARCHAR(30) NOT NULL DEFAULT 'QUEUED',
latency_ms INTEGER,
created_at TIMESTAMPTZ DEFAULT NOW()
);
이력 테이블에 축적된 validation_metrics와 프롬프트 버전은 단순한 디버깅용 로그가 아닙니다. 어떤 프롬프트 버전에서 교사의 수정 비율(Diff Rate)이 가장 적었는지를 통계적으로 분석하는 기반이 되며, 향후 학생용 맞춤 학습지 생성의 품질을 지속적으로 고도화하는 데이터 자산이 됩니다.
5. [보안 및 테넌트 격리] Supabase PostgreSQL Row Level Security(RLS)
교사가 자체 구축한 지문 라이브러리, 학교별 출제 청사진, 학생 배포용 학습지 데이터는 민감한 교육 자산입니다. 멀티테넌트 환경에서 보안 사고를 방지하기 위해 온유 리본은 데이터베이스 엔진 레벨의 **Row Level Security(RLS)**를 전면 적용했습니다.
심층 방어(Defense in Depth)를 위한 RLS 정책 구현
애플리케이션 백엔드 API 레이어에서 user_id 검증 코드를 실수로 누락하더라도, 데이터베이스 엔진이 세션의 토큰 정보(auth.uid())를 직접 판별하여 타 사용자의 데이터 침범을 100% 차단합니다.
-- 생성 작업 테이블에 대한 엄격한 RLS 정책 선언
ALTER TABLE generation_jobs ENABLE ROW LEVEL SECURITY;
-- 본인의 생성 작업만 조회 가능
CREATE POLICY "Users can only read own generation jobs"
ON generation_jobs FOR SELECT
USING (auth.uid() = user_id);
-- 본인의 생성 작업만 생성 가능
CREATE POLICY "Users can only insert own generation jobs"
ON generation_jobs FOR INSERT
WITH CHECK (auth.uid() = user_id);
상세한 RLS 구현 가이드와 모범 사례는 Supabase의 Row Level Security 공식 문서를 통해 자세히 확인할 수 있습니다.
더불어 데이터베이스 관리자 권한을 가진 service_role 키는 서버 측 격리 환경(Next.js Server Actions / API Routes)에서만 제한적으로 사용하며, 브라우저 클라이언트에는 절대 노출되지 않도록 환경 변수를 철저히 분리했습니다.
6. [PDF 렌더링 엔진] 데이터 분리와 Human-in-the-Loop(HITL) 워크플로
정형화된 JSON 데이터는 최종적으로 교실에서 인쇄해 배포할 수 있는 2단(Two-Column) 레이아웃의 고품질 PDF 문서로 렌더링됩니다.
데이터 레이어와 프레젠테이션의 완전 분리
온유 리본의 렌더링 엔진은 문항 텍스트와 레이아웃 조판 엔진을 분리하여 동일한 데이터베이스 레코드로부터 두 가지 형태의 출력물을 생성합니다.
- 학생용 시험지(Worksheet PDF): 지문 본문, 배점, 문제 발문, 빈칸 밑줄 박스, 조건 박스 자동 배치
- 교사용 정답 및 해설지(Answer Key PDF): 모범 답안, 지문 전문 해석, 구문 분석, 채점 가이드라인 자동 정렬
Human-in-the-Loop(HITL): 자동화와 교사 전문성의 공존
온유 리본이 추구하는 학생용 맞춤 학습지 생성의 본질은 “인간의 개입이 없는 완전 자동화”가 아닙니다. AI와 백엔드는 서식 정리, 조건 일치 검증, 조판 작업에 소요되던 80%의 반복 노동을 대신 처리하고, 교사는 웹 미리보기 화면에서 최종 난이도와 답안의 수렴성을 확인하는 최종 교육적 검토(HITL)에 집중합니다.
기출문제의 출제 규칙을 청사진으로 변환하는 세부 엔지니어링 과정은 앞선 AI 영어 서술형 변형문제 개발기에서도 상세히 다루고 있습니다.
7. 에듀테크 백엔드 엔드투엔드 데이터 흐름 요약
지문 등록부터 최종 PDF 인쇄까지 이어지는 전체 데이터 파이프라인의 흐름을 정리하면 다음과 같습니다.
| 단계 | 핵심 기술 및 컴포넌트 | 주요 기능 및 시스템 산출물 |
|---|---|---|
| 1. 지문 등록 | SHA-256 Content Hash | 원문 중복 저장 방지, 학교별 시험 범위 다대다 매핑 |
| 2. 청사진 선택 | Rule Abstraction (JSON) | 승인된 학교별 출제 제약(단어수, 어형변화, 배점) 로드 |
| 3. 문항 생성 | LLM Engine (Structured Output) | 지문 본문과 청사진 제약이 결합된 구조화된 초안 도출 |
| 4. 품질 검증 | Multi-stage Quality Gate | 포맷 적합성, 본문 근거 일치율, 글자 수 제약 자동 판정 |
| 5. 이력 저장 | Supabase PostgreSQL (RLS) | 문항 데이터, 청사진 스냅샷, 검증 텔레메트리 영구 격리 보존 |
| 6. 조판 및 인쇄 | PDF Layout Engine | 교사 검토(HITL)를 거친 학생용 시험지 및 정답 해설지 출력 |
8. 자주 묻는 질문 (FAQ)
Q. 단순 프롬프트 엔지니어링 대비 백엔드 아키텍처 구축의 실질적 이점은 무엇인가요?
단순 프롬프트 입력 방식은 생성 결과가 비결정적이며 이전 출제 조건을 재현하기 어렵습니다. 백엔드 시스템을 통하면 지문 원본과 학교별 출제 청사진, 검증된 생성 이력이 데이터베이스에 남아 매 시험 기간마다 안정적이고 일관된 학생용 맞춤 학습지 생성을 반복 실행할 수 있습니다.
Q. 교사가 웹 UI에서 생성된 문항을 수정하면 AI 생성 원본 기록이 사라지나요?
사라지지 않습니다. 온유 리본은 AI가 생성한 원본 초안 데이터와 교사가 수정한 최종본을 별도 필드로 분리 보존합니다. 이를 통해 교사의 수정 패턴(Diff)을 분석하여 향후 시스템 프롬프트와 품질 게이트의 정확도를 높이는 데 활용합니다.
Q. PostgreSQL Row Level Security(RLS)를 적용했을 때 성능 저하는 없나요?
적절한 인덱스(user_id 복합 인덱스)를 구성하면 RLS로 인한 오버헤드는 수 밀리초(ms) 이하로 극히 미미합니다. 애플리케이션 코드 레벨의 권한 필터링보다 데이터베이스 엔진 내부에서 최적화된 쿼리 플랜을 실행하므로 안전성과 성능을 동시에 확보할 수 있습니다.