JAVASCRIPT

퀴즈 이펙트 만들기 7 (CBT 유형)

hyejeong3283 2023. 4. 4. 00:03
728x90
반응형

json 형식의 데이터를 이용해 CBT 유형으로 퀴즈 이펙트를 만들었습니다.

 

HTML

<!DOCTYPE html>
<html lang="ko">
<head> 
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퀴즈 이펙트07</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/quiz.css">

    <link rel="shortcut icon" type="image/x-icon" href="img/favicon.png"/>  
    <link rel="apple-touch-icon" sizes="114x114" href="img/favicon.png"/> 
    <link rel="apple-touch-icon" href="img/favicon.png"/>

</head>
<body>
    <header id="header">
        <h1><a href="../javascript14.html">Quiz</a> <em>객관식 확인 CBT 유형</em></h1>
        <ul>
            <li><a href="quizEffect01.html">1</a></li>
            <li><a href="quizEffect02.html">2</a></li> 
            <li><a href="quizEffect03.html">3</a></li>
            <li><a href="quizEffect04.html">4</a></li>
            <li><a href="quizEffect05.html">5</a></li>
            <li><a href="quizEffect06.html">6</a></li>
            <li class="active"><a href="quizEffect07.html">7</a></li>
        </ul>
    </header>
    <!-- //header -->

    <main id="main">
        <div class="quiz__wrap__cbt">
            <div class="cbt__header">
                <h2>2020년 1회 정보처리기능사 기출문제</h2>
            </div>
            <div class="cbt__conts">
                <div class="cbt__quiz">
                    <!-- <div class="cbt good">
                        <div class="cbt__question"><span>1</span>. 객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                        <div class="cbt__question__img"><img src="img/gineungsaWD2023_01_01.jpg" alt="기능사"></div>
                        <div class="cbt__selects">
                            <input type="radio" id="select1">
                            <label for="select1"><span>클래스</span></label>
                            <input type="radio" id="select2">
                            <label for="select2"><span>메소드</span></label>
                            <input type="radio" id="select3">
                            <label for="select3"><span>상속</span></label>
                            <input type="radio" id="select4">
                            <label for="select4"><span>메시지</span></label>
                        </div>
                        <div class="cbt__desc">객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다. 객체지향언어는 이다.</div>
                        <div class="cbt__keyword">객체지향언어</div>
                    </div> -->
                </div>
            </div>
            <div class="cbt__aside">
                <div class="cbt__info">
                    <div>
                        <div class="cbt__title">수험자 : <em>이혜정</em></div>
                        <div class="cbt__score">
                            <span>전체 문제수 : <em>60</em>문항</span>
                            <span>남은 문제수 : <em>59문항</em></span>
                        </div>
                    </div>
                </div>
                <div class="cbt__omr">
                    <!-- <div class="omr">
                        <strong>1</strong>
                        <input type="radio" id="omr0_1">
                        <label for="omr0_1">
                            <span class="label-inner">1</span>
                        </label>
                        <input type="radio" id="omr0_2">
                        <label for="omr0_2">
                            <span class="label-inner">2</span>
                        </label>
                        <input type="radio" id="omr0_3">
                        <label for="omr0_3">
                            <span class="label-inner">3</span>
                        </label>
                        <input type="radio" id="omr0_4">
                        <label for="omr0_4">
                            <span class="label-inner">4</span>
                        </label>
                    </div> -->
                </div>
            </div>
            <div class="cbt__submit">제출하기</div>
            <div class="cbt__time">59분 10초</div>
        </div>
    </main>
    <!-- //main -->
</body>
</html>
  • 문제를 푸는 부분과 omr 부분을 나누어 줍니다. 
  • 문제, 문제 번호, 문제 이미지, 객관식 보기를 각각 태그를 사용해서 구성을 해줍니다.
  • 수험자정보, 총 문제수와 남은 문제수를 태그를 사용해 각 영역을 만듭니다.
  • 문제를 풀고 제출하는 영역과 시간이 카운팅 되는 영역을 만들어 줍니다.

 

JSON

