feat(prototype): 중1~고3 샘플 ebook 6권 + PS 제거 + 복습캘린더 + 태그 삭제

### 샘플 ebook (대회 시연용 B2B 데모)
- /exams 카탈로그: API 호출/필터 제거, EBOOK_LIST 기반 6카드 정적 렌더
- /exams/sample-ebook/[id] 동적 라우트: 중1~고3 수학 6권 × 30문항 + 해설
- 교육과정별 단원 커버 (중1: 정수·일차방정식 ~ 고3: 극한·벡터)

### PS (Solved.ac) 도메인 제거
- backend: PsModule/PsService/PsController/SolvedAcClient 전체 삭제, app.module 정리
- frontend: /ps 라우트, PsTabs, SideNav/BottomNav PS 항목, api.ts PS 타입 전부 제거
- onboarding: ps.sync() 호출 제거

### 복습큐 → 복습캘린더
- backend: GET /reviews/calendar?year&month, GET /reviews/day?date API 추가
- frontend: 대시보드 "오늘 복습 큐" 카드 → ReviewCalendar 위젯 교체
  - 월간 7열 그리드, 날짜 클릭 시 해당일 복습 목록 인라인 패널
  - 밀린 날 warning / 완료 날 success / 오늘 하이라이트
  - 0건이면 "쉬어가자" 안내

### 태그 삭제 기능
- subjects/page.tsx: 태그 행 × 아이콘 → ConfirmDialog (danger) → DELETE /tags/:id
- 낙관적 업데이트 + 실패 시 롤백

backend tsc + frontend tsc 클린.
This commit is contained in:
reloop
2026-04-16 10:44:55 +09:00
parent 57cd305166
commit 03ce2c64fd
30 changed files with 2424 additions and 3080 deletions

View File

