🍊 계기

μ˜€λŠ˜μ€ λ“œλ””μ–΄ ꡐ윑 μ‹€μŠ΅ 2μ£Όμ°¨λ‹€. ν•™μƒλ“€μ΄λž‘ μ²΄μœ‘λŒ€νšŒλ„ 즐기고, μˆ˜μ—…λ„ νŽΈν•˜κ²Œ ν•˜κΈ° μœ„ν•΄μ„œλŠ” λΉ λ₯΄κ²Œ μΉœν•΄μ Έμ•Όν•  것 κ°™λ‹€λŠ” 압박감이 μžˆμ—ˆλ‹€. (λ¬Όλ‘  μ••λ°• μ™Έμ˜ 개인적 μš•μ‹¬λ„ μžˆμ—ˆλ‹€) 개발 곡뢀 ν•΄μ•Όν•  것은 λ§Žμ€λ°, κ΅μƒμ΄λΌλ‹ˆ.. ν•˜λ©° νˆ΄νˆ΄λŒ€λ‹€κ°€ 두 마리의 토끼λ₯Ό μž‘μ„ 방법이 λ– μ˜¬λžλ‹€! κ°œλ°œν•˜λ©΄μ„œ 학생듀과 μΉœν•΄μ§€λŠ” 것 (γ…‹γ…‹)

 

κ·Έλž˜μ„œ smoreλ‚˜ ꡬ글폼같은 νˆ΄μ„ μ‚¬μš©ν•˜μ§€ μ•Šκ³ , λ‚˜λ₯Ό μ†Œκ°œν•˜λŠ” λ‚΄μš©μ΄ λ‹΄κΈ΄ ν€΄μ¦ˆλ₯Ό λ§Œλ“€κΈ°λ‘œ κ²°μ‹¬ν–ˆλ‹€.

 

# λΉ„ν•˜μΈλ“œ

μ™œ μž₯고둜 ν–ˆλŠ”κ°€? 사싀 바닐라 μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ§Œλ“€ 생각에 μ„€λ œλ˜ 것인데 μ•½ ν•˜λ£¨-μ΄ν‹€λ§Œμ— λ§Œλ“€μ–΄μ•Όν•˜λŠ” 것과, λ‚˜μ˜ 자슀 μ‹€λ ₯을 κ³ λ €ν–ˆμ„ λ•Œ μ–΄λ €μ›Œλ³΄μ˜€λ‹€. λ¦¬μ•‘νŠΈλŠ” μ–Όλ§ˆλ‚˜ GOD인가... κ·ΈλŸ¬λ‚˜ λ°˜λ“œμ‹œ ꡐ생 이후에 λ¦¬νŒ©ν† λ§λ„ ν•˜κ³  바닐라JS둜 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ ν•΄μ•Όκ² λ‹€.

 

🍊 ν€΄μ¦ˆ κΈ°νšλ‚΄μš©

κΈ°νšμ€ 거의 2μ‹œκ°„.. μ•„λ‹ˆ 더 짧게 ν•œ 것 κ°™λ‹€. λ””μžμΈ λ½‘λŠ” μ‹œκ°„μ€ 슀λͺ¨μ–΄ μ°Έκ³ ν•΄μ„œ 맀우 μ΅œμ†Œν™”ν•˜μ˜€λ‹€.

 

λ¬Έμ œμœ ν˜•μ€ μ•„λž˜μ™€ 같이 5κ°œλ‹€. λΆ€λΆ„μ μˆ˜ λΆ€μ—¬λ‘œ μΌ€μ΄μŠ€λ₯Ό λ‹€μ–‘ν•˜κ²Œ ν•˜κΈ° μœ„ν•΄ λ³΅μˆ˜μ„ νƒ μœ ν˜•μ„ ν¬ν•¨μ‹œμΌ°λ‹€. μ„œμˆ ν˜•μ€ 닡이 λ„ˆλ¬΄ λ‹€μ–‘ν•˜κ²Œ λ‚˜μ˜¬ 것 κ°™μ•„μ„œ ν€΄μ¦ˆ μ’…λ£Œ ν›„ ν•˜κ³  싢은 말을 λ‚¨κΈ°λŠ” μš©λ„λ‘œλ§Œ ν™œμš©ν–ˆλ‹€.

 

λ¬Έμ œλ‚΄μš©μ€ μ•„λž˜μ˜ μ˜ˆμ‹œμ™€ 같이 정말 TMI(Too Much Information)둜만 κ΅¬μ„±ν–ˆλ‹€. λŒ€μ‹ , μ•½κ°„μ˜ ν•™μƒλ“€μ˜ λˆˆλ†’μ΄μ™€ μœ ν–‰μ— λ§žλŠ”.

각 문제의 배점을 λ‹¬λ¦¬ν•˜κ³ , (λ‚˜λ§Œμ˜?) 재미 μš”μ†Œλ‘œ νŠΉμ • 선택지에 λŒ€ν•œ νŒ¨λ„ν‹°(감점)도 μ μš©μ‹œμΌ°λ‹€. 

