feat: refine codex live chat context flows

This commit is contained in:
2026-05-08 21:15:51 +09:00
parent 82c0d8a197
commit 442879313f
92 changed files with 14815 additions and 7314 deletions

View File

@@ -190,7 +190,7 @@ function formatPercent(value: number) {
}
function getSubjectQuestionCount(examId: string, subjectId: string) {
return CBT_QUESTIONS.filter((question) => question.examId === examId && question.subjectId === subjectId).length;
return CBT_QUESTIONS.filter((question) => question.isActive && question.examId === examId && question.subjectId === subjectId).length;
}
function getSubjectQuestionSetCount(examId: string, subjectId: string) {

View File

@@ -33,7 +33,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '타당성 검토에서 기술적 타당성을 확인할 때 가장 먼저 보는 관점은 무엇인가요?',
answerValue: '3',
explanation: '현 기술 스택과 인력으로 요구 기능을 구현 가능한지 확인하는 것이 기술적 타당성의 핵심입니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['타당성', '분석'],
correctRate: 0.71,
choices: ['사무실 좌석 배치를 바꾸는 비용', '광고 문구의 완성도', '현재 기술과 인력으로 구현 가능한지 여부', '배경 이미지 해상도'],
@@ -105,7 +105,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: 'DevOps 도입의 직접적인 목표로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '개발과 운영 협업을 강화해 배포 속도와 안정성을 함께 높이는 것이 목적입니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['DevOps', '협업'],
correctRate: 0.74,
choices: ['운영팀을 없앤다', '테스트를 생략한다', '문서를 금지한다', '개발과 운영의 피드백 주기를 단축한다'],
@@ -117,7 +117,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '기존 기능 수정 후 주변 기능이 깨지지 않았는지 확인하는 테스트는 무엇인가요?',
answerValue: '2',
explanation: '회귀 테스트는 변경 이후 기존 기능의 정상 동작을 다시 확인하는 테스트입니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['테스트', '회귀'],
correctRate: 0.77,
choices: ['인수 테스트', '회귀 테스트', '알파 테스트', '베타 테스트'],
@@ -153,7 +153,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '시맨틱 버저닝에서 `2.4.1`의 마지막 숫자가 증가하는 일반적인 경우는 무엇인가요?',
answerValue: '4',
explanation: '패치 버전은 하위 호환 가능한 버그 수정이 있을 때 증가합니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['배포', '버전관리'],
correctRate: 0.72,
choices: ['대규모 구조 개편이 있을 때', '하위 호환이 깨지는 변경일 때', '새로운 주요 기능 묶음을 추가할 때', '하위 호환 가능한 버그 수정일 때'],
@@ -189,7 +189,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '집계 결과에 조건을 적용할 때 `WHERE` 대신 주로 사용하는 절은 무엇인가요?',
answerValue: '4',
explanation: '집계 이후의 그룹 조건은 HAVING 절에서 처리합니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['SQL', '집계'],
correctRate: 0.79,
choices: ['ORDER BY', 'LIMIT', 'GROUP SETS', 'HAVING'],
@@ -201,7 +201,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '공통 키가 있는 행만 결과로 가져오려면 어떤 조인을 사용해야 하나요?',
answerValue: '1',
explanation: 'INNER JOIN은 양쪽 테이블에서 조건이 일치하는 행만 반환합니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['SQL', '조인'],
correctRate: 0.81,
choices: ['INNER JOIN', 'LEFT OUTER JOIN', 'CROSS JOIN', 'SELF JOIN'],
@@ -237,7 +237,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '재귀 함수가 무한 호출되지 않도록 반드시 갖춰야 하는 요소는 무엇인가요?',
answerValue: '1',
explanation: '재귀 종료 조건(base case)이 있어야 반복 호출이 멈춥니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['기초', '재귀'],
correctRate: 0.82,
choices: ['종료 조건', '전역 변수', '배열 정렬', 'GUI 이벤트'],
@@ -273,7 +273,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '데이터와 메서드를 하나의 단위로 묶고 외부 접근을 제한하는 개념은 무엇인가요?',
answerValue: '3',
explanation: '캡슐화는 내부 구현을 숨기고 필요한 인터페이스만 노출합니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['객체지향', '캡슐화'],
correctRate: 0.78,
choices: ['오버로딩', '추상화', '캡슐화', '가비지 컬렉션'],
@@ -285,7 +285,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '선입선출(FIFO) 구조로 동작하는 자료구조는 무엇인가요?',
answerValue: '2',
explanation: 'Queue는 먼저 들어온 데이터가 먼저 나가는 FIFO 구조입니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['자료구조', '큐'],
correctRate: 0.8,
choices: ['Stack', 'Queue', 'Tree', 'Graph'],
@@ -309,7 +309,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '변경관리(Change Management)의 핵심 목적은 무엇인가요?',
answerValue: '4',
explanation: '변경 요청을 통제해 서비스 영향과 위험을 줄이려는 것이 핵심입니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['운영', '변경관리'],
correctRate: 0.73,
choices: ['문서 작성을 금지한다', '모든 변경을 즉시 반영한다', '개발 서버만 유지한다', '변경 영향과 승인 절차를 관리한다'],
@@ -333,7 +333,7 @@ export const CBT_BONUS_QUESTION_SEEDS: BonusQuestionSeed[] = [
body: '최소 권한 원칙(Principle of Least Privilege)의 설명으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '업무 수행에 필요한 최소한의 권한만 부여해야 보안 위험을 줄일 수 있습니다.',
difficulty: 'easy',
difficulty: 'medium',
tags: ['보안', '권한'],
correctRate: 0.76,
choices: ['필요한 최소 권한만 부여한다', '관리자 권한을 기본값으로 준다', '모든 로그를 삭제한다', '암호를 화면에 표시한다'],

View File

@@ -1,5 +1,6 @@
import type { ExamCategory, QuestionRecord, QuestionSet, Subject } from './cbtTypes';
import { CBT_BONUS_QUESTION_SEEDS } from './cbtBonusQuestionSeeds';
import { CBT_SUBJECT_EXPANSION_QUESTION_SEEDS } from './cbtSubjectExpansionSeeds';
type QuestionSeed = Omit<QuestionRecord, 'choices' | 'sourceLabel' | 'examId' | 'type' | 'isActive'> & {
examId?: string;
@@ -10,6 +11,7 @@ type QuestionSeed = Omit<QuestionRecord, 'choices' | 'sourceLabel' | 'examId' |
const ENGINEER_SOURCE_CORE = '비공식 재구성 문제집';
const ENGINEER_SOURCE_PRACTICE = '비공식 실전형 문제집';
const WEB_SOURCE = '공개 허용 샘플 형식';
const WEB_SOURCE_ADVANCED = '공개 허용 심화 샘플 형식';
export const CBT_EXAMS: ExamCategory[] = [
{ id: 'engineer-info', label: '정보처리기사' },
@@ -60,9 +62,26 @@ export const CBT_QUESTION_SETS: QuestionSet[] = [
{ id: 'system-security', examId: 'engineer-info', subjectId: 'system', label: '보안/위험 문제집', sourceLabel: ENGINEER_SOURCE_PRACTICE },
{ id: 'system-infra', examId: 'engineer-info', subjectId: 'system', label: '인프라/운영 문제집', sourceLabel: ENGINEER_SOURCE_PRACTICE },
{ id: 'web-core', examId: 'web-general', subjectId: 'html-css', label: '입문 문제집', sourceLabel: WEB_SOURCE },
{ id: 'web-layout', examId: 'web-general', subjectId: 'html-css', label: '레이아웃 문제집', sourceLabel: WEB_SOURCE_ADVANCED },
{ id: 'web-accessibility', examId: 'web-general', subjectId: 'html-css', label: '접근성 문제집', sourceLabel: WEB_SOURCE_ADVANCED },
{ id: 'web-responsive', examId: 'web-general', subjectId: 'html-css', label: '반응형 문제집', sourceLabel: WEB_SOURCE_ADVANCED },
{ id: 'web-performance', examId: 'web-general', subjectId: 'html-css', label: '성능 문제집', sourceLabel: WEB_SOURCE_ADVANCED },
{ id: 'web-browser', examId: 'web-general', subjectId: 'html-css', label: '브라우저/모바일 문제집', sourceLabel: WEB_SOURCE_ADVANCED },
];
const QUESTION_SET_SOURCE_MAP = new Map(CBT_QUESTION_SETS.map((item) => [item.id, item.sourceLabel]));
const INACTIVE_QUESTION_IDS = new Set([
'dev-core-2',
'dev-core-2-v1',
'dev-core-2-v2',
'dev-core-2-v3',
'programming-core-2',
'programming-core-2-v1',
'programming-core-2-v2',
'programming-core-2-v3',
'web-core-1',
'web-core-3',
]);
function buildQuestion(seed: QuestionSeed): QuestionRecord {
return {
@@ -78,7 +97,7 @@ function buildQuestion(seed: QuestionSeed): QuestionRecord {
sourceLabel: seed.sourceLabel ?? QUESTION_SET_SOURCE_MAP.get(seed.setId) ?? ENGINEER_SOURCE_PRACTICE,
tags: seed.tags,
correctRate: seed.correctRate,
isActive: true,
isActive: !INACTIVE_QUESTION_IDS.has(seed.id),
choices: seed.choices.map((label, index) => ({
value: String(index + 1),
label,
@@ -1098,6 +1117,7 @@ export const CBT_QUESTIONS: QuestionRecord[] = [
...QUESTION_SEEDS,
...ENGINEER_VARIANT_QUESTION_SEEDS,
...CBT_BONUS_QUESTION_SEEDS,
...CBT_SUBJECT_EXPANSION_QUESTION_SEEDS,
].map(buildQuestion);
export const QUICK_QUESTION_COUNTS = [10, 20, 40, 60, 80];

View File

@@ -0,0 +1,655 @@
type BonusQuestionSeed = {
id: string;
examId?: string;
subjectId: string;
setId: string;
body: string;
answerValue: string;
explanation: string;
difficulty: 'easy' | 'medium' | 'hard';
tags: string[];
correctRate: number;
choices: [string, string, string, string];
sourceLabel?: string;
};
export const CBT_SUBJECT_EXPANSION_QUESTION_SEEDS: BonusQuestionSeed[] = [
{
id: 'algo-core-9',
subjectId: 'algo',
setId: 'algo-core',
body: '요구사항 검증 회의에서 모호한 표현을 우선 수정해야 하는 가장 직접적인 이유는 무엇인가요?',
answerValue: '2',
explanation: '모호한 요구사항은 구현과 테스트 기준을 흐리게 만들어 해석 차이를 키웁니다.',
difficulty: 'medium',
tags: ['요구사항', '검증'],
correctRate: 0.62,
choices: ['화면 수를 줄이기 위해', '구현자마다 다른 해석이 생기지 않게 하려고', '배포 속도를 높이기 위해', 'DB 정규화를 생략하려고'],
},
{
id: 'algo-core-10',
subjectId: 'algo',
setId: 'algo-core',
body: '현행 업무 분석에서 AS-IS와 TO-BE를 함께 정리하는 이유로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '현재 상태와 목표 상태를 나란히 봐야 개선 범위와 변경 포인트를 명확히 잡을 수 있습니다.',
difficulty: 'medium',
tags: ['현행분석', '요구사항'],
correctRate: 0.58,
choices: ['소스 코드를 자동 생성하려고', '운영 서버를 줄이려고', '테스트를 생략하려고', '개선 대상과 전환 범위를 비교하려고'],
},
{
id: 'algo-pattern-9',
subjectId: 'algo',
setId: 'algo-pattern',
body: '객체 생성 절차가 복잡하고 생성 단계 조합이 많을 때 적용하기 좋은 패턴은 무엇인가요?',
answerValue: '3',
explanation: 'Builder 패턴은 복잡한 생성 절차를 단계별로 분리해 조합하기 좋습니다.',
difficulty: 'medium',
tags: ['패턴', '생성'],
correctRate: 0.56,
choices: ['State', 'Facade', 'Builder', 'Observer'],
},
{
id: 'algo-quality-9',
subjectId: 'algo',
setId: 'algo-quality',
body: '마이크로서비스 간 결합이 과도할 때 주로 나타나는 문제로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '서비스 간 의존이 강하면 한 서비스 변경이 연쇄 장애나 배포 제약으로 이어집니다.',
difficulty: 'hard',
tags: ['아키텍처', '품질'],
correctRate: 0.43,
choices: ['하나의 변경이 여러 서비스 배포를 동시에 요구한다', '정적 파일 캐시 효율이 높아진다', '데이터 모델이 항상 단순해진다', '문서 작성량이 자동 감소한다'],
},
{
id: 'dev-core-9',
subjectId: 'dev',
setId: 'dev-core',
body: '점증적(Incremental) 개발 모델을 적용할 때 기대 효과로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '작은 단위로 기능을 나눠 제공하면 사용자 피드백을 더 빠르게 반영할 수 있습니다.',
difficulty: 'medium',
tags: ['개발방법론', '점증적'],
correctRate: 0.6,
choices: ['모든 기능을 마지막에만 검증한다', '우선순위 높은 기능부터 점진적으로 제공한다', '요구사항 변경을 금지한다', '배포를 한 번만 수행한다'],
},
{
id: 'dev-core-10',
subjectId: 'dev',
setId: 'dev-core',
body: '사용자 스토리(User Story)에 수용 기준(Acceptance Criteria)을 함께 적는 이유는 무엇인가요?',
answerValue: '3',
explanation: '수용 기준이 있어야 완료 판단 기준과 테스트 관점을 구체화할 수 있습니다.',
difficulty: 'medium',
tags: ['애자일', '요구사항'],
correctRate: 0.64,
choices: ['회의 시간을 늘리려고', '디자인 시안을 줄이려고', '완료 조건과 검증 기준을 명확히 하려고', '소스 저장소를 분리하려고'],
},
{
id: 'dev-test-9',
subjectId: 'dev',
setId: 'dev-test',
body: '동등 분할 기법의 주된 목적은 무엇인가요?',
answerValue: '1',
explanation: '유사하게 동작할 것으로 기대되는 입력 그룹을 나눠 대표값으로 효율적으로 테스트합니다.',
difficulty: 'medium',
tags: ['테스트', '블랙박스'],
correctRate: 0.63,
choices: ['유사 입력군을 대표값으로 묶어 테스트 효율을 높인다', '코드 실행 경로를 모두 시각화한다', '배포 파이프라인을 생략한다', '운영 로그를 삭제한다'],
},
{
id: 'dev-test-10',
subjectId: 'dev',
setId: 'dev-test',
body: '상태 전이 테스트가 특히 유용한 시스템 사례로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '로그인 잠금, 주문 상태 전환처럼 상태와 이벤트 조합이 많은 기능에서 효과적입니다.',
difficulty: 'medium',
tags: ['테스트', '상태전이'],
correctRate: 0.57,
choices: ['정적 소개 페이지', '이미지 파일 압축 작업', '컬러 팔레트 정리', '주문 상태가 단계별로 바뀌는 업무 흐름'],
},
{
id: 'dev-release-9',
subjectId: 'dev',
setId: 'dev-release',
body: '지속적 전달(CD) 환경에서 배포 승인을 별도 단계로 두는 이유는 무엇인가요?',
answerValue: '2',
explanation: '자동 검증을 통과해도 운영 반영 시점과 위험도를 사람이 최종 판단할 수 있어야 합니다.',
difficulty: 'medium',
tags: ['배포', 'CD'],
correctRate: 0.59,
choices: ['브랜치 이름을 짧게 만들려고', '운영 반영 타이밍과 위험을 통제하려고', '테스트 데이터를 삭제하려고', '형상 관리를 중단하려고'],
},
{
id: 'dev-release-10',
subjectId: 'dev',
setId: 'dev-release',
body: '릴리즈 전 체크리스트에 데이터 마이그레이션 검증을 넣어야 하는 이유는 무엇인가요?',
answerValue: '1',
explanation: '스키마나 데이터 구조 변경은 기능 이상보다 더 치명적인 운영 장애로 이어질 수 있습니다.',
difficulty: 'hard',
tags: ['배포', '데이터'],
correctRate: 0.46,
choices: ['운영 데이터 손상과 롤백 위험을 줄이기 위해', '화면 색상을 맞추기 위해', '개발자 수를 줄이기 위해', '문서 버전을 숨기기 위해'],
},
{
id: 'dev-release-11',
subjectId: 'dev',
setId: 'dev-release',
body: '형상 식별(Configuration Identification)의 설명으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '어떤 산출물을 관리 대상으로 삼고 버전과 구성 단위를 구분할지 정하는 단계입니다.',
difficulty: 'medium',
tags: ['형상관리', '구성관리'],
correctRate: 0.55,
choices: ['모든 문서를 폐기하는 절차', '배포 후 로그만 남기는 절차', '관리 대상 산출물과 버전 기준을 정의하는 활동', '테스트를 운영에서만 수행하는 방식'],
},
{
id: 'db-core-9',
subjectId: 'db',
setId: 'db-core',
body: '후보키(Candidate Key)의 설명으로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '후보키는 유일성과 최소성을 만족하는 키 후보이며 이 중 하나가 기본키가 됩니다.',
difficulty: 'medium',
tags: ['키', '모델링'],
correctRate: 0.6,
choices: ['반드시 외래키를 포함하는 키', '정렬용으로만 쓰는 컬럼', 'NULL이 허용되는 식별자', '유일성과 최소성을 만족하는 식별자 후보'],
},
{
id: 'db-core-10',
subjectId: 'db',
setId: 'db-core',
body: '이행 함수 종속을 제거하는 정규화 단계는 무엇인가요?',
answerValue: '2',
explanation: '제3정규형(3NF)은 이행 함수 종속을 제거하는 단계입니다.',
difficulty: 'medium',
tags: ['정규화', '모델링'],
correctRate: 0.57,
choices: ['제1정규형', '제3정규형', 'BCNF', '제5정규형'],
},
{
id: 'db-sql-9',
subjectId: 'db',
setId: 'db-sql',
body: '윈도우 함수 `ROW_NUMBER()`를 주로 사용하는 상황으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '그룹 내 순번 계산이나 상위 N건 추출처럼 행 순서를 함께 다뤄야 할 때 유용합니다.',
difficulty: 'medium',
tags: ['SQL', '윈도우함수'],
correctRate: 0.54,
choices: ['정렬 기준에 따라 행 순번을 계산할 때', '테이블을 삭제할 때', '인덱스를 비활성화할 때', '트랜잭션을 커밋할 때'],
},
{
id: 'db-sql-10',
subjectId: 'db',
setId: 'db-sql',
body: '실행 계획을 확인하는 가장 직접적인 이유는 무엇인가요?',
answerValue: '3',
explanation: '실제 접근 경로와 비용이 어떻게 계산됐는지 봐야 느린 쿼리의 원인을 찾을 수 있습니다.',
difficulty: 'hard',
tags: ['SQL', '튜닝'],
correctRate: 0.42,
choices: ['UI 레이아웃을 조정하려고', '샘플 데이터를 지우려고', '조회 경로와 병목 구간을 분석하려고', '백업 주기를 바꾸려고'],
},
{
id: 'db-ops-9',
subjectId: 'db',
setId: 'db-ops',
body: 'Repeatable Read 격리 수준이 주로 방지하려는 현상은 무엇인가요?',
answerValue: '2',
explanation: '같은 행을 두 번 읽을 때 값이 바뀌는 비반복 읽기 현상을 막는 데 초점이 있습니다.',
difficulty: 'medium',
tags: ['트랜잭션', '격리수준'],
correctRate: 0.53,
choices: ['Dirty Write', 'Non-repeatable Read', 'Hash Collision', 'Full Scan'],
},
{
id: 'db-ops-10',
subjectId: 'db',
setId: 'db-ops',
body: '포인트 인 타임 복구(PITR)가 필요한 상황으로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '잘못된 대량 삭제처럼 특정 시점 이전으로 복구해야 할 때 PITR이 유용합니다.',
difficulty: 'hard',
tags: ['백업', '복구'],
correctRate: 0.45,
choices: ['화면 정렬 순서를 바꿀 때', '정적 파일을 압축할 때', '새 테마를 적용할 때', '특정 시점 직전 상태로 데이터를 되돌려야 할 때'],
},
{
id: 'programming-core-9',
subjectId: 'programming',
setId: 'programming-core',
body: '포인터 연산을 잘못 사용했을 때 발생하기 쉬운 문제로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '잘못된 주소 접근은 메모리 오류와 비정상 종료를 유발할 수 있습니다.',
difficulty: 'medium',
tags: ['C', '포인터'],
correctRate: 0.57,
choices: ['의도하지 않은 메모리 영역 접근', '컴파일러 업데이트 자동 수행', '정렬 알고리즘 단순화', '함수 수 감소'],
},
{
id: 'programming-core-10',
subjectId: 'programming',
setId: 'programming-core',
body: 'Call by Reference 방식의 특징으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '참조를 전달하므로 함수 내부 변경이 원본 데이터에 반영될 수 있습니다.',
difficulty: 'medium',
tags: ['기초', '함수'],
correctRate: 0.63,
choices: ['항상 복사본만 바뀐다', '지역 변수를 만들 수 없다', '원본 데이터가 직접 수정될 수 있다', '배열을 전달할 수 없다'],
},
{
id: 'programming-oo-9',
subjectId: 'programming',
setId: 'programming-oo',
body: '인터페이스를 우선 설계하는 이유로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '구현보다 계약을 먼저 고정하면 교체 가능성과 테스트 용이성이 높아집니다.',
difficulty: 'medium',
tags: ['객체지향', '인터페이스'],
correctRate: 0.61,
choices: ['상속 구조를 없애려고', '구현체 교체와 의존성 분리를 쉽게 하려고', '예외 처리를 금지하려고', '모든 메서드를 static으로 만들려고'],
},
{
id: 'programming-oo-10',
subjectId: 'programming',
setId: 'programming-oo',
body: '추상화가 잘된 설계의 효과로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '핵심 개념과 계약만 드러내고 세부 구현을 숨겨 변경 영향을 줄일 수 있습니다.',
difficulty: 'hard',
tags: ['객체지향', '추상화'],
correctRate: 0.45,
choices: ['모든 필드를 public으로 노출한다', '런타임 비용을 항상 0으로 만든다', '소스 파일 수를 절반으로 줄인다', '세부 구현 변경이 외부 사용처에 덜 번지게 한다'],
},
{
id: 'programming-script-9',
subjectId: 'programming',
setId: 'programming-script',
body: '이진 탐색의 전제 조건으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '이진 탐색은 탐색 대상이 정렬돼 있어야 절반씩 범위를 줄일 수 있습니다.',
difficulty: 'medium',
tags: ['알고리즘', '탐색'],
correctRate: 0.62,
choices: ['데이터가 정렬돼 있어야 한다', '항상 연결 리스트여야 한다', '재귀를 사용할 수 없다', '중복 데이터가 없어야만 한다'],
},
{
id: 'programming-script-10',
subjectId: 'programming',
setId: 'programming-script',
body: '깊이 우선 탐색(DFS)에 대한 설명으로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '가능한 한 깊게 내려간 뒤 더 갈 곳이 없으면 되돌아오는 탐색입니다.',
difficulty: 'medium',
tags: ['알고리즘', '그래프'],
correctRate: 0.6,
choices: ['항상 최단 경로를 보장한다', '한 경로를 끝까지 탐색한 뒤 되돌아온다', '큐만 사용해야 한다', '정렬된 배열에서만 동작한다'],
},
{
id: 'programming-script-11',
subjectId: 'programming',
setId: 'programming-script',
body: '해시 함수 품질이 낮을 때 생기기 쉬운 문제로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '충돌이 많아지면 평균 접근 성능이 떨어지고 해시 테이블 장점이 약해집니다.',
difficulty: 'hard',
tags: ['자료구조', '해시'],
correctRate: 0.44,
choices: ['정렬이 자동으로 보장된다', '메모리 사용량이 0이 된다', '재귀 호출이 불가능해진다', '충돌 증가로 탐색 성능이 저하된다'],
},
{
id: 'system-core-9',
subjectId: 'system',
setId: 'system-core',
body: '리스크 등록부(Risk Register)에 우선 포함해야 할 항목으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '위험 내용, 영향도, 대응 계획, 담당자 같은 정보가 있어야 관리가 가능합니다.',
difficulty: 'medium',
tags: ['위험관리', '프로젝트관리'],
correctRate: 0.61,
choices: ['디자인 시안 배경색', '팀 점심 메뉴', '위험 항목과 대응 전략', '브라우저 북마크 목록'],
},
{
id: 'system-core-10',
subjectId: 'system',
setId: 'system-core',
body: '변경 영향도 분석을 생략했을 때 발생하기 쉬운 문제는 무엇인가요?',
answerValue: '1',
explanation: '연관 시스템과 운영 절차를 빠뜨리면 배포 후 예상치 못한 장애가 발생하기 쉽습니다.',
difficulty: 'hard',
tags: ['변경관리', '운영'],
correctRate: 0.47,
choices: ['연쇄 영향 범위를 놓쳐 장애를 키울 수 있다', '정규화 단계가 자동 감소한다', '테스트 케이스가 자동 작성된다', '모든 승인 절차가 단축된다'],
},
{
id: 'system-security-9',
subjectId: 'system',
setId: 'system-security',
body: '다중 인증(MFA)의 직접적인 효과로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '비밀번호가 노출돼도 추가 인증 수단이 있어 계정 탈취 위험을 낮출 수 있습니다.',
difficulty: 'medium',
tags: ['보안', '인증'],
correctRate: 0.67,
choices: ['세션 저장소를 없앤다', '단일 인증 정보 유출만으로는 로그인하기 어렵게 만든다', '암호화를 대체한다', '방화벽 설정을 불필요하게 만든다'],
},
{
id: 'system-security-10',
subjectId: 'system',
setId: 'system-security',
body: '입력값 검증이 특히 중요한 이유로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '입력 검증은 SQL Injection, XSS 같은 공격 표면을 줄이는 기본 통제입니다.',
difficulty: 'medium',
tags: ['보안', '입력검증'],
correctRate: 0.64,
choices: ['서버 시간을 고정하려고', '디자인 토큰을 통일하려고', '문서 용량을 줄이려고', '악의적 입력으로 인한 취약점 노출을 막으려고'],
},
{
id: 'system-infra-9',
subjectId: 'system',
setId: 'system-infra',
body: '관측 가능성(Observability)을 높이는 데 필요한 축으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '로그, 메트릭, 트레이스를 함께 봐야 분산 환경의 원인 분석이 쉬워집니다.',
difficulty: 'medium',
tags: ['인프라', '관측성'],
correctRate: 0.57,
choices: ['테마, 배경, 아이콘', '문서, 회의록, 공지', '로그, 메트릭, 트레이스', 'CPU, 키보드, 마우스'],
},
{
id: 'system-infra-10',
subjectId: 'system',
setId: 'system-infra',
body: '무중단 배포를 설계할 때 세션 저장소 외부화가 중요한 이유는 무엇인가요?',
answerValue: '1',
explanation: '인스턴스 교체 시 세션이 서버 로컬에 있으면 사용자 연결 상태가 쉽게 끊길 수 있습니다.',
difficulty: 'hard',
tags: ['인프라', '배포'],
correctRate: 0.46,
choices: ['서버 교체 중에도 사용자 세션을 유지하기 쉬워진다', '정규화 단계를 줄일 수 있다', '모든 장애를 예방한다', '쿼리 튜닝이 자동 완료된다'],
},
{
id: 'web-layout-1',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-layout',
body: 'Flex 레이아웃에서 세로 축 정렬을 제어하는 속성으로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '기본 방향이 row일 때 교차 축은 세로 방향이며 `align-items`가 이를 제어합니다.',
difficulty: 'medium',
tags: ['CSS', 'Flexbox'],
correctRate: 0.66,
choices: ['justify-content', 'align-items', 'flex-basis', 'order'],
},
{
id: 'web-layout-2',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-layout',
body: 'CSS Grid에서 열 반복 구성을 정의할 때 가장 자주 사용하는 속성은 무엇인가요?',
answerValue: '3',
explanation: '`grid-template-columns`로 열 개수와 너비 패턴을 지정합니다.',
difficulty: 'medium',
tags: ['CSS', 'Grid'],
correctRate: 0.62,
choices: ['grid-auto-flow', 'place-content', 'grid-template-columns', 'grid-column-end'],
},
{
id: 'web-layout-3',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-layout',
body: '모바일 카드 UI에서 긴 텍스트가 레이아웃을 깨지 않게 처리하는 방법으로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '줄 수 제한이나 줄바꿈 정책을 명확히 둬야 작은 화면에서도 카드 높이 폭주를 막을 수 있습니다.',
difficulty: 'medium',
tags: ['CSS', '모바일'],
correctRate: 0.64,
choices: ['모든 텍스트를 절대 위치로 바꾼다', '폰트 크기를 8px로 고정한다', '스크롤을 막는다', 'line-clamp 또는 적절한 word-break 규칙을 적용한다'],
},
{
id: 'web-layout-4',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-layout',
body: '`position: sticky`가 기대대로 동작하지 않는 대표 원인으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '상위 스크롤 컨테이너와 overflow 조건이 맞지 않으면 sticky 기준이 깨집니다.',
difficulty: 'hard',
tags: ['CSS', '레이아웃'],
correctRate: 0.45,
choices: ['부모의 overflow 조건 때문에 기준 스크롤 영역이 달라진다', 'HTML에 section 태그가 없기 때문이다', '이미지 개수가 많기 때문이다', 'font-weight가 bold이기 때문이다'],
},
{
id: 'web-accessibility-1',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-accessibility',
body: '폼 입력과 라벨을 명시적으로 연결하는 가장 기본적인 방법은 무엇인가요?',
answerValue: '2',
explanation: '`label`의 `for`와 입력 요소의 `id`를 연결하면 스크린리더와 클릭 영역 모두 개선됩니다.',
difficulty: 'medium',
tags: ['HTML', '접근성'],
correctRate: 0.71,
choices: ['placeholder만 넣는다', '`label for`와 `input id`를 연결한다', 'div로만 감싼다', '색상 대비만 높인다'],
},
{
id: 'web-accessibility-2',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-accessibility',
body: '장식용 이미지를 스크린리더가 무시하게 하는 방법으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '의미 없는 장식 이미지는 빈 대체 텍스트로 처리해 불필요한 읽기를 막습니다.',
difficulty: 'medium',
tags: ['HTML', '접근성'],
correctRate: 0.67,
choices: ['title만 넣는다', 'role을 article로 준다', 'alt=\"\"로 둔다', 'font-size를 줄인다'],
},
{
id: 'web-accessibility-3',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-accessibility',
body: '모달이 열렸을 때 키보드 포커스를 모달 내부에 가둬야 하는 이유는 무엇인가요?',
answerValue: '4',
explanation: '배경 UI로 포커스가 빠지면 키보드 사용자와 보조기기 사용자의 맥락이 무너집니다.',
difficulty: 'hard',
tags: ['접근성', 'UI'],
correctRate: 0.48,
choices: ['애니메이션 속도를 올리려고', '스크롤을 완전히 막으려고', '이미지 로딩을 줄이려고', '활성 대화 상자의 상호작용 범위를 명확히 유지하려고'],
},
{
id: 'web-accessibility-4',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-accessibility',
body: '버튼처럼 동작하는 요소를 `div` 대신 `button`으로 만드는 주된 이유는 무엇인가요?',
answerValue: '1',
explanation: '기본 키보드 동작, 포커스, 접근성 의미가 이미 제공되기 때문입니다.',
difficulty: 'medium',
tags: ['HTML', '접근성'],
correctRate: 0.73,
choices: ['기본 상호작용 의미와 키보드 지원을 바로 얻을 수 있어서', 'CSS 파일 개수를 줄여서', '이미지 최적화를 위해서', '로컬스토리지를 쓰기 위해서'],
},
{
id: 'web-accessibility-5',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-accessibility',
body: '색상만으로 오류 상태를 표시하면 안 되는 이유로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '색각 이상 사용자나 보조기기 사용자에게 정보가 전달되지 않을 수 있습니다.',
difficulty: 'medium',
tags: ['접근성', '폼'],
correctRate: 0.69,
choices: ['브라우저가 자동 종료되기 때문에', '색상을 구분하지 못하는 사용자에게 의미가 전달되지 않을 수 있어서', 'HTML 파서 오류가 발생해서', '네트워크 요청이 느려져서'],
},
{
id: 'web-responsive-1',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-responsive',
body: '반응형 웹에서 `meta viewport` 설정이 필요한 가장 직접적인 이유는 무엇인가요?',
answerValue: '3',
explanation: '모바일 브라우저가 레이아웃 폭을 기기 너비 기준으로 해석하게 해야 의도한 반응형이 동작합니다.',
difficulty: 'medium',
tags: ['HTML', '반응형'],
correctRate: 0.68,
choices: ['캐시를 비우기 위해', '애니메이션을 끄기 위해', '기기 너비 기준 초기 배율과 레이아웃 폭을 맞추기 위해', '쿠키를 막기 위해'],
},
{
id: 'web-responsive-2',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-responsive',
body: '작은 화면에서 카드가 너무 촘촘할 때 우선 검토할 CSS 전략으로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '간격, 컬럼 수, 최소 너비를 브레이크포인트별로 조정해야 모바일 가독성이 확보됩니다.',
difficulty: 'medium',
tags: ['CSS', '반응형'],
correctRate: 0.61,
choices: ['모든 카드 높이를 고정한다', '이미지를 삭제한다', '폰트를 임의로 랜덤 변경한다', '브레이크포인트에서 gap과 컬럼 구성을 줄인다'],
},
{
id: 'web-responsive-3',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-responsive',
body: '`clamp()` 함수를 타이포그래피에 사용하는 장점으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '최소값과 최대값을 두고 뷰포트에 따라 유연하게 크기를 조절할 수 있습니다.',
difficulty: 'hard',
tags: ['CSS', '타이포그래피'],
correctRate: 0.47,
choices: ['너무 작거나 큰 값을 막으면서 유동 크기를 줄 수 있다', '이미지를 자동 압축한다', '스크린리더를 비활성화한다', 'DOM 트리를 줄인다'],
},
{
id: 'web-responsive-4',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-responsive',
body: '모바일 브라우저에서 100vh 사용 시 생길 수 있는 대표 문제는 무엇인가요?',
answerValue: '2',
explanation: '주소창 표시/숨김에 따라 실제 보이는 높이와 계산된 vh가 달라 하단 잘림이 생길 수 있습니다.',
difficulty: 'hard',
tags: ['CSS', '모바일'],
correctRate: 0.44,
choices: ['글자 수가 줄어든다', '브라우저 UI 높이 변화로 화면이 잘릴 수 있다', '쿠키 저장이 안 된다', '이미지가 모두 고정된다'],
},
{
id: 'web-performance-1',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-performance',
body: '웹 폰트 로딩으로 인한 렌더링 지연을 줄일 때 검토할 속성으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: '`font-display`를 적절히 설정하면 초기 텍스트 표시 전략을 제어할 수 있습니다.',
difficulty: 'medium',
tags: ['CSS', '성능'],
correctRate: 0.6,
choices: ['object-fit', 'tabindex', 'font-display', 'z-index'],
},
{
id: 'web-performance-2',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-performance',
body: '이미지 지연 로딩(lazy loading)의 직접적인 효과로 가장 적절한 것은 무엇인가요?',
answerValue: '4',
explanation: '초기 뷰포트 밖 이미지를 나중에 불러와 첫 화면 로딩 부담을 줄일 수 있습니다.',
difficulty: 'medium',
tags: ['HTML', '성능'],
correctRate: 0.72,
choices: ['서버 시간을 고정한다', '모든 이미지를 더 크게 만든다', '스크린리더를 끈다', '초기 네트워크 요청량을 줄여 첫 렌더를 가볍게 한다'],
},
{
id: 'web-performance-3',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-performance',
body: 'CLS(Cumulative Layout Shift)를 줄이기 위한 방법으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '이미지와 광고 영역에 미리 크기를 확보해 두면 렌더 후 갑작스러운 밀림을 줄일 수 있습니다.',
difficulty: 'hard',
tags: ['성능', 'CLS'],
correctRate: 0.46,
choices: ['이미지와 동적 영역의 크기를 미리 예약한다', '애니메이션을 모두 제거한다', 'HTML 파일을 여러 개로 분리한다', '모든 버튼을 absolute로 둔다'],
},
{
id: 'web-performance-4',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-performance',
body: '크리티컬 CSS를 인라인으로 우선 제공하는 목적은 무엇인가요?',
answerValue: '2',
explanation: '첫 화면 렌더에 필요한 최소 스타일을 먼저 적용해 초기 표시 속도를 높이기 위함입니다.',
difficulty: 'hard',
tags: ['CSS', '성능'],
correctRate: 0.43,
choices: ['자바스크립트를 금지하려고', '첫 화면 렌더에 필요한 스타일 적용을 앞당기려고', '모든 스타일 파일을 삭제하려고', '폰트 종류를 하나로 제한하려고'],
},
{
id: 'web-browser-1',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-browser',
body: '브라우저 기본 스타일 차이로 인한 오차를 줄이는 일반적인 접근으로 가장 적절한 것은 무엇인가요?',
answerValue: '3',
explanation: 'reset 또는 normalize 스타일을 적용해 기본 마진과 요소 표현 차이를 줄입니다.',
difficulty: 'medium',
tags: ['CSS', '브라우저호환성'],
correctRate: 0.65,
choices: ['모든 태그를 span으로 바꾼다', '이미지 파일명을 짧게 만든다', 'reset/normalize 스타일을 적용한다', '스크롤을 비활성화한다'],
},
{
id: 'web-browser-2',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-browser',
body: '특정 CSS 기능 사용 전 브라우저 지원 범위를 확인해야 하는 이유는 무엇인가요?',
answerValue: '4',
explanation: '지원하지 않는 환경에서는 레이아웃이 깨지거나 대체 스타일이 필요할 수 있습니다.',
difficulty: 'medium',
tags: ['CSS', '호환성'],
correctRate: 0.66,
choices: ['폰트 파일 수를 늘리려고', 'DOM 깊이를 줄이려고', '테스트 케이스를 삭제하려고', '일부 사용자 환경에서 기능이 동작하지 않을 수 있어서'],
},
{
id: 'web-browser-3',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-browser',
body: '입력 폼 자동완성 스타일이 브라우저별로 다를 때 우선 고려할 점으로 가장 적절한 것은 무엇인가요?',
answerValue: '1',
explanation: '브라우저 기본 UI는 완전한 통제가 어려우므로 사용성 저하 없이 허용 범위를 정하는 접근이 필요합니다.',
difficulty: 'hard',
tags: ['HTML', '브라우저호환성'],
correctRate: 0.42,
choices: ['브라우저 기본 UI를 모두 제거하려 하기보다 허용 범위를 정한다', 'label 태그를 없앤다', 'submit 버튼을 숨긴다', '모든 입력을 textarea로 바꾼다'],
},
{
id: 'web-browser-4',
examId: 'web-general',
subjectId: 'html-css',
setId: 'web-browser',
body: '모바일 Safari에서 터치 영역이 작게 느껴질 때 우선 검토할 항목으로 가장 적절한 것은 무엇인가요?',
answerValue: '2',
explanation: '시각적 크기보다 실제 패딩과 line-height, 최소 터치 크기 확보가 중요합니다.',
difficulty: 'medium',
tags: ['모바일', 'UX'],
correctRate: 0.7,
choices: ['배경색만 바꾼다', '버튼 패딩과 실제 클릭 영역 크기를 늘린다', '스크롤을 잠근다', '폰트를 모두 소문자로 바꾼다'],
},
];