Skip to content

UQuiz React

1. 🛤️ 라우팅 설정

주소컴포넌트컨텐츠
/Home닉네임 설정 페이지(메인)
/quiz/:nicknameQuiz퀴즈 풀이 페이지
results/:nicknameResults결과 페이지

1-1. URL 파라미터를 사용한 이유

  • 사용자별 개별화된 퀴즈 경험을 제공하기 위해
  • URL만 봐도 어떤 사용자의 퀴즈인지 직관적으로 알 수 있다.
  • 새로고침 시에도 파라미터로 복구되므로 초기화 이슈 최소화
  • 브라우저의 뒤로가기/앞으로 가기 기능 지원
  • URL 공유 가능 (친구에게 퀴즈 링크 공유 등)

1-2. App.jsx 코드

jsx
export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="quiz/:nickname" element={<Quiz />} />
        <Route path="results/:nickname" element={<Results />} />
      </Routes>
    </BrowserRouter>
  );
}
  • Home.jsx: 라우팅 진입점

2. 👥 닉네임 설정 페이지 구현

2-1. Home 컴포넌트

jsx
// 🧩 닉네임 설정 페이지 (메인 페이지)
import { useState } from "react";
import { useNavigate } from "react-router-dom";

function Home() {
  // useState로 닉네임 상태 관리
  const [nickname, setNickname] = useState("");
  const navigate = useNavigate();

  // 닉네임 검증 및 라우팅 로직
  const handleStart = (e) => {
    e.preventDefault(); // 폼 제출 시 새로고침 방지
    // 빈 값 또는 공백만 입력된 경우
    if (!nickname.trim()) {
      alert("닉네임을 입력해주세요.");
      return;
    }
    // 닉네임 입력 시, 닉네임을 URL 파라미터로 전달
    navigate(`/quiz/${encodeURIComponent(nickname)}`);
  };

  return (
    <section>
      {/* 페이지 제목 */}
      <h1>UQuiz</h1>

      {/* 닉네임 입력창 */}
      <form onSubmit={handleStart}>
        <label htmlFor="nickname-input" className="a11yhidden">
          닉네임
        </label>
        <input
          id="nickname-input"
          type="text"
          value={nickname}
          placeholder="닉네임을 입력하세요."
          onChange={(e) => setNickname(e.target.value)}
          required
        />
        {/* 시작버튼 */}
        <button type="submit">시작하기</button>
      </form>
    </section>
  );
}
export default Home;

2-2. 주요 구현 포인트

jsx
const navigate = useNavigate();

const handleStart = (e) => {
  e.preventDefault();
  if (!nickname.trim()) {
    alert("닉네임을 입력해주세요.");
    return;
  }
  navigate(`/quiz/${encodeURIComponent(nickname)}`);
};

useNavigate()

React Router에는 화면 이동을 위한 두 가지 방식이 있다.

  • Link 컴포넌트 적합한 경우

    • 정적인 이동에 적합하다.
    • JSX 안에서 바로 라우트로 연결할 때 직관적이다.
    • 클릭 즉시 이동하므로, 단순한 페이지 이동(검증 없음)에 적합하다.
    • 네비게이션 메뉴
  • useNavigate 훅 적합한 경우

    • 동적 로직과 함께 쓸 수 있다.
    • 조건부 라우팅(검증, 권한 체크 등)
    • 폼 제출 후 이동

따라서, 닉네임이 빈 값일 때 경고 메세지를 보여주고 이동을 막는 검증이 필요했기 때문에 useNavigate() 사용

e.preventDefault(); 사용

  • 페이지 새로고침 방지: 폼 제출 시 기본 동작 차단
  • SPA 동작 유지: React Router의 클라이언트 사이드 라우팅 보장
  • 사용자 경험 향상: 페이지 깜빡임 없이 부드러운 전환

nickname.trim() 검증

  • 앞뒤 공백을 빈 값으로 처리
  • 일관된 데이터 형태 유지 및 사용자 실수 방지
  • 이전 계산기 프로젝트에서 의도치 않게 공백이 입력되는 현상이 있어서, trim()으로 사전에 방지하도록 개선했던 경험이 있습니다.

encodeURIComponent() 사용

  • 특수 문자 처리: 한글, 특수 문자도 안전하게 URL에 포함
  • 보안성 향상: URL 인젝션 공격 방지
  • 브라우저 호환성: 모든 브라우저에서 정상적인 URL처리 보장

2-3. form 태그 접근성 고려

jsx
<form onSubmit={handleStart}>
  <label htmlFor="nickname-input" className="a11yhidden">
    닉네임
  </label>
  <input
    id="nickname-input"
    type="text"
    value={nickname}
    placeholder="닉네임을 입력하세요."
    onChange={(e) => setNickname(e.target.value)}
    required
  />
  <button type="submit">시작하기</button>
</form>

form 태그 및 onSubmit 이벤트

  • 접근성 향상: 스크린 리더가 폼의 목적을 명확히 인식
  • 자동 Enter 키 지원: 입력 후 Enter 키만 눌러도 제출 가능
  • 브라우저 기본 기능 활용: 폼 검증, 자동완성 등

label 처리

  • 스크린 리더가 입력 필드의 목적을 읽을 수 있음
  • WCAG 가이드라인 충족
  • a11yhidden 클래스로 시각적으로는 숨기되, 스크린 리더만 읽도록 처리

required 속성

  • 브라우저 기본 검증 속성으로 브라우저 레벨에서 1차 유효성 검사 제공