λ¬Έν•­ μ˜ˆμ‹œ1
λ¬Έν•­ μ˜ˆμ‹œ2

 


🍊 핡심 κ΅¬ν˜„ 사항

κ°œλ°œμ„ μ‹œμž‘ν•˜κΈ° μ „, 핡심 κ΅¬ν˜„ 사항듀을 μ•„λž˜μ™€ 같이 λ‚˜λˆ„μ–΄ μƒκ°ν•˜μ˜€λ‹€.

- 선택지λ₯Ό κ³ λ₯΄λ©΄ λ°”λ‘œ λ‹€μŒ 질문으둜 ν™”λ©΄ μ „ν™˜

- 문제 μœ ν˜•μ— 따라 λ‹€λ₯΄κ²Œ μ œμΆœλ˜λŠ” λ‹΅μ•ˆ

- μœ μ €κ°€ 제좜된 λ‹΅μ•ˆμ΄ ν•΄λ‹Ή μœ μ €μ˜ 점수둜 μ­‰ λˆ„μ λ˜μ–΄ μ΅œμ’… 점수 μ‚°μΆœ

 

 

1) 선택지λ₯Ό κ³ λ₯΄λ©΄ λ°”λ‘œ λ‹€μŒ 질문으둜 ν™”λ©΄ μ „ν™˜

이 뢀뢄이 사싀 바닐라 JS둜 처음 κ΅¬ν˜„ν•˜λ € ν–ˆμ„ λ•Œμ˜ λ©˜ν’ν¬μΈνŠΈμ˜€λ‹€. λΌμš°νŒ…μ„ μ–΄λ–»κ²Œ κ΅¬ν˜„ν• μ§€?κ°€ λ§‰λ§‰ν–ˆκ³ , 문제 μœ ν˜•μ΄ 계속 λ°˜λ³΅λ ν…λ° 이 μž¬μ‚¬μš©λ˜λŠ” 뢀뢄을 μ–΄λ–»κ²Œ 효율적으둜 μ§€μ§€, 질문/μ„ νƒμ§€λ‚΄μš©/배점 데이터λ₯Ό μ–΄λ–»κ²Œ λΏŒλ €μ€˜μ•Όν• μ§€κ°€ κ·Έλ €μ§€μ§€ μ•Šμ•˜λ‹€. μ‹œκ°„μ΄ 더 μžˆμ—ˆλ‹€λ©΄ 기쑴의 λΈ”λ‘œκ·Έ μ„ λ°°λ“€μ˜ 쒋은 글듀을 μ°Έκ³ ν•  수 μžˆμ—ˆκ² μ§€λ§Œ μΆ©λΆ„μΉ˜ μ•Šμ•˜λ‹€ πŸ₯²

 

결ꡭ은 μž₯κ³  templateμ—μ„œ 1번~14번 문항별 λͺ¨λ“  htmlνŒŒμΌμ„ λ‹€ μž‘μ„±ν–ˆλŠ”λ° 큰 흑역사 ν”Œμ  🀒으둜 남지 μ•Šμ„κΉŒ μ‹Άλ‹€...

(μ•„λ‹ˆμ§€ ν•˜λ©΄μ„œ μ„±μž₯ν•˜λŠ”κ±°λ‹ˆκΉŒ!)

 

/tmi_quiz/urls.py 일뢀

path('question/<int:question_id>', views.question, name="question")

 

/quiz/views.py 일뢀

def question(request, question_id):
    ongoing = Person.objects.get(name = request.user)
    return render(request, 'q{0}.html'.format(question_id), {'ongoing': ongoing})

 

ν™”λ©΄ μ „ν™˜μ€ 2κ°€μ§€ 경우둜 λ‚˜λˆ μ„œ μƒκ°ν–ˆλ‹€.

(1) μ–΄μ°¨ν”Ό ν•˜λ‚˜μ˜ 닡을 κ³ λ₯΄λŠ” μ„ νƒμ§€λŠ” - μ–΄λ–€ 선택지 λ²„νŠΌμ„ λˆ„λ₯΄λŠ” κ²ƒκ³ΌλŠ” 상관없이 클릭만 ν•˜λ©΄ 무쑰건 λ‹€μŒ 질문으둜 μ „ν™˜ν•˜λ©΄ 되고

(2) 볡수의 닡을 κ³ λ₯΄λŠ” μ„ νƒμ§€λŠ” - λ‚΄κ°€ 선택할 닡듀을 λ‹€ κ³ λ₯Έ 후에 λ„˜κΈ°κΈ° λ²„νŠΌμ„ 직접 λˆ„λ₯΄κ³  λ‚˜μ„œμ•Ό μ „ν™˜μ΄ λ˜μ–΄μ•Ό ν•œλ‹€

 

μ—¬νŠΌ 이 두 κ°€μ§€ 경우 λͺ¨λ‘ 선택지 μ—˜λ¦¬λ¨ΌνŠΈλ“€μ—λ‹€κ°€ clickμ΄λ²€νŠΈλ¦¬μŠ€λ„ˆλ₯Ό λ“±λ‘ν•˜μ—¬ 클릭 μ‹œ location.hrefλ₯Ό 직접 μ§€μ •ν•΄μ£Όμ—ˆλ‹€.

 