[
    {
        "subject": "소프트웨어 설계",
        "question": "GoF(Gang of Four)의 디자인 패턴에서 행위 패턴에 속하는 것은?",
        "question_desc": "문제에 대한 설명 부분",
        "correct_answer": "Visitor",
        "incorrect_answers": ["Builder","prototype","Bridge"],
        "desc": "문제에 대한 해설 부분입니다.",
        "keyword_num": "24",
        "keyword": "디자인 패턴"
    },{
        "subject": "소프트웨어 설계",
        "question": "객체지향 프로그램에서 데이터를 추상화하는 단위는?",
        "correct_answer": "클래스",
        "incorrect_answers": ["메소드","상속성","메시지"],
        "keyword": "객체지향",
        "keyword_num": "22",
        "desc": "객체지향 구성 요소에는 클래스(Class), 객체(Object), 인스턴스(Instance), 메시지(Message), 메소드(Method) 등이 있다."
    },{
        "subject": "소프트웨어 설계",
        "question": "객체지향 기법에서 클래스들 사이의 '부분-전체(part-shole)' 관계 또는 '부분(is-a-part-of)'의 관계로 설명되는 연관성을 나태나는 용어는?",
        "correct_answer": "집단화",
        "incorrect_answers": ["일반화","추상화","캡슐화"],
        "keyword": "객체지향",
        "keyword_num": "22"
    },{
        "subject": "소프트웨어 설계",
        "question": "객체지향 분석 방법론 중 E-R 다이어그램을 사용하여 객체의 행위를 모델링하여, 객체 식별, 구조 식별, 주체 정의, 속성 및 관계 정의, 서비스 정의 등의 과정으로 구성되는 것은?",
        "correct_answer": "Coad와 Yourdon 방법",
        "incorrect_answers": ["Booch 방법","Jacobson 방법","Wirfs-Brocks 방법"],
        "desc": "객체지향 분석 방법론에는 Rumbaugh(럼바우), Booch, Jacobson, Coad와 Yourdon, Wirfs-brock 등이 있다.",
        "keyword": "객체지향 분석 방법론",
        "keyword_num": "23"
    },{
        "subject": "소프트웨어 설계",
        "question": "코드 설계에서 일정한 일련번호를 부여하는 방식의 코드는?",
        "correct_answer": "순차 코드",
        "incorrect_answers": ["연상 코드","블록 코드","표의 숫자 코드"]
    },{
        "subject": "소프트웨어 설계",
        "question": "소프트웨어 설계 시 구축된 플랫폼의 성능 특성 분석에 사용되는 측정 항목이 아닌 것은?",
        "correct_answer": "서버 튜닝(Server Tunning)",
        "incorrect_answers": ["응답시간(Response Time)","가용성(Availability)","사용률(Utilization)"]
    },{
        "subject": "소프트웨어 설계",
        "question": "자료 사전에서 자료의 생략을 의미하는 기호는?",
        "correct_answer": "()",
        "incorrect_answers": ["{}","**","="],
        "keyword": "구조적 분석",
        "keyword_num": "2"
    },{
        "subject": "소프트웨어 설계",
        "question": "검토회의 전에 요구사항 명세서를 미리 배포하여 사전 검토한 후 짧은 검토 회의를 통해 오류를 조기에 검출하는 데 목적을 두는 요구사항 검토 방법은?",
        "correct_answer": "워크 스루",
        "incorrect_answers": ["빌드 검증","동료 검토","개발자 검토"],
        "keyword": "요구사항분석",
        "keyword_num": "35"
    },{
        "subject": "소프트웨어 설계",
        "question": "CASE가 갖고 있는 주요 기능이 아닌 것은?",
        "correct_answer": "언어 번역",
        "incorrect_answers": ["그래픽 지원","소프트웨어 생명주기 전 단계의 연결","다양한 소프트웨어 개발 모형 지원"],
        "keyword": "CASE",
        "keyword_num": "36"
    },{
        "subject": "소프트웨어 설계",
        "question": "XP(eXtreme Programming)의 5가지 가치로 거리가 먼 것은?",
        "correct_answer": "정형 분석",
        "incorrect_answers": ["용기","의사소틍","피드백"],
        "desc": "익스트림 프로그래밍(eXtreme Programming, XP)는 켄트 백 등이 제안한 소프트웨어 개발 방법이다.<br> XP에는 용기(Courage), 단순성(Simplicity), 커뮤니케이션(Communication), 피드백(Feedback), 존중(Respect) 5가지 가치가 있다.",
        "keyword": "XP",
        "keyword_num": "8"
    },{
        "subject": "소프트웨어 설계",
        "question": "DBMS 분석 시 고려사항으로 거리가 먼 것은?",
        "correct_answer": "네트워크 구성도",
        "incorrect_answers": ["가용성","성능","상호 호환성"]
    },{
        "subject": "소프트웨어 설계",
        "question": "HIPO(Hierachy Input Process Output)에 대해서 설명으로 거리가 먼 것은?",
        "correct_answer": "상향식 소프트웨어 개발을 위한 문서화 도구이다.",
        "incorrect_answers": ["HIPO 차트 종류에는 가시적 도표, 총체적 도표, 세부적 도표가 있다.","기능과 자료의 의존 관계를 동시에 표현할 수 있다.","보기 쉽고 이해하기 쉽다."],
        "desc": "하향식 개발을 위한 시스템 설계 및 문서화 도구이다. 가시적 도표, 총체적 도표, 세부적 도표으로 구성되며 분석 및 설계 도구로 사용된다.",
        "keyword": "구조적 분석",
        "keyword_num": "2"
    },{
        "subject": "소프트웨어 설계",
        "question": "UI 설계 원칙에서 누구나 쉽게 이해하고 사용할 수 있어야 한다는 것은?",
        "correct_answer": "직관성",
        "incorrect_answers": ["유효성","무결성","유연성"],
        "desc": "UI 설계 원칙으로 직관성, 유효성, 학습성, 유연성이 있다.",
        "keyword": "UI",
        "keyword_num" : "5"
    },{
        "subject": "소프트웨어 설계",
        "question": "럼바우(Rumbaugh)의 객체 지향 분석 절차를 가장 바르게 나열한 것은?",
        "correct_answer": "객체 모형 -> 동적 모형 -> 기능 모형",
        "incorrect_answers": ["객체 모형 -> 기능 모형 -> 동적 모형","기능 모형 -> 동적 모형 -> 객체 모형","기능 모형 -> 객체 모형 -> 동적 모형"],
        "desc": "소프트웨어 구성 요소를 그래픽 표기법을 이용하여 모델링하는 객체지향 분석(Object-oriented Analysis) 기법이다.",
        "keyword": "객체지향 분석 방법론",
        "keyword_num": "23"
    },{
        "subject": "소프트웨어 설계",
        "question": "데이터 흐름도(DFD)의 구성 요소에 포함되지 않는 것은?",
        "correct_answer": "data dictionary",
        "incorrect_answers": ["process","data flow","data store"],
        "desc": "자료흐름도(DFD)의 구성 요소에는 처리(Process), 자료흐름(Data Flow), 자료저장소(Data Store), 단말(Terminator) 등이 있다.",
        "keyword": "구조적 분석",
        "keyword_num": "2"
    },{
        "subject": "소프트웨어 설계",
        "question": "데이터 흐름도(DFD)의 구성 요소에 포함되지 않는 것은?",
        "correct_answer": "<< >>",
        "incorrect_answers": ["(( ))","{{ }}","[[ ]]"],
        "keyword": "구조적 분석",
        "keyword_num": "2"
    },{
        "subject": "소프트웨어 설계",
        "question": "트랜잭션이 올바르게 처리되고 있는지 데이터를 감시하고 제어하는 미들웨어는?",
        "correct_answer": "TP monitor",
        "incorrect_answers": ["RPC","ORB","HUB"],
        "desc": "트랜잭션은 데이터베이스(DB)에서의 상호작용의 단위(논리적 단위)이다. RPC : 원격 프로시저 호출 / ORB : 브로커를 통해 다른 컴퓨터의 프로그램 호출",
        "keyword": "트랜잭션",
        "keyword_num": "29"
    },{
        "subject": "소프트웨어 설계",
        "question": "소프트웨어 개발 방법 중 요구사항 분석(requirements analysis)과 거리가 먼 것은?",
        "correct_answer": "설계 명세서 작성",
        "incorrect_answers": ["비용과 일정에 대한 제약 설정","타당성 조사","요구사항 정의 문서화"],
        "desc": "요구사항 분석이 마무리되면 설계 단계가 시작되며, 설계가 마무리되면 명세서를 작성한다.",
        "keyword": "요구사항분석",
        "keyword_num": "35"
    },{
        "subject": "소프트웨어 설계",
        "question": "공동 모듈에 대한 명세 기법 중 해당 기능에 대해 일관되게 이해되고 한 가지로 해석될 수 있도록 작성하는 원칙은?",
        "correct_answer": "명확성",
        "incorrect_answers": ["상호작용성","독립성","내용성"],
        "keyword": "모듈화",
        "keyword_num": "41"
    },{
        "subject": "소프트웨어 설계",
        "question": "UML 모델에서 사용되는 Structural Diagram에 속하지 않는 것은?",
        "correct_answer": "Activity Diagram",
        "incorrect_answers": ["Class Diagram","Object Diagram","Component Diagram"],
        "desc" : "구조적 다이어그램에는 클래스, 객체, 복합체, 배치, 컴포넌트, 패키지가 있습니다.",
        "keyword": "UML",
        "keyword_num": "31"
    },
    {
        "subject": "소프트웨어 개발",
        "question": "정렬된 N개의 데이터를 처리하는데 O(Nlog2N)의 시간이 소요되는 정렬 알고리즘은?",
        "correct_answer": "합병정렬",
        "incorrect_answers": ["선택정렬","삽입정렬","버블정렬"],
        "keyword": "정렬",
        "keyword_num": "14"
    },{
        "subject": "소프트웨어 개발",
        "question": "평가 점수에 따른 성적부여는 다음 표와 같다. 이를 구현한 소프트웨어를 경계값 분석 기법으로 테스트 하고자 할 때 다음 중 테스트 케이스의 입력 값으로 옳지 않은 것은?",
        "question_img": "gisa2020_01_01",
        "correct_answer": "90",
        "incorrect_answers": ["59","80","101"],
        "desc": "경계값 분석은 경계 근처 값을 넣어야 의미가 있음"
    },{
        "subject": "소프트웨어 개발",
        "question": "다음 트리의 차수(degree)와 단말 노드(terminal node)의 수는?",
        "question_img": "gisa2020_01_02",
        "correct_answer": "차수: 2, 단말 노드: 4",
        "incorrect_answers": ["차수: 4, 단말 노드: 4", "차수: 4, 단말 노드: 8", "차수: 2, 단말 노드: 8"],
        "keyword": "릴레이션",
        "keyword_num": "30"
    },{
        "subject": "소프트웨어 개발",
        "question": "검증 검사 기법 중 개발자의 장소에서 사용자가 개발자 앞에서 행하는 기법이며, 일반적으로 통제된 환경에서 사용자와 개발자가 함계 확인하면서 수행되는 검사는?",
        "correct_answer": "알파검사",
        "incorrect_answers": ["동치 분할 검사", "형상 검사", "베타 검사"],
        "desc": "동치 분할 검사 : 입력 자료에 촘점을 맞춰 검사 사례를 만들고 검사하는 방법 <br> 형상 검사 : 구성 요소, 목록, 유지보수를 위한 모든 사항이 표현되었는가를 검사 <br> 베타 검사 : 통제된 환경 외에서 사용자들이 직접 검사"
    },{
        "subject": "소프트웨어 개발",
        "question": "하향식 통합에 있어서 모듈 간의 통합 시험을 위해 일시적으로 필요한 조건만을 가지고 임시로 제공되는 시험용 모듈을 무엇이라고 하는가?",
        "correct_answer": "Stub",
        "incorrect_answers": ["Driver", "Procedure", "Function"],
        "desc": "Driver는 상향식 통합 모듈에 사용된다.",
        "keyword": "통합테스트",
        "keyword_num": "3"
    }
]

