콘텐츠 내보내기에서 변형 문항 그룹 ID 보존

이 글의 목차 10개 항목
  • 분야: DB
  • 기술 스택: Node.js · SQLite · 콘텐츠 내보내기

문제와 원인

원본 DB의 변형 문항은 variant_group_id로 연결돼 있었지만 내보내기 결과에는 이 컬럼이 빠졌다. SELECT 목록을 만드는 QUESTION_COLUMNS에 해당 필드가 없었기 때문이다.

문항 행 수는 5,225개로 유지돼 개수 검사만으로는 누락을 찾기 어려웠다. 그룹 ID가 있는 28개 문항을 ID별로 대조하자 모두 관계 필드가 빠져 있었다.

수정 전 코드

QUESTION_COLUMNS

그룹 ID가 빠진 컬럼 목록으로 문항을 내보냈다.

export const QUESTION_COLUMNS = Object.freeze([
  "id", "category", "topic", "display_order", "exam_scope", "difficulty",
  "difficulty_rationale", "kind", "prompt", "choices", "correct_answers",
  "explanation", "tags", "scoring_criteria", "required_concepts",
  "acceptable_alternatives", "deduction_conditions", "error_conditions",
  "theory_id", "practice_scope", "bookmarked", "active", "created_at", "updated_at",
]);

readCanonicalContent

const questions = database.prepare(`
  SELECT ${QUESTION_COLUMNS.join(", ")}
  FROM questions
  ORDER BY display_order, id
`).all();

수정 후 코드

QUESTION_COLUMNS

이전 컬럼 목록을 LEGACY_QUESTION_COLUMNS로 보존하고 content-v2의 목록에 variant_group_id를 추가했다.

export const LEGACY_CONTENT_SCHEMA_VERSION = "content-v1";
export const CONTENT_SCHEMA_VERSION = "content-v2";

export const QUESTION_COLUMNS = Object.freeze([
  ...LEGACY_QUESTION_COLUMNS.slice(0, 20),
  "variant_group_id",
  ...LEGACY_QUESTION_COLUMNS.slice(20),
]);

questionColumnsForSchema

조회에서는 스키마 버전에 맞는 목록을 선택한다.

function questionColumnsForSchema(schemaVersion) {
  if (schemaVersion === LEGACY_CONTENT_SCHEMA_VERSION) {
    return LEGACY_QUESTION_COLUMNS;
  }
  if (schemaVersion === CONTENT_SCHEMA_VERSION) {
    return QUESTION_COLUMNS;
  }
  throw new Error(`unsupported content schema: ${schemaVersion}`);
}

readCanonicalContent

선택한 스키마의 컬럼 목록으로 조회한다.

const questionColumns = questionColumnsForSchema(schemaVersion);
const questions = database.prepare(`
  SELECT ${questionColumns.join(", ")}
  FROM questions
  ORDER BY display_order, id
`).all();

검증 결과

같은 DB의 내보내기 비교

Node.js, SQLite에서 같은 기준 DB로 수정 전후 readCanonicalContent()를 실행했다. 원본의 문항 ID별 그룹 값과 결과를 대조하고, 내보낸 레코드를 Wrangler의 로컬 D1에 적재해 Local Explorer SQL로 조회했다.

비교 항목수정 전수정 후
내보낸 문항5,225개5,225개
내보낸 이론158개158개
그룹 ID가 있는 28개 문항의 값 보존0/28개28/28개
variant_group_id 필드를 포함한 문항0개5,225개
그룹 ID 외의 문항 필드 전체 값기준값모두 일치
이론 필드 전체 값기준값모두 일치
content-v1 조회 결과기준값모두 일치

그룹 값이 없는 나머지 5,197개 문항은 null을 유지했다. 기존 필드 비교는 새 그룹 ID 필드를 제외하고 전체 컬럼을 직렬화해 수행했다.

내보내기 SQL 비교: 문항 5,225개 유지·그룹 ID 28개 보존원본 보기 (새 창)

내보내기 SQL 비교: 문항 5,225개 유지·그룹 ID 28개 보존

100%원본 보기 (새 창)

확대한 이미지는 상하좌우로 이동할 수 있습니다. 키보드는 이미지 영역에 초점을 두고 방향키를 사용하세요. Esc로 닫습니다.