/quiz/templates/q4.html 일뢀

<script>

    // ... μƒλž΅ ... //
    const $choices = document.querySelectorAll(".basic-btn");
    for (let $choice of $choices) {
      $choice.addEventListener("click", (e)=> {
       
        console.log(e.target.innerText);
        if(e.target.innerText === "ν•­μ •μ‚΄") {
          // μ •λ‹΅ 처리 (점수 μΆ”κ°€)
          score += 5;
          console.log("μ •λ‹΅!")
        }

        window.localStorage.setItem("{{ user.username }}", JSON.stringify([score]));
        location.href = "http://localhost:8000/question/2"
      })
    }
  
  </script>

 

2) 문제 μœ ν˜•μ— 따라 λ‹€λ₯΄κ²Œ μ œμΆœλ˜λŠ” λ‹΅μ•ˆ

 

πŸ€“ 2μ§€μ„ λ‹€ 1선택, 4μ§€μ„ λ‹€ 1μ„ νƒπŸ€“

선택지 μ—˜λ¦¬λ¨ΌνŠΈ λͺ¨λ‘μ— 클릭 μ΄λ²€νŠΈλ¦¬μŠ€λ„ˆλ₯Ό λ“±λ‘ν•œλ‹€. ν΄λ¦­ν•œ μ—˜λ¦¬λ¨ΌνŠΈμ˜ λ‚΄μš©μ΄ μ •λ‹΅κ³Ό μΌμΉ˜ν•˜λ©΄ 점수λ₯Ό μ˜¬λ¦¬λŠ” λ°©μ‹μœΌλ‘œ μ²˜λ¦¬ν•˜μ˜€λ‹€. 재미λ₯Ό μœ„ν•΄ μ–΄λ–€ 선택지λ₯Ό κ³ λ₯Ό μ‹œμ—λŠ” κ°μ λ˜λ„λ‘ ν•˜μ˜€λ‹€.

