OX퀴즈 웹페이지 만들기 – 3. 동작 구현

OX퀴즈 - 3. 동작구현

이전 글에서는 “OX퀴즈 웹페이지 만들기” 프로젝트의 첫 두 단계를 살펴보았습니다. 첫 번째 단계에서는 웹페이지의 구조를 설정하고 두 번째 단계에서는 스타일링을 적용하는 방법을 다뤘습니다. 이제 세 번째 단계에서는 웹페이지에 실질적인 퀴즈 동작을 구현해 보겠습니다.

[OX퀴즈 프로젝트 관련 게시물]

https://ljj.kr/ox퀴즈-웹페이지-만들기-1-마크업
https://ljj.kr/ox퀴즈-웹페이지-만들기-2-스타일링
https://ljj.kr/ox퀴즈-웹페이지-만들기-3-동작-구현

1. JavaScript 파일 생성

퀴즈 동작을 위해 JavaScript 파일을 생성합니다. 아래 단계를 따라 진행하세요.

HTML 파일에 JavaScript 연결

HTML 파일의 </body> 앞줄에 다음과 같은 코드를 추가하여 JavaScript 파일을 연결합니다.

<script src="ox.js"></script>

2. 퀴즈 동작 구현

이제 퀴즈 동작을 구현해 봅시다.

jQuery 기반 동작 구현

앞서 작성한 ox.js가 들어간 외부스크립트 앞줄에 jQuery 라이브러리를 불러와줍니다.

// 진행버튼
$("#bt").click(function(){
    var menu = $("#quiz").attr("class");
    if(menu=="start") {
        $("#quiz").attr("class","test");
        $("#bt").text("다음");
    }else if(menu=="test"){
        $(this).removeClass("next");
        if($("#bt").text()=="결과보기") {
            $("#quiz").attr("class","result");
            $("#bt").text("다시하기");
            // 점수계산
            var score = $("#quiz input[value=right]:checked").length / $("#quiz li").length * 100;
            $("#ending strong").text(score);
        } else {
            var n = $("#quiz li").index($("#quiz li.on"));
            $("#quiz li.on").removeClass("on");
            $("#quiz li").eq(++n).addClass("on");
            if($("#quiz li:last").hasClass("on")) {
                $("#bt").text("결과보기");
            } 
        }
    }else if(menu=="result") {
        // 시작화면으로 초기화
        $("#bt").text("시작하기");
        $("#quiz").attr("class","start");
        $("#quiz input").removeAttr("checked");
        $("#quiz label").removeAttr("class");
        $("#quiz li p").removeAttr("class");
        $("#quiz li p:last-child").hide();
        $("#quiz li.on").removeClass("on");
        $("#quiz li:first").addClass("on");
    }else {
        alert("설정한 상태가 아닙니다.")
    }
    return false;
})

// OX버튼
$("#quiz label input").click(function(){
    var result = $(this).parent().parent().children(":last-child").is(":hidden");
    if(result) {
        $(this).parent().parent().children(":last-child").show();
        var chk = $(this).val();
        if(chk=="right") {
            $(this).parent().addClass("right");
        } else {
            $(this).parent().addClass("wrong");
        }
        var n = $("li.on input").index($("li.on input[value=right]"));
        if(n==1) $(this).parent().parent().children(":last-child").addClass("right");
        $("#quiz #bt").addClass("next");
    }
})

전행버튼 : 전체동작은 ‘시작’, ‘퀴즈진행’, ‘결과로 크게 3화면으로 구분하였고 3단계의 디자인은 클래스로 구분하고 있기 때문에 스크립트에서는 클래값을 얻어 현재 상태를 체크하고 클래스를 변경함으로서 다음으로 진행하고 있습니다.

OX버튼 : 각문제의 정답에 의한 체크는 input의 value 값을 얻어 체크하고 있으며 다음문제로 진행하는 기능까지 담고 있습니다.

순수 Javascript 기반 동작 구현

이번에는 jQuery 순수 스크립트 버전으로 작성한 버전입니다.

