HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
CheQuiz 프로젝트
CheQuiz 프로젝트
/
[epic] 퀴즈생성

[epic] 퀴즈생성

Feat1. 퀴즈 생성1.1. Todo (Basic & Advance)1.2. 제어컴포넌트 VS 비제어컴포넌트 조사 후 선택1.3. 가장 작은 단위의 Form 만들기PR -ing []Feat2. 메인페이지 퀴즈 세트 리스트 출력Feat3. 메인 페이지 퀴즈 세트 필터링 & 정렬할
UI
notion image

Feat1. 퀴즈 생성

1.1. Todo (Basic & Advance)

todo
[ Basic ]
  • 문제 정보 관련
    • 문제 카테고리를 셀렉트 박스를 통해 선택할 수 있다.
      • html, css, javascript, react, vue, web, CS, interview
      문제 유형을 셀렉트 박스를 통해 선택할 수 있다.
      • TrueOrFalse만 가능, MultipleChoice, shortAnswer는 disable
      문제의 Title을 textArea를 통해 받을 수 있다.
  • 정답 관련
    • 문제 유형에 따라 정답을 선택하도록 한다.
      • O, X 체크박스로 선택
      중요도와 난이도를 선택할 수 있다.
      정답 관련 해설을 작성할 수 있다.
  • 퀴즈 추가
    • 추가 버튼을 통해 퀴즈 아이템을 추가한다.
       
  • 퀴즈 세트화 여부
    • 체크박스를 통해 퀴즈 세트 여부를 결정한다
      • 체크시 세트이름 Input의 상태가 editable 하도록 변경
       
  • 기타
    • 아래의 Validation을 만족 시 제출하도록 한다.
      • 1글자 이상의 문제 Title, 문제정답, 문제해설 존재
      • 문제 중요도와 난이도 선택
      • 카테고리 및 문제유형 선택
      • 세트화여부 체크시, 세트 이름 입력
[ Advance ]
문제 정보 관련
문제에 코드블럭을 추가할 수 있다.
문제에 이미지를 추가할 수 있다.
정답 유형관련
객관식으로 정답 유형을 선택할 수 있다.
단답식으로 정답 유형을 선택할 수 있다.
추가 기능
문제의 제한 시간을 지정할 수 있다.
 
 

1.2. 제어컴포넌트 VS 비제어컴포넌트 조사 후 선택

[ 개요 ]
  • HTML의 Form 요소는 그 자체로 내부의 상태를 가지기 때문에, 폼을 다룰 때 상태 관리의 주체가 어디인 것인가에 대한 설정이 필요
    • 제어컴포넌트(React State로 관리) VS 비제어컴포넌트 (Html Dom 요소에서 관리)
    •  
[ 제어컴포넌트의 동작 과정 ]
  • 사용자가 input 값 변경
  • input의 값이 변하면 onChange 핸들러가 발동하여, setState를 통해 state를 변경
  • input Element의 값으로 state를 할당하여, 화면에 변경 값 렌더링
특징
  • React state는 신뢰 가능한 단일 출처(single source of truth)를 지킴
[ 비제어컴포넌트의 동작과정 ]
  • 사용자가 input 값 변경
  • 변경된 값들은 해당 input Element의 값 혹은 innerHtml(textArea)로 가지게 됨
  • submit 시 각 DOM에 접근하여 로직을 처리
특징
  • ref를 통해 직접 DOM 값에 접근하여 사용하므로, vanilla JS와 유사한 방식
  • submit할 때 한 번에 form내의 value들을 접근하여 로직을 처리한다.
 
[ 두가지 방식의 선택 기준 ]
동기화여부
  • 제어컴포넌트는 사용자 입력에 따라 입력 값이 state로 반영되어 항상 최신의 상태를 유지하는 반면, 비제어컴포넌트는 제출과 같은 특정 상황에서 값을 불러와 최신정보를 반영한다.
  • 따라서 매 입력 시 마다 유효성검사와 같은 로직이 필요하다면 제어컴포넌트 사용이 바람직하고,
  • 사용자 입력 액션 마다 리렌더링 하는 것이, 불필요한 요청과 리렌더링으로 판단될 경우는 비제어 컴포넌트 사용이 바람직하다.
    • notion image
 