문제 정보가 들어있는 json 파일입니다. 이를 기반으로 퀴즈 페이지를 만들어줍니다.

문제 수가 많아 조금 줄여서 올렸습니다.

 

JAVASCRIPT

<script>
        const cbt = document.querySelectorAll(".cbt");
        const cbtQuiz = document.querySelector(".cbt__quiz");
        const cbtOmr = document.querySelector(".cbt__omr");
        const cbtSubmit = document.querySelector(".cbt__submit");

        let questionAll = [];  //모든 퀴즈 정보

        //데이터 가져오기
        const dataQuestion = () => {
            fetch("json/gisa2020_01.json")
            .then(res => res.json())
            .then(items => {
                questionAll = items.map((item, index) => {
                    const formattedQuestion = {
                        question: item.question,
                        number: index + 1
                    }
                    const answerChoices = [...item.incorrect_answers];  //오답 불러오기
                    formattedQuestion.answer = Math.floor(Math.random() * answerChoices.length) + 1;
                    answerChoices.splice(formattedQuestion.answer - 1, 0, item.correct_answer); 

                    //보기를 추가
                    answerChoices.forEach((choice, index) => {                  
                        formattedQuestion["choice" + (index+1)] = choice;
                    });

                    //문제에 대한 해설이 있으면 출력
                    if(item.hasOwnProperty("question_desc")){
                        formattedQuestion.questionDesc = item.question_desc;
                    }

                    //문제에 대한 이미지가 있으면 출력
                    if(item.hasOwnProperty("question_img")){
                        formattedQuestion.questionImg = item.question_img;
                    }

                    //해설이 있으면 출력
                    if(item.hasOwnProperty("desc")){
                        formattedQuestion.desc = item.desc;
                    }

                    //console.log(formattedQuestion);
                    return formattedQuestion;
                });
                newQuestion();  //문제 만들기

            })
            .catch((err) => console.log(err));
        }

        //문제 만들기
        const newQuestion = () => {
            const exam = [];
            const omr = [];

            questionAll.forEach((question, number) => {
                exam.push(`
                    <div class="cbt">
                        <div class="cbt__question"><span>${question.number}</span>. ${question.question}</div>
                        <div class="cbt__question__img"></div>
                        <div class="cbt__selects">
                            <input type="radio" id="select${number}_1" name="select${number}" value="${number+1}_1" onclick="answerSelect(this)">
                            <label for="select${number}_1"><span>${question.choice1}</span></label>
                            <input type="radio" id="select${number}_2" name="select${number}" value="${number+1}_2" onclick="answerSelect(this)">
                            <label for="select${number}_2"><span>${question.choice2}</span></label>
                            <input type="radio" id="select${number}_3" name="select${number}" value="${number+1}_3" onclick="answerSelect(this)">
                            <label for="select${number}_3"><span>${question.choice3}</span></label>
                            <input type="radio" id="select${number}_4" name="select${number}" value="${number+1}_4" onclick="answerSelect(this)">
                            <label for="select${number}_4"><span>${question.choice4}</span></label>
                        </div>
                        <div class="cbt__desc hide">${question.desc}</div>
                    </div>
                `);

                omr.push(`
                    <div class="omr">
                        <strong>${question.number}</strong>
                        <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_0">
                        <label for="omr${number}_1"><span class="label-inner">1</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_1">
                        <label for="omr${number}_2"><span class="label-inner">2</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_2">
                        <label for="omr${number}_3"><span class="label-inner">3</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_3">
                        <label for="omr${number}_4"><span class="label-inner">4</span></label>
                    </div>
                `)
            });
        
            cbtQuiz.innerHTML = exam.join('');
            cbtOmr.innerHTML = omr.join('');
        }

        //정답 확인
        const answerQuiz = () => {
            const cbtSelects = document.querySelectorAll(".cbt__selects");

            questionAll.forEach((question, number) => {
                const quizSelectsWrap = cbtSelects[number];
                const userSelector = `input[name=select${number}]:checked`;
                const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
                const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;

                if(numberAnswer == question.answer){
                    console.log("정답입니다.");
                    cbtSelects[number].parentElement.classList.add("good");
                } else {
                    console.log("오답입니다.")
                    cbtSelects[number].parentElement.classList.add("bad");
                    
                    // 오답일 경우 정답 표시
                    const label = cbtSelects[number].querySelectorAll("label");
                    label[question.answer-1].classList.add("correct");
                }

                // 설명 숨기기
                const quizDesc = document.querySelectorAll(".cbt__desc");

                if(quizDesc[number].innerHTML == "undefined"){
                    quizDesc[number].classList.add("hide");
                } else {
                    quizDesc[number].classList.remove("hide");
                }
            });
        }

        const answerSelect = () => {

        }

        cbtSubmit.addEventListener("click", answerQuiz);
        dataQuestion();

    </script>
  • dataQuestion 함수는
    fetch() 함수를 이용해 문제 정보가 들어있는 json파일을 불러오고, then() 메서드를 사용하여 불러온 데이터를 어떻게 사용할지 처리합니다.
  • newQuestion 함수는
    dataQuestion 함수에서  questionAll 에 담아둔 문제의 보기를 각 exam과 omr  영역에 출력하게 해주는 함수입니다.
    각 보기문항에 onclick 속성을 사용하여 문항을 선택할때 answerSelect 함수를 실행하도록 합니다.
  • answerSelect 함수는
    각 문제의 문항을 선택 했을때 실행되는 함수입니다.
  • answerQuiz 함수는
    선택한 문항이 정답일 경우의 이벤트와 오답일 경우의 이벤트를 정의해 둔 함수입니다.
    if ~ else 문을 사용하여 정답인 경우의 css효과 와 오답인 경우의 css를 어떻게 줄지 분기처리하였습니다.