// 진행버튼
document.getElementById("bt").addEventListener("click", function (e) {
    e.preventDefault();
    var menu = document.getElementById("quiz").className;
    if (menu == "start") {
        document.getElementById("quiz").className = "test";
        document.getElementById("bt").textContent = "다음";
    } else if (menu == "test") {
		document.getElementById("bt").classList.remove("next");
        if (this.textContent == "결과보기") {
            document.getElementById("quiz").className = "result";
            this.textContent = "다시하기";
            // 점수 계산
            var rightAnswers = document.querySelectorAll("#quiz input[value=right]:checked").length;
            var totalQuestions = document.querySelectorAll("#quiz li").length;
            var score = (rightAnswers / totalQuestions) * 100;
            document.querySelector("#ending strong").textContent = score;
        } else {
            var currentQuestion = document.querySelector("#quiz li.on");
            currentQuestion.classList.remove("on");
            var nextQuestion = currentQuestion.nextElementSibling;
            if (nextQuestion) {
                nextQuestion.classList.add("on");
                if (nextQuestion === document.querySelector("#quiz li:last-child.on")) {
                    this.textContent = "결과보기";
                }
            }
        }
    } else if (menu == "result") {
        // 시작화면으로 초기화
        this.textContent = "시작하기";
        document.getElementById("quiz").className = "start";
        var answerInputs = document.querySelectorAll("#quiz input[type='radio']");
        answerInputs.forEach(function (input) {
            input.checked = false;
        });
        var answerLabels = document.querySelectorAll("#quiz label");
        answerLabels.forEach(function (label) {
            label.className = "";
        });
        var answerFeedback = document.querySelectorAll("#quiz li p:last-child");
        answerFeedback.forEach(function (feedback) {
            feedback.className = "";
            feedback.style.display = "none";
        });
        document.querySelector("#quiz li.on").classList.remove("on");
        document.querySelector("#quiz li:first-child").classList.add("on");
    } else {
        alert("설정한 상태가 아닙니다.");
    }
    return false;
});

// OX버튼
var answerInputs = document.querySelectorAll("#quiz label input");
answerInputs.forEach(function (input) {
    input.addEventListener("click", function () {
        var result = window.getComputedStyle(document.querySelector("#quiz li.on p:last-child")).display;
        if (result == "none") {
            document.querySelector("#quiz li.on p:last-child").style.display = "block";
            var chk = this.value;
            if (chk == "right") {
                this.parentElement.classList.add("right");
				
            } else {
                this.parentElement.classList.add("wrong");
            }
            var rightInput = document.querySelector("li.on input[value=right]");
            var rightInputIndex = Array.from(answerInputs).indexOf(rightInput);
            if (rightInputIndex === 1) {
                this.parentElement.parentElement.lastElementChild.classList.add("right");
            }
        }
		document.getElementById("bt").classList.add("next");
    });
});

가능하면 jQuery와 같은 알고리즘이 되도록 구성을 하였으니 비교해서 보는 것도 좋을 것 같네요.

순수 스크립트로 재개발을 하는 경우 주의사항

저처럼 개발의 편의성등의 이유로 jQuery로 개발을 먼저 하고 필요시 순수스크립트로 재개발을 하는 경우가 있습니다. 이런 경우 몇가지 주의사항이 있습니다.

  1. 문법 차이
    jQuery와 순수 JavaScript는 문법이 다릅니다. jQuery의 함수와 메서드를 순수 JavaScript 코드로 대체해야 합니다.
  2. 브라우저 호환성
    jQuery는 다양한 브라우저에서 일관된 작동을 보장하기 위한 노력이 이미 포함되어 있습니다. 순수 JavaScript로 작업할 때는 브라우저 호환성에 특별한 주의를 기울여야 합니다.
  3. 이벤트 처리
    이벤트 핸들링이나 AJAX 요청과 같은 jQuery의 유용한 기능을 순수 JavaScript로 대체해야 합니다.
  4. DOM 조작
    DOM 요소를 선택하고 조작하는 방법은 jQuery와 순수 JavaScript 사이에 차이가 있으므로 주의가 필요합니다.
  5. 애니메이션
    jQuery는 애니메이션 효과를 쉽게 다룰 수 있도록 도와줍니다. 순수 JavaScript로 애니메이션을 구현하려면 추가적인 코드와 로직이 필요할 수 있습니다.
  6. 라이브러리 크기
    jQuery는 작은 웹 페이지에서는 부담이 되지 않지만, 대규모 웹 애플리케이션에서는 라이브러리 크기가 중요할 수 있습니다. 순수 JavaScript로 작업하면 라이브러리 크기를 줄일 수 있습니다.
  7. jQuery 플러그인
    jQuery 플러그인을 사용 중인 경우, 해당 플러그인을 대체할 수 있는 순수 JavaScript 라이브러리나 코드를 찾아야 합니다.
  8. 성능 고려
    jQuery는 최적화된 DOM 조작을 제공합니다. 순수 JavaScript로 작업할 때 성능을 고려하여 최적화된 코드를 작성해야 합니다.
  9. 테스트와 디버깅
    순수 JavaScript 코드의 테스트와 디버깅을 위한 도구를 활용하여 코드의 안정성과 신뢰성을 확보해야 합니다.