let score = 0;
    const $choices = document.querySelectorAll(".basic-btn");
    for (let $choice of $choices) {
      $choice.addEventListener("click", (e)=> {
       
        console.log(e.target.innerText);
        if(e.target.innerText === "μ •λ‹΅λ©˜νŠΈ") {
          // μ •λ‹΅ 처리 (점수 μΆ”κ°€)
          score += 5;
          //console.log("μ •λ‹΅!")
        }

 

πŸ€“ μ΄λ―Έμ§€ 2μ§€μ„ λ‹€ 1μ„ νƒπŸ€“

이미지 선택지도 μœ„μ˜ μœ ν˜•κ³Ό 거의 λ™μΌν•œ 방식이닀. λ‹€λ§Œ, μœ μ €κ°€ ν΄λ¦­ν•˜λŠ” μ˜μ—­μ— 따라 이미지 divκ°€ λˆŒλ¦¬κΈ°λ„ ν•˜κ³ , 이미지 μ„€λͺ…이 λˆŒλ¦¬κΈ°λ„ ν–ˆλ‹€. 두 경우λ₯Ό λͺ¨λ‘ μ•„μš°λ₯΄κΈ° μœ„ν•΄ μ •λ‹΅ ν…μŠ€νŠΈλ₯Ό ν¬ν•¨ν•˜κ±°λ‚˜, 이미지 μˆœμ„œκ°€ 정닡에 ν•΄λ‹Ήν•˜λŠ” 경우λ₯Ό 쑰건으둜 μ •μ˜ν–ˆλ‹€.

  for (let $choice of $choices) {
      $choice.addEventListener("click", (e)=> {

        if(e.target.innerText.includes("슀파이크") || e.target.id.includes(2)) {
          // μ •λ‹΅ 처리 (점수 μΆ”κ°€)
          score += 4;
          console.log("μ •λ‹΅!");
        }

 

πŸ€“ 4μ§€μ„ λ‹€ 닀쀑 μ„ νƒπŸ€“

이 μœ ν˜•μ΄ λ‚˜λ¦„ κΉŒλ‹€λ‘œμ› λ‹€. λ‹€μŒκ³Ό 같은 사항을 λͺ¨λ‘ κ³ λ €ν•΄μ•Ό ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

(1) μœ μ €κ°€ κ³ λ₯Έ 선택지가 "μ„ νƒλ˜μ—ˆμŒ" λ˜λŠ” "μ·¨μ†Œλ˜μ—ˆμŒ"이 ν‘œμ‹œλ˜μ–΄μ•Ό ν•œλ‹€.

(2) λ‹€μŒ λ¬Έν•­μœΌλ‘œ λ„˜μ–΄κ°€κΈ° μ „ "μ΅œμ’…"적으둜 μ„ νƒλœ μ˜΅μ…˜λ“€μ„ λ°˜μ˜ν•΄μ•Ό ν•œλ‹€.

 

μ•„λž˜μ™€ 같이 4κ°€μ§€ 선택지에 λŒ€ν•œ 선택 μƒνƒœ(isChecked)λ₯Ό boolean λ°°μ—΄λ‘œ κ΄€λ¦¬ν•˜μ˜€λ‹€.

➑️ 점수 μ—…λ°μ΄νŠΈλŠ” λ‹€λ₯Έ μœ ν˜•λ“€κ³Ό 달리 μ‚¬μš©μžκ°€ 직접 λ‹€μŒ 문제둜 λ„˜μ–΄κ°€λŠ” λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ μ²˜λ¦¬λ˜λ„λ‘ ν–ˆλ‹€. '닀쀑 선택'μ΄λž€ μœ μ € μž…μž₯μ—μ„œλŠ” 계속 μ„ νƒν•œ μΌ€μ΄μŠ€λ“€μ„ λ³€κ²½ν•  수 있기 λ•Œλ¬Έμ— 직접 μ΅œμ’… μƒνƒœλ₯Ό κ²°μ •ν•˜λŠ” κΆŒν•œμ„ λ„˜κ²¨μ£Όμ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν–ˆλ‹€.

 let score = 0;

    let isChecked = [false,false,false,false];

    for (let i=0; i<4; i++) {
        $choices[i].addEventListener("click", (e) => {

        // μ²΄ν¬λ°•μŠ€ 체크처리
        isChecked[i] = !isChecked[i];
       
        // μ²΄ν¬λ°•μŠ€ μƒ‰κΉ”ν‘œμ‹œ
        if (isChecked[i]) {
            $choices[i].children[0].style.backgroundColor = 'yellow';
        } else {
            $choices[i].children[0].style.backgroundColor = 'white';
        }
        })
    }

    $nextBtn.addEventListener("click", (e) => {
        isChecked.forEach((check, idx) => {
            if (check && (idx === 1  || idx === 2)) {
                score += 6;
            }
        })

 

μ•„λž˜μ™€ 같은 λͺ¨μŠ΅μœΌλ‘œ λ™μž‘ν•˜κ²Œ λ˜μ—ˆλ‹€.

3) μœ μ €κ°€ 제좜된 λ‹΅μ•ˆμ΄ ν•΄λ‹Ή μœ μ €μ˜ 점수둜 μ­‰ λˆ„μ λ˜μ–΄ μ΅œμ’… 점수 μ‚°μΆœ

μ²˜μŒμ— μ΄λ ‡κ²Œ μƒκ°ν–ˆλ‹€. λ‘œκ·ΈμΈν•˜λŠ” μœ μ €κ°€ μ•„λ‹Œλ°, μ–΄λ–»κ²Œ κ΄€λ¦¬ν•˜μ§€?

- λ‹‰λ„€μž„ 쀑볡체크도 ν•˜κ³  μ‹Άκ³ .

- μœ μ €λ₯Ό λ“±λ‘ν•΄μ„œ, ν•΄λ‹Ή μœ μ €μ˜ 점수둜 λͺ¨λ“  λ¬Έν•­μ˜ μ μˆ˜κ°€ λˆ„μ λ˜λ„λ‘ κ΄€λ¦¬ν•˜κ³  μ‹Άκ³ .

 

μ•„μ£Ό μ˜›λ‚ μ˜›μ (?) ν˜Έλž‘μ΄ λ‹΄λ°°ν”Όμš°λ˜ μ‹œμ ˆ, μž₯κ³ κ°€ 자체적으둜 μ œκ³΅ν•˜λŠ” Userλͺ¨λΈκ³Ό μ†Œμ…œ λ‘œκ·ΈμΈμ„ κ΅¬ν˜„ν–ˆλ˜ κ²½ν—˜μ΄ 문득 μŠ€μ³κ°”λ‹€. λ‹‰λ„€μž„ μ€‘λ³΅μ²΄ν¬ν•˜κΈ°μ— 맀우 νŽΈλ¦¬ν•˜κ² λ‹€κ³  μƒκ°ν•˜μ—¬, μž₯κ³  auth의 Userλͺ¨λΈμ„ μ‚¬μš©ν•˜κΈ°λ‘œ ν–ˆλ‹€.

 

models.py

from django.db import models
from django.contrib.auth.models import User

class Person(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)
    comment = models.TextField('ν•˜κ³  싢은 말')
    score = models.IntegerField(default=0)
    # "1번점수-2번점수- ... -13번점수" ν˜•μ‹μœΌλ‘œ μ €μž₯

    def __str__(self):
        return self.name

 

μ–΄μ°¨ν”Ό λ‚΄κ°€ μœ μ € 데이터에 κ΅¬μ„±ν•˜κ³  싢은 것은 (이름 / λ§ˆμ§€λ§‰ λ¬Έν•­μ—μ„œ μž‘μ„±ν•˜λ„λ‘ ν•˜λŠ” 'ν•˜κ³ μ‹Άμ€ 말' / 제좜 λ‹΅μ•ˆ)λΏμ΄μ—ˆλ‹€. 

μ΄λ•Œ User λͺ¨λΈμ„ μ»€μŠ€ν…€ν•˜μ—¬ μ“°λŠ” 것이기 λ•Œλ¬Έμ— κ°€μž₯ νŽΈλ¦¬ν•΄λ³΄μ΄λŠ” OneToOneField 방식을 νƒν–ˆλ‹€. μ–΄μ°¨ν”Ό λ‹‰λ„€μž„ λΆ€λΆ„λ§Œ μ—°κ²°λ˜μ–΄λ„ λ˜λŠ” ꡬ쑰이기 λ•Œλ¬Έμ—. 

https://docs.djangoproject.com/en/5.0/topics/db/examples/one_to_one/

 

One-to-one relationships | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

νŽΈλ²•(μž”λ¨Έλ¦¬?)μœΌλ‘œλ„ λ³Ό 수 μžˆμ§€λ§Œ γ…‹γ…‹ μœ μ €κ°€ λ‹‰λ„€μž„μ„ μž…λ ₯ν•˜λ©΄, ν•΄λ‹Ή λ‹‰λ„€μž„μ— λŒ€ν•œ 쀑볡 체크λ₯Ό μ‹€ν–‰ν•˜κ³  μžλ™μœΌλ‘œ νšŒμ›κ°€μž… ν›„ λ‘œκ·ΈμΈλ˜λ„λ‘ μ²˜λ¦¬ν•˜μ˜€λ‹€. μ•„λž˜λŠ” viewsμ—μ„œμ˜ 처리 λ‚΄μš©μ΄λ‹€. 

 

(+) μ€‘λ³΅λ˜λŠ” λ‹‰λ„€μž„μ„ μž‘μ„±ν•  경우 λ…Έλž€μƒ‰μœΌλ‘œ κ²½κ³  λ©”μ‹œμ§€κ°€ μž…λ ₯μ°½ μ•„λž˜μ— μž‘κ²Œ ν‘œμ‹œλ˜λ„λ‘ ν•˜μ˜€λ‹€.

 

views.py

def login(request):
    found_user = User.objects.filter(username = request.POST.get('username'))

    if len(found_user) > 0 :
            error = '이미 μ‘΄μž¬ν•˜λŠ” λ‹‰λ„€μž„μž…λ‹ˆλ‹€.'
            return render(request, 'nickname.html', {'error':error})

    ## μœ μ € νšŒμ›κ°€μž… ν›„ 둜그인 처리
    if request.method == 'POST':
        new_user = User.objects.create_user(
            username = request.POST['username'],
        )
        auth.login(
            request,
            new_user,
            backend='django.contrib.auth.backends.ModelBackend'
        )
        print(new_user)
    
        Person.objects.create(
            user = new_user,
            name = request.POST['username']
        )
        return redirect("tutorial")

    return render(request, 'nickname.html')

 

 

μ΄λ ‡κ²Œ λŒμ•„κ°„λ‹€!

 

λ§ˆμ§€λ§‰μ— "ν•˜κ³  싢은 말"을 μž…λ ₯받을 λ•Œλ„, ν˜„μž¬ 문항을 ν’€κ³  μžˆλŠ” 둜그인된 μœ μ €μ™€ λŒ€μ‘ν•˜λŠ” Person을 μ°Ύμ•„ μΆ”κ°€ν•΄μ£Όμ—ˆλ‹€. μ•„λž˜λŠ” viewsμ—μ„œ κ΅¬ν˜„ν•œ 뢀뢄이닀.

def comment(request):
    if request.method == 'POST':
        #print(request.user, '########')
        ongoing_user = Person.objects.filter(name = request.user).update(
            comment = request.POST['comment']
        )
        return redirect("scoring")

    return render(request, 'comment.html')

 

 

그런데 개발 쀑에 λ‚˜λ₯Ό 괴둭힌 큰 1κ°€μ§€ λ―ΈμŠ€ν…Œλ¦¬κ°€ μžˆμ—ˆλŠ”λ° ,,,

μ΄κ²ƒλ•Œλ¬Έμ— μ†Œμš” μ‹œκ°„μ΄ 거의 2λ°°λŠ” λ˜μ—ˆλ˜ 것 κ°™λ‹€. λ°”λ‘œ 점수 λˆ„μ  λ°©μ‹μ΄μ—ˆλ‹€.

 

πŸ‘‰ λ‚΄κ°€ 처음 μƒκ°ν–ˆλ˜ 방식은 μ•„λž˜μ™€ κ°™λ‹€.

 

TextFieldλ₯Ό ν™œμš©ν–ˆλ‹€. "1λ²ˆμ—μ„œ 얻은 점수-2λ²ˆμ—μ„œ 얻은 점수-...-Nλ²ˆμ—μ„œ 얻은 점수" 이런 μ‹μœΌλ‘œ μ—…λ°μ΄νŠΈν•˜λŠ” λ°©μ‹μ΄μ—ˆλ‹€. 

ex) 3번 λ¬Έν•­κΉŒμ§€ λ‹΅λ³€ν–ˆμœΌλ©΄ "5-2-3" μ΄λ ‡κ²Œ μ €μž₯될 수 있고, 4번 λ¬Έν•­μ—μ„œ 1점을 μ–»μ—ˆλ‹€λ©΄ "5-2-3-1" μ΄λŸ°μ‹μœΌλ‘œ μΆ”κ°€λœλ‹€. μ΄λ ‡κ²Œ ν•΄μ„œ λ§ˆμ§€λ§‰ λ¬Έν•­κΉŒμ§€ λ‹΅λ³€ ν›„ -κΈ°μ€€μœΌλ‘œ splitν•˜μ—¬ 총점을 ν™˜μ‚°ν–ˆλ‹€.

 

λ™μž‘μ„  ν•˜κΈ΄ ν–ˆλ‹€. 그런데 맀우맀우맀우~ 느리게 선택지λ₯Ό κ³¨λΌμ•Όλ§Œ μ œλŒ€λ‘œ νšλ“ν•œ μ μˆ˜κ°€ λ‹΄κ²Όκ³ , 심지어 느리게 담아도 μ œλŒ€λ‘œ λ‹΄κΈ°μ§€ μ•Šμ„ λ•Œλ„ μžˆμ—ˆλ‹€. μ΄μœ λŠ” λͺ¨λ₯΄κ² μœΌλ‚˜ ,,, λ‚΄ 생각엔 λΆˆν•„μš”ν•˜κ²Œ μ‘°νšŒν•˜κ³  μ—…λ°μ΄νŠΈν•˜λŠ” κ³Όμ • λ•Œλ¬Έμ— μ§€μ—°μ‹œκ°„μ΄ λ°œμƒν•˜μ§€ μ•Šμ•˜λ‚˜ μ‹Άλ‹€.

(이 뢀뢄은 κΌ­ μ°Ύμ•„λ‚΄μ•Όκ² λ‹€. μž₯고의 object.filter μ†Œμš” μ‹œκ°„ λ“±. ν‚€μ›Œλ“œλŠ” λͺ¨λ₯΄κ² κΈ΄ ν•œλ°,,, )

 

πŸ‘‰ κ²°κ΅­ λ‘œμ»¬μŠ€ν† λ¦¬μ§€ λ°©μ‹μœΌλ‘œ λ°”κΎΈμ—ˆλ‹€. 

(1) 1번 λ¬Έν•­μ—μ„œ λ‘œκ·ΈμΈν•œ μœ μ €μ˜ λ‹‰λ„€μž„μ„ 기반으둜 둜컬 μŠ€ν† λ¦¬μ§€μ— λΉˆλ°°μ—΄μ„ λ“±λ‘ν•œλ‹€.

 window.localStorage.setItem("{{ user.username }}", []);

 

(2) λ§€ λ¬Έν•­λ§ˆλ‹€ μ΄μ „κΉŒμ§€μ˜ νšλ“ 점수 기둝이 λ‹΄κΈ΄ 배열을 getItem으둜 μ½μ–΄μ˜¨λ‹€. 

(3) ν˜„μž¬ λ¬Έν•­μ—μ„œ 얻은 νšλ“ 점수λ₯Ό μΆ”κ°€ν•œ 배열을 λ§Œλ“€μ–΄ λ‹€μ‹œ 둜컬 μŠ€ν† λ¦¬μ§€μ— λ“±λ‘ν•œλ‹€. 

const $choices = document.querySelectorAll(".four-btn");
    let prevScore = JSON.parse(window.localStorage.getItem("{{ user.username }}"));
    let score = 0;

    for (let $choice of $choices) {
      $choice.addEventListener("click", (e)=> {
       
        console.log(e.target.innerText);
        if(e.target.innerText === "μ •λ‹΅λ©˜νŠΈ") {
          // μ •λ‹΅ 처리 (점수 μΆ”κ°€)
          score += 4;
        }

        const newScore = [...prevScore, score];
        console.log(newScore);

        window.localStorage.setItem("{{ user.username }}", JSON.stringify(newScore));
   
      })
    }

 

(4) 점수 ν‘œμ‹œ 이전 νŽ˜μ΄μ§€μ—μ„œ 점수 기둝듀을 μ΄ν•©μ‚°ν•˜μ—¬ μ΅œμ’… 점수λ₯Ό μ‚°μΆœν•œλ‹€. 

 const finalScore = [...JSON.parse(window.localStorage.getItem("{{ user.username }}"))];
    let newScore = 0;
    finalScore.forEach((score) => {
        newScore += score;
    })
    
 fetch('/answer', {
        method: 'POST', 
        body: JSON.stringify({score: newScore})
        })
        .then(response => response.json())

    setTimeout(()=>{
        location.href = "http://localhost:8000/result"
    }, 6000)

 

 

(5) views.pyμ—μ„œ ν˜„μž¬ λ‘œκ·ΈμΈν•˜κ³  μžˆλŠ” μœ μ €μ™€ λŒ€μ‘ν•˜λŠ” Person의 μŠ€μ½”μ–΄λ‘œ μ΅œμ’… 점수λ₯Ό μ—…λ°μ΄νŠΈν•œλ‹€. ν•΄λ‹Ή μ μˆ˜λŠ” resultνŽ˜μ΄μ§€μ—μ„œ ν‘œμ‹œλœλ‹€.

 

views.py

@csrf_exempt
def answer(request):
    request_body = json.loads(request.body)
    
    

    print(request_body['score'],'******')
    ongoing_user = Person.objects.filter(name = request.user).update(
            score = request_body['score']
        )
    return HttpResponse({'signal': 'great'})

 

🚨 κ·€μš”λ―Έ μœ μ €λ“€μ˜ νŠΈλŸ¬λΈ”(에 λŒ€ν•œ 처리)

사싀 μ²˜μŒμ—λŠ” λ¬Έν•­λ§ˆλ‹€ 얻은 점수λ₯Ό κΈ°λ‘ν•˜μ§„ μ•Šμ•˜λ‹€. λ°”λ‘œλ°”λ‘œ λˆ„μ μ μˆ˜λ₯Ό λ‚¨κΈ°λŠ” ν˜•νƒœμ˜€λ‹€.

그런데 μšΈν•™κ΅ κ·€μš”λ―Έλ“€(μœ μ €λ“€)이 버그λ₯Ό μ°Ύμ•˜λ‹€λ©° λ²„νŠΌμ„ 마ꡬ λˆ„λ₯΄λŠ” νŽΈλ²•μ„ λ°œκ²¬ν–ˆλ‹€. 

 

λ‹€μŒ λ¬Έν•­μœΌλ‘œ λ„˜μ–΄κ°€κΈ° μ „, μ •λ‹΅ 선택지λ₯Ό μ—¬λŸ¬ 번 μ—°νƒ€ν•˜λ©΄, νŽ˜μ΄μ§€ μ „ν™˜ μ „κΉŒμ§€ μ—°νƒ€ν•œ 만큼 λͺ¨λ‘ μ μˆ˜μ— λ°˜μ˜λœλ‹€. (2000점을 λ‹¬μ„±ν•œ μΉœκ΅¬κ°€ 생겨났닀 γ…‹γ…‹γ…‹)

 

1λ“± 점수 νšλ“μžμ—κ²Œ μƒν’ˆμ„ κ±Έμ—ˆλ˜ μƒν™©μ΄μ—ˆκΈ°μ— 재빠λ₯Έ μˆ˜μ •μ΄ ν•„μš”ν–ˆλ‹€. λ‚΄κ°€ μ’‹μ•„ν•˜λŠ” 개발 λΈ”λ‘œκ·Έμ—μ„œ 이λ₯Ό μœ„ν•œ μ—¬λŸ¬ κ°€μ§€ μ˜΅μ…˜μ„ 찾을 수 μžˆμ—ˆλ‹€.

https://yceffort.kr/2020/10/prevent-double-click-on-button

 

(ν•¨μˆ˜ν˜•μœΌλ‘œ) μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ HTML λ²„νŠΌ 쀑볡 클릭 λ°©μ§€ν•˜κΈ°

λ²„νŠΌ 쀑볡 클릭을 λ°©μ§€ν•˜λŠ” 것은 μ€‘μš”ν•˜λ‹€. λ¬Όλ‘  기본적인 쀑볡 방지에 λŒ€ν•œ μ²˜λ¦¬λŠ” μ„œλ²„μ— λ˜μ–΄ μžˆμ–΄μ•Ό ν•˜μ§€λ§Œ, κ·Έλ ‡λ‹€κ³  마λƒ₯ ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ 손놓고 μžˆμ„ μˆ˜λŠ” μ—†λŠ” 일이닀. μ£Όλ‹ˆμ–΄ ν’€μŠ€νƒ

yceffort.kr

- κΈ€λ‘œλ²Œ ν”Œλž˜κ·Έ μ‚¬μš©ν•˜κΈ°

- ν•Έλ“€λŸ¬ 날렀버리기

- λ²„νŠΌ disable μ²˜λ¦¬ν•˜κΈ°

- μ§€μ—­λ³€μˆ˜ μ²˜λ¦¬ν•˜κΈ°

- κ³ μ°¨ν•¨μˆ˜ μ‚¬μš©ν•˜κΈ° (=μ•„λ§ˆλ„ μ΅œμ„ μ˜ 방법)

 

이쀑 ν•„μžκ°€ 적은 κ³ μ°¨ν•¨μˆ˜ μ™Έμ˜ 선택지듀은 ν•œκ³„μ μ΄ μžˆμ—ˆλ‹€. κ°€λ Ή, disableμ²˜λ¦¬ν•˜λ©΄ λ‚˜μ˜ λ‘œμ§μ—μ„œλŠ” 잘λͺ» λˆŒλ Έμ„ 경우 λ‹€μŒ λ¬Έν•­μœΌλ‘œ λ„˜μ–΄κ°€μ§€ λͺ»ν•˜κ²Œ 될 μˆ˜λ„ μžˆλ‹€ (μœ μ €κ°€ μ–΄λ–€ 문항에 νƒˆμΆœκ΅¬λ„ 없이 κ°‡νžˆλŠ” 격이닀 ,,) κΈ€λ‘œλ²Œ ν”Œλž˜κ·Έλ„ μ—¬μ „νžˆ 연타 λ¬Έμ œμ—μ„œ μžμœ λ‘­μ§€λŠ” μ•Šλ‹€. (μ•„λ§ˆλ„ μ΅œμ„ μ˜ 방법이라고 ν•œ κ³ μ°¨ν•¨μˆ˜λ„ λ§ˆμ°¬κ°€μ§€)

 

결둠은, μ™„λ²½νžˆ 막을 수 μžˆλŠ” λ°©λ²•μ΄λž€ μ—†μ—ˆλŠ”λ°... 사싀 κ°œλ°œμ΄λΌλŠ” 것은 이런 문제λ₯Ό ν’€ λ•Œ 더 μž¬λ°ŒλŠ” 것이 μ•„λ‹Œκ°€?  (γ…Ž . γ…Ž) πŸ’›

➑️ λ‚΄κ°€ μ„ νƒν•œ 방식은 μ–΄μ°¨ν”Ό 연타λ₯Ό λˆ„λ₯΄λŠ” 건 λͺ» λ§‰μœΌλ‹ˆ, 문항별 νšλ“ 점수 둜그λ₯Ό λ‚¨κΈ°λŠ” κ²ƒμ΄μ—ˆλ‹€. κ³ λ“μ μžλ“€μ˜ 둜그λ₯Ό ν™•μΈν•΄μ„œ 일뢀 μ‹€κ²©μ²˜λ¦¬ν•˜λ©΄ 되기 λ•Œλ¬Έμ—!

 

➑️ 생각해보면 점수 λ°˜μ˜μ„ νŽ˜μ΄μ§€μ—μ„œ ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, νŽ˜μ΄μ§€λ³„λ‘œ μ΅œμ’… μ œμΆœν•œ "선택지"에 λŒ€ν•œ 둜그λ₯Ό λ‚¨κ²¨μ„œ κ²°κ³Ό ν‘œμ‹œ 전에 μ΅œμ’… μ±„μ ν•˜λŠ” 둜직으둜 ν’€μ—ˆλ‹€λ©΄ λ°œμƒν•˜μ§€ μ•Šμ„ 문제인 것 κ°™λ‹€. (μš°λ¦¬κ°€ 일반적으둜 μ‹œν—˜μ„ 보고 μ±„μ ν•˜λŠ” κ³Όμ •μ²˜λŸΌ.) μ΄λ ‡κ²Œ 바꿔봐야겠닀. 


🍊 이후 처리 & 확인해야 ν•  것듀

- μ€‘λ³΅λ˜λŠ” λ‹‰λ„€μž„μ΄ μ‘°νšŒλ˜μ—ˆμ„ 경우, μ—λŸ¬ λ©”μ‹œμ§€ 뜨고 μƒˆλ‘œμš΄ λ‹‰λ„€μž„μœΌλ‘œλŠ” μ œλŒ€λ‘œ μž‘λ™ν•˜λŠ”κ°€?

- 배포 ν›„ ν™”λ©΄ μ „ν™˜ μ‹œ server error λΆˆκ·œμΉ™ν•˜κ²Œ λœ¨λŠ” 이슈 (이건 μ‹¬κ°ν•œ λ¬Έμ œμž„. 자꾸 μœ μ €κ°€ μ²˜μŒλΆ€ν„° ν•΄μ•Ό ν•˜λŠ” κ²½μš°κ°€ μžˆμœΌλ‹ˆκΉŒ)

- λΆ€λ“œλŸ¬μš΄ ν™”λ©΄ μ „ν™˜

 

μ œν•œλœ μ‹œκ°„ μ•ˆμ— ν•˜λŠλΌ 마ꡬ작이 μ½”λ“œλ₯Ό μ“°κΈ΄ ν–ˆμ§€λ§Œ, λ°°ν¬ν•΄μ„œ κ°„λ‹¨ν•œ 문제 해결에 λŒ€ν•œ 고민을 ν•  수 μžˆμ–΄ ν–‰λ³΅ν–ˆλ‹€. μ—¬λŸ¬ 방법을 κ³ λ €ν•˜λŠ” κ³Όμ • μžμ²΄κ°€ 재밌던 것 κ°™λ‹€. λ¬Όλ‘  이후 λ¦¬νŒ©ν„°λ§μ΄ 더 μ€‘μš”ν•˜κ² μ§€λ§Œ γ…Žγ…Ž...

 

ꡐ생 λλ‚˜κ³ λŠ” κΌ­ . ν•˜μ•„ 기말기간이긴 ν•˜κ² μ§€λ§Œ, 기말고사 λλ‚˜μ„œλΌλ„ κΌ­ wrap-upν•˜μž.

'ν”Œμ μΌμ§€' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Ncloud와 ν•¨κ»˜ν•œ HoneyFlow 개발기둝  (3) 2024.12.02

BELATED ARTICLES

more