[ 결정 ]
  • 최종적으로 제어컴포넌트 사용
    • 비제어 컴포넌트 방식으로 UseRef를 통해 직접 DOM에 접근하여, 제출과 같은 필요한 순간에만 사용자 입력정보를 검토하고, API 요청을 하는 것으로 생각하였으나, 하나의 페이지안에서 여러 퀴즈를 제출할 수 있다보니, useRef로 관리해야하는 element들이 너무 많아질 수 있다는 치명적인 문제점을 인지
    • 제어컴포넌트 형식을 통해 TodoList와 같이 하나의 quizForm을 하나의 TodoItem으로 생각하는 것 처럼 작업하기로 결정
 
 
[ 보너스 ]
useRef가 리렌더링을 발생시키지 않는 이유 (참고)
  • 객체 이기 때문에, 최초 렌더링 이후, 항상 같은 값을 참조하기 때문이다.
useRef() 는 heap영역에 저장되는 일반적인 자바스크립트 객체이다. 매번 렌더링할 때 동일한 객체를 제공한다. heap에 저장되어 있기 때문에 어플리케이션이 종료되거나 가비지 컬렉팅될 때 까지, 참조할때마다 같은 메모리 값을 가진다고 할 수 있다. 값이 변경되어도 리렌더링이 되지 않는다. 같은 메모리 주소를 갖고있기 때문에 자바스크립트의 === 연산이 항상 true 를 반환한다. 즉 변경사항을 감지할 수 없어서 리렌더링을 하지 않는다는 뜻이다.
 
 
[ 이슈 ]
#1. 제어컴포넌트 방식으로 textarea 작성했는데, 한 글자 입력 시 마다, 페이지 리렌더링 되며 focus()를 잃는 현상
이슈 gif 확인
notion image
원인
  • 리렌더링의 원인은 컴포넌트 함수 내부에 styledComponent에 대한 선언이 있었기 때문
  • 컴포넌트 내부에 const QuizForm = styled.form`…` 이 매번 재생성되며, Input포커스를 잃게 됨
해결
  • styled component 부분을 컴포넌트 외부에 선언해줌으로 해결
ref
[ ref ]
  • 리액트에서의 Form
 

1.3. 가장 작은 단위의 Form 만들기

  • API 명세서 수정
    • Post.tag : String[] ⇒ String
      • 현재 tag는 배열형식인데, selctor박스로 되어 있어서, 1개만 선택하는 것인지, 여러개 선택가능하도록 할 것인지 정해야함
      • Set의 태그는 String[] 여러개이지만, 하나의 퀴즈는 하나의 카테고리만 가지는 것으로 결정
  • 의견: 세트화 여부를 퀴즈 제출하기 버튼 클릭 시, 모달에서 처리하는 방식 (kahoot방식)
[ 이슈 ]
 

PR -ing [
[Feat] 퀴즈 생성 basic 기능 구현
Github
[Feat] 퀴즈 생성 basic 기능 구현
Updated
Jun 16, 2022
]

디자인 및 컴포넌트화
validation
메인페이지 리스트 출력
메인페이지 필터링 & 정렬

Feat2. 메인페이지 퀴즈 세트 리스트 출력

Feat3. 메인 페이지 퀴즈 세트 필터링 & 정렬할

 
  • validation을 로그인에는 필요없다고 생각해서 넣지 않았는데 어떻게 생각하시나요?
  • 비밀번호 validation을 현재 중요한 포인트는 아니라고 생각해서 일단 최소 8자리 조건만 넣었습니다
  • 스토리지는 개발 편의 상 로컬스토리지를 사용했습니다
    • 스토리지에는 user객체와 token이 들어갑니다
  • 이 부분도 로그인, 회원가입 동작 확인 해주시면 감사하겠습니다
    • 홈 페이지에 상단에 폼 2개 넣어두어서 이걸로 확인할 수 있습니다
  • styled 컴포넌트를 분리했고 네임스페이스를 부여해서 함수 컴포넌트와 명시적으로도 분리될 수 있도록 했는데 어떻게 생각하시나요?
    • 매우 좋다고 생각