이러한 주의 사항을 고려하여 jQuery 코드를 순수 JavaScript 코드로 변환할 때는 작업의 복잡성과 시간을 고려해야 합니다. jQuery를 사용하는 이유 중 하나는 간단하고 편리한 문법이므로, 순수 JavaScript로 작업할 때 이러한 이점을 상실하지 않도록 주의해야 합니다.

이제 웹페이지를 미리보고 퀴즈 동작이 제대로 작동하는지 확인하세요. 사용자가 퀴즈를 풀고 결과를 확인할 수 있어야 합니다.

3. 추후 추가될 기능

기본 형태를 유지하는 OX퀴즈를 교육용을 목적으로 제작하였지만 실제로 웹서비스에 응용한다면 여러가지 아이디어와 요구사항을 접목할 수 있을것입니다. 가령 예를 들면

  • 타이머 기능
    각 문제에 대한 제한 시간을 설정하고, 퀴즈가 시작된 후 시간이 지나면 자동으로 다음 문제로 넘어가도록 만들 수 있습니다.
  • 힌트 기능
    각 문제에 대한 힌트 버튼을 추가하여, 사용자가 힌트를 요청할 수 있도록 만들 수 있습니다.
  • 랭킹 시스템
    사용자의 정답률을 저장하고, 사용자 간에 랭킹을 비교할 수 있는 시스템을 추가할 수 있습니다.
  • 음성 안내
    각 문제와 선택지에 대한 음성 안내를 제공하여 시각 장애인들도 이용할 수 있도록 만들 수 있습니다.
  • 다국어 지원
    퀴즈의 내용과 버튼 텍스트를 다양한 언어로 지원하고, 사용자가 언어를 선택할 수 있도록 만들 수 있습니다.
  • 색상 테마
    사용자가 원하는 색상 테마를 선택할 수 있도록 하여 사용자 정의 가능한 테마를 추가할 수 있습니다.
  • 소셜 미디어 공유
    사용자가 퀴즈 결과를 소셜 미디어에 공유할 수 있는 기능을 추가할 수 있습니다.

이러한 기능 중 하나 또는 여러 가지를 선택하여 퀴즈를 더 흥미롭게 만들 수 있습니다. 추가할 기능은 사용자의 요구 사항과 퀴즈의 목적에 따라 다를 수 있습니다.

5. 마무리

“OX퀴즈 웹페이지 만들기를 3개의 포스팅으로 나누어 진행을 해 봤습니다.
그래픽 엔진을 쓰고 게임엔진을 연동하지 않더라도 작은 아이디어를 웹게임으로 만들수 있으니 여러분들도 다양한 시도를 해보는게 좋을것 같네요.

자주 묻는 질문 (FAQs)

Q1. 퀴즈 데이터를 추가하려면 어떻게 해야 하나요?

A1. 퀴즈의 데이터는 마크업에서 작성하면 바로 연동되는 구조로 프로그래밍 하였기 때문에 마크업 추가만으로 쉽게 유지보수 할수 있습니다.

Q2. 추가 기능을 구현하려면 어떻게 해야 하나요?

A2. (문제)의 추가 기능을 구현하려면 DB연동이 필요할것 같네요. JavaScript만으로는 저장이 되지 않기 때문에 입장시 사용자의 이름을 입력 받는 정도만 가능하고 저장 기능이 필요한 것은 백엔드 언어를 사용하여 제작해야 합니다..

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다