@@ -1,20 +1,14 @@
'use client';
import React, { useCallback, useEffect, useState } from 'react';
import React from 'react';
import { useRouter } from 'next/navigation';
import styled from 'styled-components';
import AppShell from '@/components/layout/AppShell';
import { Icon } from '@/components/ui/Icon';
import Select from '@/components/ui/Select';
import { Badge, Button, Card, Label, PageHeader } from '@/components/ui/primitives';
import { api, type ProblemSetSummary } from '@/lib/api';
import { Badge, Button, Card, PageHeader } from '@/components/ui/primitives';
import { theme } from '@/styles/theme';
const YEAR_FILTERS = [2026, 2025] as const;
const SUBJECT_FILTERS = ['전체', '수학'] as const;
type YearFilter = number | 'all';
type SubjectFilter = (typeof SUBJECT_FILTERS)[number];
import { EBOOK_LIST } from './sample-ebook/data/index';
import type { EbookMeta } from './sample-ebook/data/index';
export default function ExamsPage() {
return (
@@ -26,40 +20,6 @@ export default function ExamsPage() {
function ExamsBody() {
const router = useRouter();
const [problemSets, setProblemSets] = useState<ProblemSetSummary[] | null>(null);
const [error, setError] = useState<string | null>(null);
const [selectedYear, setSelectedYear] = useState<YearFilter>('all');
const [selectedSubject, setSelectedSubject] = useState<SubjectFilter>('전체');
const [reloadKey, setReloadKey] = useState(0);
const loadProblemSets = useCallback(() => {
let active = true;
setProblemSets(null);
setError(null);
api
.get<ProblemSetSummary[]>('/problem-sets', {
params: {
year: selectedYear === 'all' ? undefined : selectedYear,
subjectName: selectedSubject === '전체' ? undefined : selectedSubject,
},
})
.then((response) => {
if (!active) return;
setProblemSets(response.data);
})
.catch(() => {
if (!active) return;
setError('문제집 목록을 불러오지 못했어. 다시 시도해줘.');
});
return () => {
active = false;
};
}, [selectedSubject, selectedYear]);
useEffect(() => loadProblemSets(), [loadProblemSets, reloadKey]);
return (
<Wrap>
@@ -67,126 +27,61 @@ function ExamsBody() {
<PageHeader
eyebrow="Exams"
title="모의고사 문제집"
subtitle="기출 문제집을 선택해 실전처럼 풀어봐"
subtitle="학년별 샘플 ebook을 선택해 문제를 풀어봐"
/>
</HeaderCard>
<FilterCard>
<FilterRow>
<FilterField>
<Label></Label>
<FieldSelect
value={selectedYear}
onChange={(value) => setSelectedYear(value as YearFilter)}
options={[
{ label: '전체', value: 'all' as const },
...YEAR_FILTERS.map((year) => ({ label: String(year), value: year })),
]}
aria-label="연도 필터"
/>
</FilterField>
<FilterField>
<Label></Label>
<FieldSelect
value={selectedSubject}
onChange={(value) => setSelectedSubject(value as SubjectFilter)}
options={SUBJECT_FILTERS.map((subject) => ({
label: subject,
value: subject,
}))}
aria-label="과목 필터"
/>
</FilterField>
</FilterRow>
</FilterCard>
{error ? (
<>
<Grid>
<SampleEbookCard router={router} />
</Grid>
<StateCard role="alert">
<StateIcon>
<Icon name="info" size={24} />
</StateIcon>
<StateTitle> </StateTitle>
<StateText>{error}</StateText>
<Button type="button" $variant="secondary" onClick={() => setReloadKey((prev) => prev + 1)}>
</Button>
</StateCard>
</>
) : problemSets === null ? (
<>
<Grid>
<SampleEbookCard router={router} />
</Grid>
<StateCard>
<StateIcon>
<Icon name="clock" size={24} />
</StateIcon>
<StateTitle> </StateTitle>
<StateText> .</StateText>
</StateCard>
</>
) : problemSets.length === 0 ? (
<>
<Grid>
<SampleEbookCard router={router} />
</Grid>
<StateCard>
<StateIcon>
<Icon name="book-open-text" size={24} />
</StateIcon>
<StateTitle> </StateTitle>
<StateText> .</StateText>
</StateCard>
</>
) : (
<Grid>
<SampleEbookCard router={router} />
{problemSets.map((problemSet) => {
const isAutoGradeUnavailable =
(problemSet.problems?.length ?? 0) > 0 &&
problemSet.problems?.every((problem) => problem.needsReview);
return (
<ExamCard key={problemSet.id}>
<CardHeader>
<CardTitle>{problemSet.title}</CardTitle>
{isAutoGradeUnavailable ? (
<MutedBadge $variant="default"> </MutedBadge>
) : null}
</CardHeader>
<CardMeta>
{problemSet.year} · {problemSet.subjectName} ·{' '}
{(problemSet._count?.problems ?? 0).toLocaleString()}
</CardMeta>
<CardFooter>
<InfoLine>
<Icon name="clock" size={16} />
</InfoLine>
<Button
type="button"
$variant="secondary"
onClick={() => router.push(`/study/exam/${problemSet.id}`)}
>
</Button>
</CardFooter>
</ExamCard>
);
})}
</Grid>
)}
<Grid>
{EBOOK_LIST.map((ebook) => (
<SampleEbookCard key={ebook.id} ebook={ebook} router={router} />
))}
</Grid>
</Wrap>
);
}
// ─── 샘플 ebook 카드 ─────────────────────────────────────────────────────────
function SampleEbookCard({
ebook,
router,
}: {
ebook: EbookMeta;
router: ReturnType<typeof useRouter>;
}) {
return (
<SampleCard>
<SampleCardHeader>
<CardTitle>{ebook.title}</CardTitle>
<SampleBadge $variant="default">
<Icon name="book-open-text" size={11} />
·
</SampleBadge>
</SampleCardHeader>
<CardMeta>
{ebook.grade} · {ebook.subtitle.split(' ').slice(2).join(' ')} · {ebook.problemCount}
</CardMeta>
<CardFooter>
<InfoLine>
<Icon name="book-open-text" size={16} />
</InfoLine>
<Button
type="button"
$variant="primary"
onClick={() => router.push(`/exams/sample-ebook/${ebook.id}`)}
>
</Button>
</CardFooter>
</SampleCard>
);
}
// ─── 스타일 ──────────────────────────────────────────────────────────────────
const Wrap = styled.div`
display: flex;
flex-direction: column;
@@ -200,33 +95,6 @@ const HeaderCard = styled(Card)`
border-color: ${theme.color.borderSoftAlpha};
`;
const FilterCard = styled(Card)`
background: rgba(255, 255, 255, 0.02);
border-color: ${theme.color.borderSoftAlpha};
`;
const FilterRow = styled.div`
display: grid;
grid-template-columns: repeat(2, minmax(0, 240px));
gap: 16px;
@media (max-width: ${theme.breakpoint.tablet}) {
grid-template-columns: 1fr;
}
`;
const FilterField = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
`;
const FieldSelect = styled(Select)`
width: 100%;
background: rgba(255, 255, 255, 0.03);
border-color: ${theme.color.borderSoftAlpha};
`;
const Grid = styled.div`
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -237,131 +105,6 @@ const Grid = styled.div`
}
`;
const ExamCard = styled(Card)`
display: flex;
flex-direction: column;
gap: 16px;
min-height: 220px;
justify-content: space-between;
background:
radial-gradient(circle at top right, rgba(79, 70, 229, 0.12), transparent 30%),
rgba(255, 255, 255, 0.02);
border-color: ${theme.color.borderSoftAlpha};
`;
const CardHeader = styled.div`
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
@media (max-width: ${theme.breakpoint.mobile}) {
flex-direction: column;
}
`;
const CardTitle = styled.h2`
font-size: 20px;
line-height: 1.45;
color: ${theme.color.textBright};
`;
const MutedBadge = styled(Badge)`
color: ${theme.color.textSub};
background: rgba(255, 255, 255, 0.06);
border-color: ${theme.color.borderSoftAlpha};
`;
const CardMeta = styled.p`
color: ${theme.color.textSub};
font-size: 14px;
line-height: 1.6;
`;
const CardFooter = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: auto;
@media (max-width: ${theme.breakpoint.mobile}) {
flex-direction: column;
align-items: stretch;
}
`;
const InfoLine = styled.span`
display: inline-flex;
align-items: center;
gap: 8px;
color: ${theme.color.textSub};
font-size: 13px;
`;
const StateCard = styled(Card)`
min-height: 260px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
text-align: center;
background: rgba(255, 255, 255, 0.02);
border-color: ${theme.color.borderSoftAlpha};
`;
const StateIcon = styled.div`
width: 52px;
height: 52px;
display: grid;
place-items: center;
border-radius: 16px;
background: rgba(79, 70, 229, 0.12);
color: ${theme.color.textBright};
`;
const StateTitle = styled.h2`
font-size: 20px;
color: ${theme.color.textBright};
`;
const StateText = styled.p`
color: ${theme.color.textSub};
`;
// ─── 샘플 ebook 카드 ─────────────────────────────────────────────────────────
function SampleEbookCard({ router }: { router: ReturnType<typeof useRouter> }) {
return (
<SampleCard>
<SampleCardHeader>
<CardTitle>[] ebook</CardTitle>
<SampleBadge $variant="default">
<Icon name="book-open-text" size={11} />
·
</SampleBadge>
</SampleCardHeader>
<CardMeta>2026 · · 5</CardMeta>
<CardFooter>
<InfoLine>
<Icon name="book-open-text" size={16} />
</InfoLine>
<Button
type="button"
$variant="primary"
onClick={() => router.push('/exams/sample-ebook')}
>
</Button>
</CardFooter>
</SampleCard>
);
}
const SampleCard = styled(Card)`
display: flex;
flex-direction: column;
@@ -389,14 +132,54 @@ const SampleCard = styled(Card)`
}
`;
const SampleCardHeader = styled(CardHeader)`
const SampleCardHeader = styled.div`
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
@media (max-width: ${theme.breakpoint.mobile}) {
flex-direction: column;
}
`;
const SampleBadge = styled(MutedBadge)`
const CardTitle = styled.h2`
font-size: 20px;
line-height: 1.45;
color: ${theme.color.textBright};
`;
const SampleBadge = styled(Badge)`
background: rgba(124, 58, 237, 0.18);
border-color: rgba(124, 58, 237, 0.4);
color: ${theme.color.accent2};
white-space: nowrap;
flex-shrink: 0;
`;
const CardMeta = styled.p`
color: ${theme.color.textSub};
font-size: 14px;
line-height: 1.6;
`;
const CardFooter = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: auto;
@media (max-width: ${theme.breakpoint.mobile}) {
flex-direction: column;
align-items: stretch;
}
`;
const InfoLine = styled.span`
display: inline-flex;
align-items: center;
gap: 8px;
color: ${theme.color.textSub};
font-size: 13px;
`;

View File

@@ -1,89 +1,53 @@
'use client';
import React, { useCallback, useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import styled, { css, keyframes } from 'styled-components';
import AppShell from '@/components/layout/AppShell';
import { Icon } from '@/components/ui/Icon';
import { Badge, Button, Card } from '@/components/ui/primitives';
import { theme } from '@/styles/theme';
// ─── 샘플 문제 데이터 ──────────────────────────────────────────────────────────
interface Problem {
number: number;
question: string;
choices: string[];
answer: number; // 1-based
explanation: string;
}
const SAMPLE_PROBLEMS: Problem[] = [
{
number: 1,
question:
'함수 f(x) = x² 4x + 3 의 최솟값을 구하시오.',
choices: ['3', '2', '1', '0', '1'],
answer: 3,
explanation:
'꼭짓점 공식: f(x) = (x 2)² 1. 꼭짓점 x = 2 에서 최솟값 f(2) = 4 8 + 3 = 1.',
},
{
number: 2,
question:
'등차수열 {aₙ} 에서 a₁ = 3, 공차 d = 4 일 때, a₁₀ 의 값은?',
choices: ['35', '38', '39', '40', '43'],
answer: 3,
explanation:
'aₙ = a₁ + (n 1)d. a₁₀ = 3 + 9 × 4 = 3 + 36 = 39.',
},
{
number: 3,
question:
'lim(x→2) (x² 4) / (x 2) 의 값은?',
choices: ['0', '2', '4', '6', '수렴하지 않음'],
answer: 3,
explanation:
'분자를 인수분해: (x² 4) = (x 2)(x + 2). 약분하면 lim(x→2) (x + 2) = 4.',
},
{
number: 4,
question:
'주머니 속에 빨간 공 3개, 파란 공 2개가 있다. 한 개를 꺼낼 때 빨간 공일 확률은?',
choices: ['1/5', '2/5', '3/5', '4/5', '1'],
answer: 3,
explanation:
'전체 5개 중 빨간 공 3개. 확률 = 3/5.',
},
{
number: 5,
question:
'∫₀² (2x + 1) dx 의 값은?',
choices: ['4', '5', '6', '7', '8'],
answer: 3,
explanation:
'∫(2x + 1) dx = x² + x + C. [x² + x]₀² = (4 + 2) 0 = 6.',
},
];
import { EBOOK_MAP } from '../data/index';
import type { SampleProblem } from '../data/types';
// ─── 페이지 컴포넌트 ────────────────────────────────────────────────────────────
export default function SampleEbookPage() {
export default function SampleEbookDynamicPage() {
const params = useParams();
const id = typeof params.id === 'string' ? params.id : '';
const ebook = EBOOK_MAP[id];
if (!ebook) {
notFound();
}
return (
<AppShell>
<EbookViewer />
<EbookViewer
title={ebook.title}
problems={ebook.problems}
/>
</AppShell>
);
}
function EbookViewer() {
// ─── 뷰어 ─────────────────────────────────────────────────────────────────────
interface EbookViewerProps {
title: string;
problems: SampleProblem[];
}
function EbookViewer({ title, problems }: EbookViewerProps) {
const [pageIndex, setPageIndex] = useState(0);
const [selectedAnswers, setSelectedAnswers] = useState<Record<number, number>>({});
const [revealed, setRevealed] = useState<Record<number, boolean>>({});
const [fading, setFading] = useState(false);
const total = SAMPLE_PROBLEMS.length;
const problem = SAMPLE_PROBLEMS[pageIndex];
const total = problems.length;
const problem = problems[pageIndex];
const goTo = useCallback(
(index: number) => {
@@ -109,7 +73,6 @@ function EbookViewer() {
const selectAnswer = (choiceIndex: number) => {
setSelectedAnswers((prev) => ({ ...prev, [problem.number]: choiceIndex }));
// 답 바꾸면 해설 숨김
setRevealed((prev) => ({ ...prev, [problem.number]: false }));
};
@@ -117,7 +80,7 @@ function EbookViewer() {
setRevealed((prev) => ({ ...prev, [problem.number]: true }));
};
const chosen = selectedAnswers[problem.number]; // undefined | number (1-based)
const chosen = selectedAnswers[problem.number];
const isRevealed = revealed[problem.number] ?? false;
const isCorrect = chosen !== undefined && chosen === problem.answer;
@@ -137,7 +100,7 @@ function EbookViewer() {
</HeaderRight>
</ViewerHeader>
<ViewerTitle>[] ebook</ViewerTitle>
<ViewerTitle>{title}</ViewerTitle>
<ViewerDivider />
{/* 책 펼침 영역 */}
@@ -156,7 +119,7 @@ function EbookViewer() {
<PageLabel></PageLabel>
<ChoiceList>
{problem.choices.map((choice, idx) => {
const choiceNum = idx + 1; // 1-based
const choiceNum = idx + 1;
const isSelected = chosen === choiceNum;
const isAnswerChoice = problem.answer === choiceNum;
@@ -346,7 +309,6 @@ const ViewerDivider = styled.hr`
margin: 0;
`;
// 책 펼침 레이아웃
const BookSpread = styled.div<{ $fading: boolean }>`
display: grid;
grid-template-columns: 1fr 2px 1fr;
@@ -373,7 +335,6 @@ const BookPage = styled(Card)<{ $side: 'left' | 'right' }>`
padding: ${theme.space.xl};
min-height: 380px;
/* cream tint */
background: linear-gradient(
160deg,
rgba(20, 18, 40, 0.98) 0%,
@@ -434,7 +395,6 @@ const QuestionText = styled.p`
flex: 1;
`;
// 선택지
const ChoiceList = styled.div`
display: flex;
flex-direction: column;
@@ -527,7 +487,6 @@ const CorrectMark = styled.span`
animation: ${fadeIn} 0.2s ease;
`;
// 답 선택 상태
const AnswerStatusRow = styled.div`
display: flex;
align-items: center;
@@ -541,7 +500,6 @@ const AnswerChosen = styled.span<{ $muted?: boolean }>`
color: ${({ $muted }) => ($muted ? theme.color.textMute : theme.color.textSub)};
`;
// 해설 박스
const ExplanationBox = styled.div<{ $correct: boolean }>`
padding: ${theme.space.md};
border-radius: ${theme.radius.md};
@@ -568,7 +526,6 @@ const ExplanationText = styled.p`
color: ${theme.color.textSub};
`;
// 페이지 네비게이션
const PageNav = styled.div`
display: flex;
align-items: center;
@@ -588,7 +545,6 @@ const PageIndicator = styled.span`
text-align: center;
`;
// B2B 안내 박스
const InfoBox = styled(Card)`
display: flex;
align-items: flex-start;

View File

@@ -0,0 +1,265 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 다항식 (1~6) ──────────────────────────────────────────────────────────────
{
number: 1,
question: '(x + 2)³ 를 전개하면?',
choices: [
'x³ + 6x² + 12x + 8',
'x³ + 3x² + 3x + 8',
'x³ + 8',
'x³ + 6x + 8',
'x³ + 2x² + 4x + 8',
],
answer: 1,
explanation: '(a+b)³ = a³ + 3a²b + 3ab² + b³. a=x, b=2 대입: x³ + 3·x²·2 + 3·x·4 + 8 = x³ + 6x² + 12x + 8.',
},
{
number: 2,
question: '다항식 f(x) = 2x³ 3x² + x 5 를 (x 2) 로 나눌 때 나머지는?',
choices: ['3', '1', '1', '3', '5'],
answer: 3,
explanation: '나머지 정리: f(2) = 2·8 3·4 + 2 5 = 16 12 + 2 5 = 1.',
},
{
number: 3,
question: '(a + b)(a b) 를 전개하면?',
choices: ['a² + b²', 'a² b²', 'a² + 2ab + b²', 'a² 2ab + b²', '2a² 2b²'],
answer: 2,
explanation: '합차 공식: (a+b)(ab) = a² b².',
},
{
number: 4,
question: 'x³ 8 을 인수분해하면?',
choices: [
'(x2)(x²+2x+4)',
'(x2)(x²2x+4)',
'(x+2)(x²2x+4)',
'(x2)³',
'(x2)(x+2)²',
],
answer: 1,
explanation: 'a³ b³ = (ab)(a²+ab+b²). x³8 = x³2³ = (x2)(x²+2x+4).',
},
{
number: 5,
question: '다항식 x³ 3x² + 3x 1 을 인수분해하면?',
choices: ['(x1)³', '(x+1)³', '(x1)(x²+x+1)', '(x+1)(x²x+1)', '(x1)²(x+1)'],
answer: 1,
explanation: '(ab)³ = a³ 3a²b + 3ab² b³. a=x, b=1 대입하면 (x1)³.',
},
{
number: 6,
question: 'f(x) = x³ x + 2 를 (x + 1) 로 나눌 때 나머지는?',
choices: [
'0',
'1',
'2',
'1',
'4',
],
answer: 3,
explanation: '나머지 정리: f(1) = (1)³ (1) + 2 = 1 + 1 + 2 = 2. 나머지 = 2.',
},
// ── 방정식과 부등식 (7~12) ───────────────────────────────────────────────────
{
number: 7,
question: '이차부등식 x² 3x + 2 ≤ 0 의 해는?',
choices: ['x ≤ 1 또는 x ≥ 2', '1 ≤ x ≤ 2', 'x ≤ 1 또는 x ≥ 2', '2 ≤ x ≤ 1', 'x < 0'],
answer: 2,
explanation: '(x1)(x2) ≤ 0. 두 근 사이에서 성립: 1 ≤ x ≤ 2.',
},
{
number: 8,
question: '연립부등식 { 2x + 1 > 5, x 3 < 4 } 의 해는?',
choices: ['2 < x < 7', 'x > 2', 'x < 7', 'x ≥ 2', '2 ≤ x ≤ 7'],
answer: 1,
explanation: '첫 부등식: 2x > 4 → x > 2. 둘째: x < 7. 교집합: 2 < x < 7.',
},
{
number: 9,
question: '이차방정식 x² 5x + k = 0 이 중근을 가지려면 k의 값은?',
choices: ['5/4', '25/4', '5', '25', '25/4'],
answer: 2,
explanation: '중근 조건: 판별식 D = 0. D = 25 4k = 0 → k = 25/4.',
},
{
number: 10,
question: '방정식 x² + 2x + 5 = 0 의 두 근의 곱은?',
choices: ['5', '2', '2', '5', '10'],
answer: 4,
explanation: '비에타 공식: 두 근의 곱 = c/a = 5/1 = 5.',
},
{
number: 11,
question: '부등식 |2x 3| < 5 의 해는?',
choices: ['1 < x < 4', 'x > 1', 'x < 4', '2 < x < 4', '1 < x < 4'],
answer: 1,
explanation: '5 < 2x 3 < 5 → 2 < 2x < 8 → 1 < x < 4.',
},
{
number: 12,
question: '이차부등식 x² x 6 > 0 의 해는?',
choices: ['2 < x < 3', 'x < 2 또는 x > 3', 'x > 3', 'x < 2', '3 < x < 2'],
answer: 2,
explanation: '(x3)(x+2) > 0. 두 근 바깥쪽: x < 2 또는 x > 3.',
},
// ── 집합과 명제 (13~18) ──────────────────────────────────────────────────────
{
number: 13,
question: 'A = {1, 2, 3, 4}, B = {3, 4, 5} 일 때 A B 의 원소 개수는?',
choices: ['2', '4', '5', '7', '8'],
answer: 3,
explanation: 'A B = {1, 2, 3, 4, 5}. 원소 개수 = 5.',
},
{
number: 14,
question: 'A = {1, 2, 3, 4}, B = {3, 4, 5} 일 때 A ∩ B 의 원소 개수는?',
choices: ['1', '2', '3', '4', '5'],
answer: 2,
explanation: 'A ∩ B = {3, 4}. 원소 개수 = 2.',
},
{
number: 15,
question: '"p이면 q이다"의 대우는?',
choices: ['p이면 ¬q이다', '¬p이면 q이다', '¬q이면 ¬p이다', 'q이면 p이다', '¬p이면 ¬q이다'],
answer: 3,
explanation: '명제 p→q의 대우는 ¬q→¬p. 대우는 원명제와 동치.',
},
{
number: 16,
question: '명제 "소수이면 홀수이다"의 반례는?',
choices: ['3', '5', '7', '2', '11'],
answer: 4,
explanation: '2는 소수이지만 짝수. 따라서 반례 = 2.',
},
{
number: 17,
question: '전체집합 U = {1,2,3,4,5}, A = {1,3,5}일 때 Aᶜ(A의 여집합)는?',
choices: ['{1,3,5}', '{2,4}', '{1,2,3,4,5}', '∅', '{2,3,4}'],
answer: 2,
explanation: 'Aᶜ = U A = {1,2,3,4,5} {1,3,5} = {2,4}.',
},
{
number: 18,
question: '다음 중 동치인 것끼리 묶은 것은?',
choices: [
'원명제와 역',
'역과 이',
'이와 대우',
'원명제와 대우',
'역과 대우',
],
answer: 4,
explanation: '원명제와 대우는 항상 진릿값이 같다(동치). 역과 이도 서로 동치.',
},
// ── 함수 (19~24) ─────────────────────────────────────────────────────────────
{
number: 19,
question: 'f(x) = 2x + 3 일 때 f(1) 의 값은?',
choices: ['1', '0', '1', '2', '5'],
answer: 3,
explanation: 'f(1) = 2 × (1) + 3 = 2 + 3 = 1.',
},
{
number: 20,
question: '함수 f: A → B 가 일대일대응(전단사)이 되려면?',
choices: [
'단사이기만 하면 된다',
'전사이기만 하면 된다',
'단사이고 전사이어야 한다',
'f(a) = f(b)이면 a = b',
'공역과 치역이 달라야 한다',
],
answer: 3,
explanation: '전단사 = 단사(일대일) AND 전사(onto). 두 조건을 동시에 만족해야 한다.',
},
{
number: 21,
question: 'f(x) = x², g(x) = 2x + 1 일 때 (g∘f)(3) 의 값은?',
choices: ['13', '17', '18', '19', '22'],
answer: 4,
explanation: '(g∘f)(3) = g(f(3)) = g(9) = 2·9 + 1 = 19.',
},
{
number: 22,
question: 'f(x) = 3x 2 의 역함수 f⁻¹(x) 는?',
choices: [
'(x + 2) / 3',
'(x 2) / 3',
'3x + 2',
'(2 x) / 3',
'3 / (x 2)',
],
answer: 1,
explanation: 'y = 3x 2 → 3x = y + 2 → x = (y+2)/3. x와 y를 바꾸면 f⁻¹(x) = (x+2)/3.',
},
{
number: 23,
question: '유리함수 y = 1/x 의 그래프의 점근선은?',
choices: [
'x = 1, y = 1',
'x = 0, y = 1',
'x = 0, y = 0 (x축·y축)',
'x = 1, y = 0',
'점근선 없음',
],
answer: 3,
explanation: 'y = 1/x는 x→0에서 y→±∞, y→0에서 x→±∞. 점근선은 x축(y=0)과 y축(x=0).',
},
{
number: 24,
question: '무리함수 y = √(x 1) 의 정의역은?',
choices: ['x ≥ 0', 'x > 0', 'x ≥ 1', 'x > 1', '모든 실수'],
answer: 3,
explanation: '루트 안이 0 이상이어야 한다. x 1 ≥ 0 → x ≥ 1.',
},
// ── 경우의 수 (25~30) ─────────────────────────────────────────────────────────
{
number: 25,
question: '5명 중 2명을 선택해 순서 있게 배열하는 경우의 수는?',
choices: ['10', '15', '20', '25', '30'],
answer: 3,
explanation: '순열: P(5,2) = 5 × 4 = 20.',
},
{
number: 26,
question: '5명 중 2명을 선택하는(순서 무관) 경우의 수는?',
choices: ['5', '8', '10', '15', '20'],
answer: 3,
explanation: '조합: C(5,2) = 5!/(2!3!) = (5×4)/(2×1) = 10.',
},
{
number: 27,
question: '서로 다른 6권의 책을 일렬로 나열하는 경우의 수는?',
choices: ['120', '360', '480', '720', '1440'],
answer: 4,
explanation: '6! = 6 × 5 × 4 × 3 × 2 × 1 = 720.',
},
{
number: 28,
question: '4개의 자리에 A, B, C, D를 배열할 때 A가 맨 앞에 오는 경우의 수는?',
choices: ['4', '6', '8', '12', '24'],
answer: 2,
explanation: 'A가 고정되면 나머지 B, C, D를 3자리에 배열: 3! = 6.',
},
{
number: 29,
question: '동전 3개를 던질 때 나올 수 있는 전체 경우의 수는?',
choices: ['3', '4', '6', '8', '12'],
answer: 4,
explanation: '각 동전이 2가지(앞/뒤). 2³ = 8.',
},
{
number: 30,
question: 'C(10, 3) 의 값은?',
choices: ['60', '90', '120', '180', '720'],
answer: 3,
explanation: 'C(10,3) = 10!/(3!·7!) = (10×9×8)/(3×2×1) = 720/6 = 120.',
},
];

View File

@@ -0,0 +1,223 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 지수/로그 (1~6) ───────────────────────────────────────────────────────────
{
number: 1,
question: '2³ × 2⁴ 의 값은?',
choices: ['2⁷', '2¹²', '4⁷', '8⁷', '2⁻¹'],
answer: 1,
explanation: '지수 법칙: aᵐ × aⁿ = aᵐ⁺ⁿ. 2³ × 2⁴ = 2⁷ = 128.',
},
{
number: 2,
question: 'log₂ 8 의 값은?',
choices: ['1', '2', '3', '4', '8'],
answer: 3,
explanation: 'log₂ 8 = log₂ 2³ = 3.',
},
{
number: 3,
question: 'log₁₀ 100 + log₁₀ 10 의 값은?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: 'log₁₀ 100 = 2, log₁₀ 10 = 1. 합 = 3. (로그의 덧셈 = log(곱): log(1000) = 3)',
},
{
number: 4,
question: 'log 2 ≈ 0.3010 일 때 log 8 의 값은?',
choices: ['0.6020', '0.7525', '0.9030', '1.2040', '1.5050'],
answer: 3,
explanation: 'log 8 = log 2³ = 3 log 2 = 3 × 0.3010 = 0.9030.',
},
{
number: 5,
question: '지수함수 y = 2ˣ 에서 x = 2일 때 y의 값은?',
choices: ['4', '1/4', '1/4', '4', '8'],
answer: 3,
explanation: 'y = 2⁻² = 1/2² = 1/4.',
},
{
number: 6,
question: '자연로그 ln e 의 값은? (e는 자연상수)',
choices: ['0', '1', 'e', '1/e', '2'],
answer: 2,
explanation: 'lnₑ e = log_e e = 1. 로그의 정의에 의해 eˣ = e이면 x = 1.',
},
// ── 삼각함수 (7~12) ──────────────────────────────────────────────────────────
{
number: 7,
question: 'sin²θ + cos²θ 의 값은?',
choices: ['0', '1/2', '1', '2', 'θ'],
answer: 3,
explanation: '피타고라스 항등식: sin²θ + cos²θ = 1 (항상 성립).',
},
{
number: 8,
question: 'sin 90° 의 값은?',
choices: ['1', '0', '1/2', '√2/2', '1'],
answer: 5,
explanation: '단위원 정의: 90°일 때 y 좌표 = 1. sin 90° = 1.',
},
{
number: 9,
question: 'cos(−θ) = ? (코사인의 대칭성)',
choices: ['cos θ', 'cos θ', 'sin θ', 'sin θ', '1/cos θ'],
answer: 2,
explanation: '코사인은 우함수: cos(−θ) = cos θ.',
},
{
number: 10,
question: '각도 π/6 (라디안)을 도(°)로 변환하면?',
choices: ['15°', '30°', '45°', '60°', '90°'],
answer: 2,
explanation: 'π 라디안 = 180°. π/6 × (180/π) = 30°.',
},
{
number: 11,
question: 'y = sin x 의 주기는?',
choices: ['π/2', 'π', '2π', '4π', '1'],
answer: 3,
explanation: 'sin 함수의 주기 = 2π. y = sin(bx)의 주기는 2π/b.',
},
{
number: 12,
question: 'tan θ = sin θ / cos θ 에서 sin θ = 3/5, cos θ = 4/5일 때 tan θ는?',
choices: ['3/4', '4/3', '3/5', '5/3', '5/4'],
answer: 1,
explanation: 'tan θ = (3/5) ÷ (4/5) = (3/5) × (5/4) = 3/4.',
},
// ── 수열 (13~18) ─────────────────────────────────────────────────────────────
{
number: 13,
question: '등차수열 2, 5, 8, 11, … 의 공차는?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: '연속하는 항의 차: 5 2 = 3. 공차 d = 3.',
},
{
number: 14,
question: '등차수열의 첫째 항이 1, 공차가 3일 때 제10항은?',
choices: ['25', '27', '28', '29', '31'],
answer: 3,
explanation: 'aₙ = a₁ + (n1)d. a₁₀ = 1 + 9 × 3 = 1 + 27 = 28.',
},
{
number: 15,
question: '등비수열 3, 6, 12, 24, … 의 공비는?',
choices: ['1', '2', '3', '4', '6'],
answer: 2,
explanation: '연속하는 항의 비: 6/3 = 2. 공비 r = 2.',
},
{
number: 16,
question: '등비수열 첫째 항 2, 공비 3일 때 제4항은?',
choices: ['18', '27', '54', '81', '162'],
answer: 3,
explanation: 'aₙ = a₁ × r^(n1). a₄ = 2 × 3³ = 2 × 27 = 54.',
},
{
number: 17,
question: 'Σ(k=1 to 5) k 의 값은?',
choices: ['10', '12', '15', '18', '20'],
answer: 3,
explanation: '1 + 2 + 3 + 4 + 5 = 15. 공식: n(n+1)/2 = 5×6/2 = 15.',
},
{
number: 18,
question: '수열 {aₙ}에서 S₅ = 20, S₄ = 14이면 a₅는?',
choices: ['4', '5', '6', '7', '8'],
answer: 3,
explanation: 'aₙ = Sₙ S(n1). a₅ = S₅ S₄ = 20 14 = 6.',
},
// ── 미분 (도함수) (19~24) ────────────────────────────────────────────────────
{
number: 19,
question: 'f(x) = x³ 를 미분하면?',
choices: ['x²', '2x²', '3x²', '3x³', '4x³'],
answer: 3,
explanation: '멱함수 미분: (x^n)의 도함수 = n*x^(n-1). (x³)의 도함수 = 3x².',
},
{
number: 20,
question: 'f(x) = 2x² 3x + 1 의 도함수 f´(x) 는?',
choices: ['2x 3', '4x 3', '4x + 3', '2x + 3', 'x² 3'],
answer: 2,
explanation: '각 항을 미분: (2x²)의 도함수 = 4x, (3x)의 도함수 = 3, (1)의 도함수 = 0. f´(x) = 4x 3.',
},
{
number: 21,
question: 'f(x) = x³ 3x 에서 x=1에서의 미분계수 값은?',
choices: ['3', '2', '0', '2', '3'],
answer: 3,
explanation: 'f´(x) = 3x² 3. f´(1) = 3 × 1 3 = 0.',
},
{
number: 22,
question: 'y = 5 (상수)의 도함수는?',
choices: ['5x', '5', '1', '0', '5'],
answer: 4,
explanation: '상수의 도함수는 0. 상수 c를 미분하면 항상 0.',
},
{
number: 23,
question: 'f(x) = x³ 3x² + 2 가 극소가 되는 x의 값은?',
choices: ['2', '1', '0', '2', '3'],
answer: 4,
explanation: 'f´(x) = 3x² 6x = 3x(x2) = 0 → x = 0 또는 x = 2. x = 0은 극대, x = 2는 극소.',
},
{
number: 24,
question: '함수 f(x) = x² 4x + 3 의 x = 1에서의 접선의 기울기는?',
choices: ['4', '3', '2', '0', '2'],
answer: 3,
explanation: 'f´(x) = 2x 4. x = 1: f´(1) = 2 4 = 2.',
},
// ── 적분 (부정/정적분) (25~30) ───────────────────────────────────────────────
{
number: 25,
question: '∫ 3x² dx 의 값은?',
choices: ['x² + C', 'x³ + C', '6x + C', '3x³ + C', 'x³/3 + C'],
answer: 2,
explanation: '∫ x^n dx = x^(n+1)/(n+1) + C. ∫ 3x² dx = 3 × x³/3 + C = x³ + C.',
},
{
number: 26,
question: '∫₀² 2x dx 의 값은?',
choices: ['1', '2', '3', '4', '6'],
answer: 4,
explanation: '[x²]₀² = 4 0 = 4.',
},
{
number: 27,
question: '∫₁³ (2x 1) dx 의 값은?',
choices: ['4', '5', '6', '7', '8'],
answer: 3,
explanation: '[x² x]₁³ = (9 3) (1 1) = 6 0 = 6.',
},
{
number: 28,
question: '∫ (x + 1)² dx = ?',
choices: ['(x+1)³/3 + C', '2(x+1) + C', '(x+1)² + C', '(x+1)³ + C', 'x²/2 + x + C'],
answer: 1,
explanation: '∫ (x+1)² dx. t = x+1로 치환하면 ∫t² dt = t³/3 + C = (x+1)³/3 + C.',
},
{
number: 29,
question: '∫₀¹ x² dx 의 값은?',
choices: ['1/4', '1/3', '1/2', '1', '2'],
answer: 2,
explanation: '[x³/3]₀¹ = 1/3 0 = 1/3.',
},
{
number: 30,
question: 'y = x² 와 y = x 로 둘러싸인 넓이는?',
choices: ['1/6', '1/4', '1/3', '1/2', '1'],
answer: 1,
explanation: '교점: x² = x → x = 0, 1. 넓이 = ∫₀¹ (x x²) dx = [x²/2 x³/3]₀¹ = 1/2 1/3 = 1/6.',
},
];

View File

@@ -0,0 +1,229 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 극한 (1~5) ────────────────────────────────────────────────────────────────
{
number: 1,
question: 'lim(x→2) (x² 4) / (x 2) 의 값은?',
choices: ['0', '2', '4', '6', '수렴하지 않음'],
answer: 3,
explanation: '분자 인수분해: (x2)(x+2). 약분 후 lim(x→2) (x+2) = 2 + 2 = 4.',
},
{
number: 2,
question: 'lim(x→∞) (3x² + 2x) / (x² 1) 의 값은?',
choices: ['0', '1', '2', '3', '∞'],
answer: 4,
explanation: '분자 분모를 최고차항 x²으로 나누면 lim = (3 + 2/x) / (1 1/x²) → 3/1 = 3.',
},
{
number: 3,
question: 'lim(x→0) sin x / x 의 값은?',
choices: ['0', '1', 'π', '∞', '존재하지 않음'],
answer: 2,
explanation: '기본 극한: lim(x→0) sin x / x = 1 (중요 표준 극한).',
},
{
number: 4,
question: 'lim(n→∞) (1 + 1/n)^n 의 값은?',
choices: ['1', '2', '3', 'e', 'π'],
answer: 4,
explanation: '자연상수 e의 정의: e = lim(n→∞) (1 + 1/n)^n ≈ 2.718…',
},
{
number: 5,
question: 'f(x) = x² 에서 x = 1에서의 미분계수 lim(h→0) [f(1+h)f(1)]/h 의 값은?',
choices: ['0', '1', '2', '3', '4'],
answer: 3,
explanation: 'f(1+h) = (1+h)² = 1 + 2h + h². [f(1+h)f(1)]/h = (2h + h²)/h = 2 + h → h→0이면 2.',
},
// ── 미분법 심화 (6~11) ────────────────────────────────────────────────────────
{
number: 6,
question: 'f(x) = e^x 의 도함수는?',
choices: ['e^(x1)', 'x·e^x', 'e^x', '1/e^x', 'e'],
answer: 3,
explanation: '지수함수의 미분: e^x의 도함수 = e^x. 자기 자신이 도함수.',
},
{
number: 7,
question: 'f(x) = ln x 의 도함수는? (x > 0)',
choices: ['ln x', '1/x', 'x', 'e^x', '1/(x ln x)'],
answer: 2,
explanation: '자연로그 미분: ln x의 도함수 = 1/x.',
},
{
number: 8,
question: 'f(x) = sin x 의 도함수는?',
choices: ['sin x', 'sin x', 'cos x', 'cos x', 'tan x'],
answer: 4,
explanation: '삼각함수 미분: sin x의 도함수 = cos x.',
},
{
number: 9,
question: 'f(x) = x² · sin x 의 도함수는? (곱의 미분)',
choices: [
'2x · cos x',
'2x · sin x + x² · cos x',
'x² · cos x',
'2x · sin x x² · cos x',
'x² · sin x + 2x',
],
answer: 2,
explanation: '곱의 미분: (uv)의 도함수 = u´v + uv´. u = x², u´ = 2x; v = sin x, v´ = cos x. 결과: 2x sin x + x² cos x.',
},
{
number: 10,
question: '합성함수 f(x) = (2x + 1)³ 의 도함수는?',
choices: ['3(2x+1)²', '6(2x+1)²', '3(2x+1)', '6(2x+1)', '2(2x+1)³'],
answer: 2,
explanation: '연쇄 법칙: (u³)의 도함수 = 3u² × u´. u = 2x+1, u´ = 2. 결과: 3(2x+1)² × 2 = 6(2x+1)².',
},
{
number: 11,
question: 'f(x) = x³ 6x² + 9x 의 극대값은?',
choices: ['0', '2', '4', '6', '9'],
answer: 3,
explanation: 'f´(x) = 3x² 12x + 9 = 3(x1)(x3) = 0 → x = 1(극대), x = 3(극소). f(1) = 1 6 + 9 = 4.',
},
// ── 적분법 심화 (12~17) ───────────────────────────────────────────────────────
{
number: 12,
question: '∫ e^x dx = ?',
choices: ['e^(x+1) + C', 'e^x + C', 'x·e^x + C', '1/e^x + C', 'e^x/x + C'],
answer: 2,
explanation: '∫ e^x dx = e^x + C. e^x는 자신이 미분/적분의 고유함수.',
},
{
number: 13,
question: '∫ 1/x dx = ? (x > 0)',
choices: ['1/x² + C', 'x + C', 'ln x + C', '1/(x+1) + C', 'e^x + C'],
answer: 3,
explanation: '∫ (1/x) dx = ln |x| + C. x > 0이면 ln x + C.',
},
{
number: 14,
question: '∫ cos x dx = ?',
choices: ['sin x + C', 'sin x + C', 'cos x + C', 'cos x + C', 'tan x + C'],
answer: 2,
explanation: '∫ cos x dx = sin x + C. sin x의 도함수가 cos x이므로 역연산.',
},
{
number: 15,
question: '∫₀^π sin x dx 의 값은?',
choices: ['0', '1', '2', 'π', '2'],
answer: 3,
explanation: '[cos x]₀^π = cos π (cos 0) = (1) (1) = 1 + 1 = 2.',
},
{
number: 16,
question: '부분적분을 이용해 ∫ x·e^x dx 를 구하면?',
choices: ['x·e^x + C', 'x·e^x e^x + C', 'e^x + C', 'x²·e^x/2 + C', '(x1)·e^x + C'],
answer: 2,
explanation: '부분적분: u=x, dv=e^x dx → du=dx, v=e^x. ∫x·e^x dx = x·e^x ∫e^x dx = x·e^x e^x + C.',
},
{
number: 17,
question: 'y = x³ x 와 x 축으로 둘러싸인 넓이는? (1 ≤ x ≤ 1 구간)',
choices: ['0', '1/2', '1', '3/2', '2'],
answer: 2,
explanation: '|∫₋₁⁰ (x³x) dx| + |∫₀¹ (x³x) dx| = 1/4 + 1/4 = 1/2. 대칭 활용.',
},
// ── 확률과 통계 (18~24) ───────────────────────────────────────────────────────
{
number: 18,
question: '5명을 일렬로 세울 때 특정 2명이 항상 이웃하는 경우의 수는?',
choices: ['24', '36', '48', '60', '72'],
answer: 3,
explanation: '2명을 묶어 1명으로 보면 4명 배열: 4! = 24. 묶음 내부 순서: 2! = 2. 24 × 2 = 48.',
},
{
number: 19,
question: 'C(6, 2) 의 값은?',
choices: ['10', '12', '15', '18', '30'],
answer: 3,
explanation: 'C(6,2) = 6!/(2!·4!) = (6×5)/2 = 15.',
},
{
number: 20,
question: '이항분포 B(10, 0.5)의 평균은?',
choices: ['2', '4', '5', '6', '10'],
answer: 3,
explanation: '이항분포 B(n,p)의 평균 = np = 10 × 0.5 = 5.',
},
{
number: 21,
question: '정규분포 N(50, 10²)에서 P(40 ≤ X ≤ 60)은? (표준정규표준: P(0≤Z≤1) = 0.3413)',
choices: ['0.3413', '0.5', '0.6826', '0.9544', '1'],
answer: 3,
explanation: 'Z = (X50)/10. P(40≤X≤60) = P(1≤Z≤1) = 2×P(0≤Z≤1) = 2×0.3413 = 0.6826.',
},
{
number: 22,
question: '두 사건 A, B가 독립이고 P(A) = 0.4, P(B) = 0.5이면 P(A∩B)는?',
choices: ['0.1', '0.2', '0.4', '0.5', '0.9'],
answer: 2,
explanation: '독립사건: P(A∩B) = P(A) × P(B) = 0.4 × 0.5 = 0.2.',
},
{
number: 23,
question: '조건부 확률 P(A|B) = P(A∩B)/P(B) 에서 P(A∩B) = 0.12, P(B) = 0.4이면 P(A|B)는?',
choices: ['0.2', '0.3', '0.4', '0.5', '0.6'],
answer: 2,
explanation: 'P(A|B) = 0.12 / 0.4 = 0.3.',
},
{
number: 24,
question: '표본 크기 n = 100, 표본 평균 x̄ = 75, 모표준편차 σ = 10일 때 모평균의 95% 신뢰구간 폭은? (z₀.₀₂₅ ≈ 1.96)',
choices: ['1.96', '2.96', '3.92', '4.90', '19.6'],
answer: 3,
explanation: '신뢰구간 폭 = 2 × z × σ/√n = 2 × 1.96 × 10/10 = 2 × 1.96 = 3.92.',
},
// ── 벡터/공간좌표 (25~30) ─────────────────────────────────────────────────────
{
number: 25,
question: '벡터 a→ = (3, 4) 의 크기 |a→|는?',
choices: ['5', '6', '7', '12', '25'],
answer: 1,
explanation: '|a→| = √(3² + 4²) = √(9+16) = √25 = 5.',
},
{
number: 26,
question: 'a→ = (1, 2), b→ = (3, 1) 일 때 a→ + b→ 의 y 성분은?',
choices: ['1', '0', '1', '2', '3'],
answer: 3,
explanation: 'a→ + b→ = (1+3, 2+(1)) = (4, 1). y 성분 = 1.',
},
{
number: 27,
question: 'a→ = (2, 1), b→ = (1, 3) 일 때 내적 a→·b→ 는?',
choices: ['3', '4', '5', '6', '7'],
answer: 3,
explanation: 'a→·b→ = 2×1 + 1×3 = 2 + 3 = 5.',
},
{
number: 28,
question: '두 벡터 a→ = (1, 0), b→ = (0, 1) 의 내적은?',
choices: ['1', '0', '1', '√2', '2'],
answer: 2,
explanation: 'a→·b→ = 1×0 + 0×1 = 0. 수직(직교)이면 내적 = 0.',
},
{
number: 29,
question: '점 A(1, 2, 3), B(4, 6, 3) 사이의 거리는?',
choices: ['3', '4', '5', '6', '7'],
answer: 3,
explanation: 'd = √((41)² + (62)² + (33)²) = √(9+16+0) = √25 = 5.',
},
{
number: 30,
question: '공간에서 직선 x/1 = y/2 = z/3 의 방향벡터는?',
choices: ['(1,1,1)', '(1,2,3)', '(3,2,1)', '(2,3,1)', '(0,0,0)'],
answer: 2,
explanation: '대칭형 방정식 x/a = y/b = z/c에서 방향벡터 = (a, b, c) = (1, 2, 3).',
},
];

View File

@@ -0,0 +1,71 @@
import type { SampleProblem } from './types';
import { PROBLEMS as MIDDLE1_PROBLEMS } from './middle-1';
import { PROBLEMS as MIDDLE2_PROBLEMS } from './middle-2';
import { PROBLEMS as MIDDLE3_PROBLEMS } from './middle-3';
import { PROBLEMS as HIGH1_PROBLEMS } from './high-1';
import { PROBLEMS as HIGH2_PROBLEMS } from './high-2';
import { PROBLEMS as HIGH3_PROBLEMS } from './high-3';
export type { SampleProblem };
export interface EbookMeta {
id: string;
title: string;
grade: string;
subtitle: string;
problemCount: number;
problems: SampleProblem[];
}
export const EBOOK_MAP: Record<string, EbookMeta> = {
'middle-1': {
id: 'middle-1',
title: '[샘플] 중1 수학 문제집',
grade: '중1',
subtitle: '중학교 1학년 수학 교과과정',
problemCount: 30,
problems: MIDDLE1_PROBLEMS,
},
'middle-2': {
id: 'middle-2',
title: '[샘플] 중2 수학 문제집',
grade: '중2',
subtitle: '중학교 2학년 수학 교과과정',
problemCount: 30,
problems: MIDDLE2_PROBLEMS,
},
'middle-3': {
id: 'middle-3',
title: '[샘플] 중3 수학 문제집',
grade: '중3',
subtitle: '중학교 3학년 수학 교과과정',
problemCount: 30,
problems: MIDDLE3_PROBLEMS,
},
'high-1': {
id: 'high-1',
title: '[샘플] 고1 수학 문제집',
grade: '고1',
subtitle: '고등학교 1학년 수학 교과과정',
problemCount: 30,
problems: HIGH1_PROBLEMS,
},
'high-2': {
id: 'high-2',
title: '[샘플] 고2 수학 문제집',
grade: '고2',
subtitle: '고등학교 2학년 수학 교과과정',
problemCount: 30,
problems: HIGH2_PROBLEMS,
},
'high-3': {
id: 'high-3',
title: '[샘플] 고3 수학 문제집',
grade: '고3',
subtitle: '고등학교 3학년 수학 교과과정',
problemCount: 30,
problems: HIGH3_PROBLEMS,
},
};
export const EBOOK_LIST: EbookMeta[] = Object.values(EBOOK_MAP);

View File

@@ -0,0 +1,223 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 자연수와 정수 (1~6) ──────────────────────────────────────────────────────
{
number: 1,
question: '절댓값 |7| 의 값은?',
choices: ['7', '1', '0', '1', '7'],
answer: 5,
explanation: '절댓값은 수직선에서 원점까지의 거리이므로 음수 기호를 제거한다. |7| = 7.',
},
{
number: 2,
question: '다음 중 가장 작은 수는?\n3, 2, 5, 0, 4',
choices: ['3', '2', '5', '0', '4'],
answer: 3,
explanation: '수직선에서 왼쪽에 있을수록 작다. 5 < 3 < 0 < 2 < 4 이므로 5가 가장 작다.',
},
{
number: 3,
question: '(3) + (8) 의 값은?',
choices: ['11', '5', '5', '11', '24'],
answer: 1,
explanation: '부호가 같은 두 음수의 합은 절댓값의 합에 음수 부호를 붙인다. (3) + (8) = 11.',
},
{
number: 4,
question: '(4) × (6) 의 값은?',
choices: ['24', '10', '10', '24', '48'],
answer: 4,
explanation: '음수 × 음수 = 양수. 4 × 6 = 24이므로 (4) × (6) = 24.',
},
{
number: 5,
question: '(+5) ÷ (1/2) 의 값은?',
choices: ['10', '5/2', '5/2', '5', '10'],
answer: 1,
explanation: '÷ (1/2) = × (2). 5 × (2) = 10. 양수 ÷ 음수이므로 결과는 음수.',
},
{
number: 6,
question: '2³ + (1)⁴ 의 값은?',
choices: ['9', '7', '6', '7', '9'],
answer: 2,
explanation: '2³ = 8, (1)⁴ = 1. 따라서 8 + 1 = 7.',
},
// ── 일차방정식 (7~12) ────────────────────────────────────────────────────────
{
number: 7,
question: '방정식 2x 3 = 7 의 해는?',
choices: ['2', '4', '5', '7', '10'],
answer: 3,
explanation: '2x = 7 + 3 = 10. x = 10 ÷ 2 = 5.',
},
{
number: 8,
question: '방정식 3(x + 1) = 12 의 해는?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: '3x + 3 = 12. 3x = 9. x = 3.',
},
{
number: 9,
question: '방정식 x/2 + 1 = 4 의 해는?',
choices: ['2', '3', '5', '6', '8'],
answer: 4,
explanation: 'x/2 = 4 1 = 3. 양변에 2를 곱하면 x = 6.',
},
{
number: 10,
question: '방정식 5x 4 = 2x + 8 의 해는?',
choices: ['2', '3', '4', '5', '6'],
answer: 3,
explanation: '5x 2x = 8 + 4. 3x = 12. x = 4.',
},
{
number: 11,
question: '어떤 수의 3배에서 5를 빼면 16이다. 이 어떤 수는?',
choices: ['5', '6', '7', '8', '9'],
answer: 3,
explanation: '3x 5 = 16. 3x = 21. x = 7.',
},
{
number: 12,
question: '방정식 2(x 3) = x + 1 의 해는?',
choices: ['5', '6', '7', '8', '9'],
answer: 3,
explanation: '2x 6 = x + 1. 2x x = 1 + 6. x = 7.',
},
// ── 좌표평면과 그래프 (13~18) ────────────────────────────────────────────────
{
number: 13,
question: '점 (3, 2) 는 몇 사분면에 위치하는가?',
choices: ['제1사분면', '제2사분면', '제3사분면', '제4사분면', '어느 사분면도 아님'],
answer: 2,
explanation: 'x < 0, y > 0 이면 제2사분면. (3, 2)는 x = 3 < 0, y = 2 > 0이므로 제2사분면.',
},
{
number: 14,
question: '두 점 A(1, 3), B(4, 7) 사이의 x 좌표 차이는?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: '4 1 = 3. x 좌표끼리의 차이를 구한다.',
},
{
number: 15,
question: 'y = 2x + 1 에서 x = 3일 때 y의 값은?',
choices: ['5', '6', '7', '8', '9'],
answer: 3,
explanation: 'y = 2 × 3 + 1 = 6 + 1 = 7.',
},
{
number: 16,
question: 'y = x + 4 의 그래프가 지나는 점은?',
choices: ['(0, 4)', '(2, 2)', '(4, 0)', '(1, 3)', '(3, 0)'],
answer: 2,
explanation: 'x = 2일 때 y = 2 + 4 = 2. 따라서 점 (2, 2)를 지난다.',
},
{
number: 17,
question: '좌표축 위의 점 (5, 0) 이 위치하는 곳은?',
choices: ['제1사분면', '제2사분면', 'x 축', 'y 축', '원점'],
answer: 3,
explanation: 'y = 0인 점은 x 축 위에 있다. (5, 0)은 x 축 위의 점.',
},
{
number: 18,
question: 'y = 3x 그래프의 기울기는?',
choices: ['3', '0', '1', '3', '9'],
answer: 4,
explanation: 'y = mx 형태에서 m이 기울기. y = 3x에서 기울기는 3.',
},
// ── 기본 도형 (19~24) ────────────────────────────────────────────────────────
{
number: 19,
question: '삼각형 세 내각의 합은?',
choices: ['90°', '120°', '180°', '270°', '360°'],
answer: 3,
explanation: '삼각형 세 내각의 합은 항상 180°이다.',
},
{
number: 20,
question: '정삼각형 한 각의 크기는?',
choices: ['45°', '60°', '90°', '108°', '120°'],
answer: 2,
explanation: '정삼각형은 세 각이 모두 같고 합이 180°. 180° ÷ 3 = 60°.',
},
{
number: 21,
question: '반지름이 4 cm인 원의 둘레는? (π 사용)',
choices: ['4π cm', '8π cm', '12π cm', '16π cm', '32π cm'],
answer: 2,
explanation: '원의 둘레 = 2πr. 2 × π × 4 = 8π cm.',
},
{
number: 22,
question: '직각삼각형에서 한 예각이 35°이면 다른 예각은?',
choices: ['35°', '45°', '55°', '65°', '90°'],
answer: 3,
explanation: '세 각의 합 = 180°. 90° + 35° + ? = 180°. 나머지 각 = 55°.',
},
{
number: 23,
question: '평행사변형의 두 대각선은 서로 어떤 관계인가?',
choices: ['수직이등분', '수직', '서로 이등분', '같은 길이', '평행'],
answer: 3,
explanation: '평행사변형에서 두 대각선은 서로 이등분(교점에서 각각 반으로 나뉨)한다.',
},
{
number: 24,
question: '밑변 6 cm, 높이 4 cm인 삼각형의 넓이는?',
choices: ['10 cm²', '12 cm²', '18 cm²', '24 cm²', '48 cm²'],
answer: 2,
explanation: '삼각형 넓이 = (밑변 × 높이) ÷ 2 = (6 × 4) ÷ 2 = 12 cm².',
},
// ── 비례/반비례 (25~30) ──────────────────────────────────────────────────────
{
number: 25,
question: 'y 가 x 에 정비례하고 x = 3일 때 y = 12이다. x = 5일 때 y는?',
choices: ['15', '18', '20', '24', '30'],
answer: 3,
explanation: '정비례: y = kx. 12 = k × 3 → k = 4. y = 4 × 5 = 20.',
},
{
number: 26,
question: 'y 가 x 에 반비례하고 x = 2일 때 y = 6이다. x = 4일 때 y는?',
choices: ['2', '3', '4', '6', '12'],
answer: 2,
explanation: '반비례: xy = k. 2 × 6 = 12 = k. x = 4이면 y = 12/4 = 3.',
},
{
number: 27,
question: 'y = 6/x 에서 x = 2일 때 y의 값은?',
choices: ['1', '2', '3', '6', '12'],
answer: 3,
explanation: 'y = 6/2 = 3.',
},
{
number: 28,
question: '시속 60 km로 달리는 자동차가 3시간 동안 이동하는 거리는?',
choices: ['120 km', '150 km', '180 km', '200 km', '240 km'],
answer: 3,
explanation: '거리 = 속력 × 시간. 60 × 3 = 180 km.',
},
{
number: 29,
question: '비 3:4에서 전체를 70으로 할 때, 3에 해당하는 양은?',
choices: ['21', '28', '30', '35', '42'],
answer: 3,
explanation: '전체 비율 3 + 4 = 7. 3에 해당하는 양 = 70 × (3/7) = 30.',
},
{
number: 30,
question: '가로 세로 비가 3:5인 직사각형에서 가로가 9 cm이면 세로는?',
choices: ['12 cm', '13 cm', '14 cm', '15 cm', '18 cm'],
answer: 4,
explanation: '3:5 = 9:x. 3x = 45. x = 15 cm.',
},
];

View File

@@ -0,0 +1,241 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 유리수/무리수 (1~6) ───────────────────────────────────────────────────────
{
number: 1,
question: '다음 중 무리수인 것은?',
choices: ['√4', '0.333…', '5/3', '√7', '1.25'],
answer: 4,
explanation: '√4 = 2(유리수), 0.333… = 1/3(유리수), 5/3(유리수), 1.25(유리수). √7은 유한소수나 순환소수로 나타낼 수 없으므로 무리수.',
},
{
number: 2,
question: '√18 을 가장 간단한 꼴로 나타내면?',
choices: ['3√2', '2√3', '3√6', '6√2', '9√2'],
answer: 1,
explanation: '√18 = √(9 × 2) = √9 × √2 = 3√2.',
},
{
number: 3,
question: '√2 × √8 의 값은?',
choices: ['2', '4', '√10', '2√4', '8'],
answer: 2,
explanation: '√2 × √8 = √(2 × 8) = √16 = 4.',
},
{
number: 4,
question: '2√3 + 5√3 의 값은?',
choices: ['7', '7√3', '10√3', '7√6', '√21'],
answer: 2,
explanation: '같은 무리수끼리 계수를 더한다. (2 + 5)√3 = 7√3.',
},
{
number: 5,
question: '√5 ≈ 2.236 일 때, 3√5 의 근삿값은?',
choices: ['5.618', '6.618', '6.708', '7.236', '8.236'],
answer: 3,
explanation: '3 × 2.236 = 6.708.',
},
{
number: 6,
question: '다음 중 유리수와 무리수에 대한 설명으로 옳은 것은?',
choices: [
'무리수는 음수가 될 수 없다',
'유리수와 무리수의 합은 항상 무리수이다',
'모든 순환소수는 무리수이다',
'√9 는 무리수이다',
'두 무리수의 합은 항상 무리수이다',
],
answer: 2,
explanation: '유리수 + 무리수 = 무리수. 예: 1 + √2 = 1 + √2(무리수). 순환소수는 유리수, √9 = 3(유리수).',
},
// ── 연립방정식 (7~12) ────────────────────────────────────────────────────────
{
number: 7,
question: '연립방정식 { x + y = 5, x y = 1 } 을 풀면 x의 값은?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: '두 식을 더하면 2x = 6. x = 3. (y = 5 3 = 2 검증 가능)',
},
{
number: 8,
question: '연립방정식 { 2x + y = 7, x + 2y = 8 } 을 풀면 y의 값은?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: '첫 식에서 y = 7 2x. 대입하면 x + 2(7 2x) = 8 → x + 14 4x = 8 → 3x = 6 → x = 2. y = 7 4 = 3.',
},
{
number: 9,
question: '연립방정식 { x y = 4, 2x + y = 8 } 을 풀면 x + y의 값은?',
choices: ['2', '3', '4', '5', '6'],
answer: 3,
explanation: '더하면 3x = 12 → x = 4. y = 4 4 = 0. x + y = 4.',
},
{
number: 10,
question: '연립방정식 { 3x 2y = 1, x + y = 7 } 에서 x의 값은?',
choices: ['1', '2', '3', '4', '5'],
answer: 3,
explanation: 'y = 7 x를 대입: 3x 2(7 x) = 1 → 3x 14 + 2x = 1 → 5x = 15 → x = 3.',
},
{
number: 11,
question: '어른 2명과 어린이 3명의 입장료 합이 13,000원, 어른 1명과 어린이 1명의 합이 6,000원일 때 어른 1명의 입장료는?',
choices: ['3,000원', '4,000원', '5,000원', '6,000원', '7,000원'],
answer: 3,
explanation: 'a + c = 6000에서 c = 6000 a. 2a + 3(6000 a) = 13000 → 2a + 18000 3a = 13000 → a = 5000 → a = 5,000원.',
},
{
number: 12,
question: '연립방정식 { 2x y = 3, 4x 2y = 6 } 의 해의 개수는?',
choices: ['0개(불능)', '1개', '2개', '무한히 많다(부정)', '판단 불가'],
answer: 4,
explanation: '두 번째 식은 첫 번째 식에 2를 곱한 것과 같다. 두 식이 일치하므로 해가 무한히 많다(부정).',
},
// ── 일차함수 (13~18) ─────────────────────────────────────────────────────────
{
number: 13,
question: '일차함수 y = 3x 2 에서 y 절편(x = 0)의 값은?',
choices: ['3', '2', '0', '2', '3'],
answer: 2,
explanation: 'x = 0 대입: y = 3 × 0 2 = 2. y 절편은 2.',
},
{
number: 14,
question: '일차함수 y = 2x + 5 의 기울기는?',
choices: ['5', '2', '1', '2', '5'],
answer: 2,
explanation: 'y = mx + b 형태에서 m이 기울기. y = 2x + 5에서 기울기 = 2.',
},
{
number: 15,
question: '두 점 (1, 3), (3, 7)을 지나는 직선의 기울기는?',
choices: ['1', '2', '3', '4', '5'],
answer: 2,
explanation: '기울기 = (y₂ y₁) / (x₂ x₁) = (7 3) / (3 1) = 4 / 2 = 2.',
},
{
number: 16,
question: 'y = ax + b 에서 a > 0, b < 0이면 그래프는?',
choices: [
'오른쪽 위로 기울고 y 절편이 양수',
'오른쪽 아래로 기울고 y 절편이 양수',
'오른쪽 위로 기울고 y 절편이 음수',
'오른쪽 아래로 기울고 y 절편이 음수',
'수평선',
],
answer: 3,
explanation: 'a > 0 이면 오른쪽 위로 증가, b < 0 이면 y 절편이 음수(원점 아래를 지남).',
},
{
number: 17,
question: 'y = 2x + 1 과 y = 2x 3 의 관계는?',
choices: ['한 점에서 만난다', '두 점에서 만난다', '평행하다', '일치한다', '수직이다'],
answer: 3,
explanation: '두 직선의 기울기가 같고 (2 = 2) y 절편이 다르므로 평행하다.',
},
{
number: 18,
question: 'y = x + 2 와 y = x + 4 의 교점의 x 좌표는?',
choices: ['0', '1', '2', '3', '4'],
answer: 2,
explanation: 'x + 2 = x + 4 → 2x = 2 → x = 1.',
},
// ── 삼각형 성질 (19~24) ──────────────────────────────────────────────────────
{
number: 19,
question: '이등변삼각형에서 꼭짓각이 40°이면 밑각 하나의 크기는?',
choices: ['50°', '60°', '70°', '80°', '90°'],
answer: 3,
explanation: '세 각의 합 = 180°. 두 밑각이 같으므로 2a + 40° = 180° → 2a = 140° → a = 70°.',
},
{
number: 20,
question: '삼각형의 외각은 그 이웃하지 않는 두 내각의 합과 어떤 관계인가?',
choices: ['같다', '크다', '작다', '두 배이다', '절반이다'],
answer: 1,
explanation: '삼각형 외각 정리: 한 외각의 크기 = 그 이웃하지 않는 두 내각의 합.',
},
{
number: 21,
question: 'SSS 합동 조건이란?',
choices: [
'두 변과 그 끼인각이 각각 같다',
'두 각과 그 끼인변이 각각 같다',
'세 변의 길이가 각각 같다',
'한 변과 두 각이 같다',
'빗변과 한 예각이 같다',
],
answer: 3,
explanation: 'SSS(Side-Side-Side) 합동 조건: 세 쌍의 대응 변의 길이가 모두 같을 때.',
},
{
number: 22,
question: '직각삼각형에서 두 직각변이 3, 4일 때 빗변의 길이는?',
choices: ['3', '4', '5', '6', '7'],
answer: 3,
explanation: '피타고라스 정리: 3² + 4² = 9 + 16 = 25 = 5². 빗변 = 5.',
},
{
number: 23,
question: '삼각형 내각의 이등분선의 교점을 무엇이라 하는가?',
choices: ['외심', '무게중심', '수심', '내심', '꼭짓점'],
answer: 4,
explanation: '내각의 이등분선 교점 = 내심(내접원의 중심). 외각이등분선 교점은 방심.',
},
{
number: 24,
question: '세 중선의 교점(무게중심)은 각 중선을 꼭짓점으로부터 몇 대 몇으로 나누는가?',
choices: ['1:1', '1:2', '2:1', '3:1', '1:3'],
answer: 3,
explanation: '무게중심은 각 중선을 꼭짓점에서부터 2:1로 나눈다.',
},
// ── 확률 (25~30) ─────────────────────────────────────────────────────────────
{
number: 25,
question: '주사위 한 개를 던질 때 짝수가 나올 확률은?',
choices: ['1/6', '1/3', '1/2', '2/3', '5/6'],
answer: 3,
explanation: '짝수의 눈: 2, 4, 6 → 3가지. 전체 6가지. 확률 = 3/6 = 1/2.',
},
{
number: 26,
question: '10장의 카드(1~10)에서 한 장을 뽑을 때 3의 배수일 확률은?',
choices: ['1/10', '2/10', '3/10', '4/10', '5/10'],
answer: 3,
explanation: '3의 배수: 3, 6, 9 → 3가지. 확률 = 3/10.',
},
{
number: 27,
question: '동전 2개를 동시에 던질 때 둘 다 앞면일 확률은?',
choices: ['1/4', '1/2', '3/4', '1/3', '2/3'],
answer: 1,
explanation: '전체 경우: HH, HT, TH, TT → 4가지. 둘 다 앞면: HH → 1가지. 확률 = 1/4.',
},
{
number: 28,
question: 'P(A) = 1/3 일 때, A가 일어나지 않을 확률은?',
choices: ['1/6', '1/4', '1/3', '2/3', '5/6'],
answer: 4,
explanation: '여사건 확률 = 1 P(A) = 1 1/3 = 2/3.',
},
{
number: 29,
question: '어떤 사건 A와 B가 서로 배반이고 P(A) = 0.4, P(B) = 0.3이면 P(A 또는 B)는?',
choices: ['0.1', '0.3', '0.4', '0.7', '0.12'],
answer: 4,
explanation: '배반사건이면 P(A B) = P(A) + P(B) = 0.4 + 0.3 = 0.7.',
},
{
number: 30,
question: '빨간 공 4개, 파란 공 6개가 든 주머니에서 공 1개를 꺼낼 때 파란 공일 확률은?',
choices: ['2/5', '3/5', '4/10', '1/4', '1/2'],
answer: 2,
explanation: '파란 공 6개 / 전체 10개 = 6/10 = 3/5.',
},
];

View File

@@ -0,0 +1,235 @@
import type { SampleProblem } from './types';
export const PROBLEMS: SampleProblem[] = [
// ── 인수분해 (1~5) ────────────────────────────────────────────────────────────
{
number: 1,
question: 'x² + 5x + 6 을 인수분해하면?',
choices: ['(x+1)(x+6)', '(x+2)(x+3)', '(x2)(x3)', '(x+3)(x+2)', '(x1)(x6)'],
answer: 2,
explanation: '두 수의 합 = 5, 곱 = 6인 수: 2와 3. 따라서 (x+2)(x+3). ※ ②와 ④는 동일해서 ②가 정답.',
},
{
number: 2,
question: 'x² 9 를 인수분해하면?',
choices: ['(x3)²', '(x+3)²', '(x3)(x+3)', '(x9)(x+1)', '인수분해 불가'],
answer: 3,
explanation: '합차 공식: a² b² = (ab)(a+b). x² 9 = x² 3² = (x3)(x+3).',
},
{
number: 3,
question: '2x² + 4x 를 인수분해하면?',
choices: ['2(x+2)', '2x(x+2)', 'x(2x+4)', '2(x²+2x)', '(2x+1)(x+2)'],
answer: 2,
explanation: '공통인수 2x를 묶는다. 2x² + 4x = 2x(x + 2).',
},
{
number: 4,
question: 'x² 6x + 9 를 인수분해하면?',
choices: ['(x3)(x+3)', '(x3)²', '(x+3)²', '(x9)(x+1)', '(x1)(x9)'],
answer: 2,
explanation: '완전제곱식: x² 2·3·x + 3² = (x3)². 완전제곱 공식 (ab)² = a²2ab+b².',
},
{
number: 5,
question: '3x² 12 를 인수분해하면?',
choices: ['3(x²4)', '3(x2)(x+2)', '(3x6)(x+2)', '3(x+2)²', '(x2)(3x+6)'],
answer: 2,
explanation: '공통인수 3을 묶은 후 합차 공식: 3(x²4) = 3(x2)(x+2).',
},
// ── 이차방정식 (6~10) ─────────────────────────────────────────────────────────
{
number: 6,
question: 'x² 5x + 6 = 0 의 두 근의 합은?',
choices: ['6', '5', '1', '5', '6'],
answer: 4,
explanation: '(x2)(x3) = 0 → x = 2 또는 x = 3. 두 근의 합 = 2 + 3 = 5. (비에타: (5)/1 = 5)',
},
{
number: 7,
question: 'x² 4 = 0 의 해는?',
choices: ['x = 2', 'x = 2', 'x = ±2', 'x = 4', 'x = ±4'],
answer: 3,
explanation: 'x² = 4. x = ±√4 = ±2.',
},
{
number: 8,
question: '이차방정식 x² + 2x 8 = 0 의 두 근 중 큰 값은?',
choices: ['4', '2', '2', '4', '8'],
answer: 3,
explanation: '(x+4)(x2) = 0 → x = 4 또는 x = 2. 큰 값은 2.',
},
{
number: 9,
question: '근의 공식을 이용해 2x² 3x 2 = 0 을 풀면 해는?',
choices: ['x = 2 또는 x = 1/2', 'x = 1 또는 x = 2', 'x = 3 또는 x = 1', 'x = 2 또는 x = 1', 'x = 2 또는 x = 1/2'],
answer: 1,
explanation: 'x = (3 ± √(9+16)) / 4 = (3 ± 5) / 4. x = 8/4 = 2 또는 x = 2/4 = 1/2.',
},
{
number: 10,
question: '판별식 D = b² 4ac 에서 D > 0이면 이차방정식의 근의 개수는?',
choices: ['0개(허수)', '1개(중근)', '2개(서로 다른 실근)', '무한개', '판단 불가'],
answer: 3,
explanation: 'D > 0이면 서로 다른 두 실근, D = 0이면 중근(1개), D < 0이면 실근 없음.',
},
// ── 이차함수 (11~15) ──────────────────────────────────────────────────────────
{
number: 11,
question: 'y = x² 4x + 3 의 꼭짓점 좌표는?',
choices: ['(2, 1)', '(2, 1)', '(4, 3)', '(2, 1)', '(4, 3)'],
answer: 1,
explanation: 'y = (x2)² 1로 변형. 꼭짓점은 (2, 1).',
},
{
number: 12,
question: 'y = (x 1)² + 4 의 최댓값은?',
choices: ['4', '1', '1', '4', '5'],
answer: 4,
explanation: '위로 볼록 포물선. 꼭짓점 (1, 4)에서 최댓값 = 4.',
},
{
number: 13,
question: 'y = 2x² 의 그래프의 특징으로 옳은 것은?',
choices: [
'아래로 볼록, 꼭짓점 (0,0)',
'위로 볼록, 꼭짓점 (0,0)',
'아래로 볼록, 꼭짓점 (2,0)',
'y = x²보다 폭이 넓다',
'기울기가 2인 직선',
],
answer: 1,
explanation: 'a = 2 > 0이므로 아래로 볼록, 꼭짓점은 (0, 0). a의 절댓값이 클수록 폭이 좁다.',
},
{
number: 14,
question: 'y = x² + 2x 3 의 x 절편의 개수는?',
choices: ['0', '1', '2', '3', '무한'],
answer: 3,
explanation: 'x² + 2x 3 = (x+3)(x1) = 0 → x = 3 또는 x = 1. x 절편 2개.',
},
{
number: 15,
question: 'y = a(xp)² + q 에서 꼭짓점이 (3, 2)이고 a = 1이면 이 함수의 식은?',
choices: [
'y = (x+3)² 2',
'y = (x3)² + 2',
'y = (x3)² 2',
'y = (x+3)² + 2',
'y = (x2)² 3',
],
answer: 3,
explanation: 'y = a(xp)² + q에 a=1, p=3, q=2를 대입하면 y = (x3)² 2.',
},
// ── 피타고라스 / 삼각비 (16~22) ──────────────────────────────────────────────
{
number: 16,
question: '직각삼각형에서 두 다리가 5, 12일 때 빗변은?',
choices: ['10', '11', '13', '14', '15'],
answer: 3,
explanation: '5² + 12² = 25 + 144 = 169 = 13². 빗변 = 13.',
},
{
number: 17,
question: '빗변이 10, 한 다리가 6인 직각삼각형에서 나머지 다리의 길이는?',
choices: ['4', '6', '7', '8', '9'],
answer: 4,
explanation: '6² + b² = 10² → 36 + b² = 100 → b² = 64 → b = 8.',
},
{
number: 18,
question: '직각삼각형에서 각 A의 맞은편 변이 3, 빗변이 5이면 sin A는?',
choices: ['3/5', '4/5', '3/4', '5/3', '5/4'],
answer: 1,
explanation: 'sin = (맞은편 변) / (빗변) = 3/5.',
},
{
number: 19,
question: '각 B에서 인접변이 4, 빗변이 5이면 cos B는?',
choices: ['3/5', '4/5', '3/4', '5/4', '5/3'],
answer: 2,
explanation: 'cos = (인접변) / (빗변) = 4/5.',
},
{
number: 20,
question: 'tan 30° 의 값은?',
choices: ['√3', '1/√3 (= √3/3)', '√2/2', '1', '√3/2'],
answer: 2,
explanation: 'tan 30° = sin 30° / cos 30° = (1/2) / (√3/2) = 1/√3 = √3/3.',
},
{
number: 21,
question: 'sin 45° 의 값은?',
choices: ['1/2', '√2/2', '√3/2', '1', '√2'],
answer: 2,
explanation: '45-45-90 삼각형에서 sin 45° = 1/√2 = √2/2.',
},
{
number: 22,
question: '각 C = 90°인 직각삼각형에서 tan A = 4/3이면 sin A는? (빗변 = 5 기준)',
choices: ['3/5', '4/5', '3/4', '4/3', '5/4'],
answer: 2,
explanation: 'tan A = 맞은편/인접 = 4/3. 빗변 = √(4²+3²) = 5. sin A = 4/5.',
},
// ── 원의 성질 (23~30) ─────────────────────────────────────────────────────────
{
number: 23,
question: '중심각이 60°인 부채꼴에서 같은 원 위의 원주각의 크기는?',
choices: ['15°', '30°', '60°', '90°', '120°'],
answer: 2,
explanation: '원주각 = 중심각 / 2. 60° / 2 = 30°.',
},
{
number: 24,
question: '반지름 6 cm인 원에서 중심각 90°인 부채꼴의 호의 길이는?',
choices: ['2π cm', '3π cm', '4π cm', '6π cm', '9π cm'],
answer: 2,
explanation: '호의 길이 = 2πr × (중심각/360°) = 2π × 6 × (90/360) = 12π × 1/4 = 3π cm.',
},
{
number: 25,
question: '원에서 원주각이 같은 호에 대해 원주각의 크기는?',
choices: ['호의 길이에 비례', '항상 같다', '중심각의 2배', '중심각과 같다', '호의 길이와 무관'],
answer: 2,
explanation: '같은 호에 대한 원주각은 모두 같다(원주각의 크기 일정성).',
},
{
number: 26,
question: '원에 내접하는 사각형에서 마주보는 두 각의 합은?',
choices: ['90°', '120°', '180°', '270°', '360°'],
answer: 3,
explanation: '원에 내접하는 사각형(원내접 사각형)에서 대각의 합 = 180°.',
},
{
number: 27,
question: '원의 접선과 현이 이루는 각(접선-현의 각)의 크기는 그 현에 대한?',
choices: ['중심각과 같다', '원주각과 같다', '원주각의 2배', '중심각의 절반', '접선의 길이와 같다'],
answer: 2,
explanation: '접선과 현의 각(접현각) = 그 현이 대하는 원주각. 접선-현의 각 정리.',
},
{
number: 28,
question: '두 원이 외부에서 접할 때 공통 접선의 개수는?',
choices: ['1', '2', '3', '4', '0'],
answer: 3,
explanation: '두 원이 외접(외부에서 접)할 때 공통 접선은 3개(외부 공통 접선 2 + 내부 공통 접선 1).',
},
{
number: 29,
question: '원의 중심으로부터 현까지의 수선은 현을 어떻게 나누는가?',
choices: ['1:2로', '2:1로', '이등분한다', '황금비로', '나누지 않는다'],
answer: 3,
explanation: '원의 중심에서 현에 내린 수선은 현을 이등분한다(원과 현의 성질).',
},
{
number: 30,
question: '반지름 5 cm인 원에서 반지름에 수직인 현의 길이가 8 cm이면 중심에서 현까지의 거리는?',
choices: ['2 cm', '3 cm', '4 cm', '5 cm', '6 cm'],
answer: 2,
explanation: '현의 절반 = 4 cm. 피타고라스: 5² = 4² + d² → d² = 9 → d = 3 cm.',
},
];

View File

@@ -0,0 +1,7 @@
export interface SampleProblem {
number: number;
question: string;
choices: string[];
answer: number; // 1-based
explanation: string;
}