Skip to content

[Release] React · TypeScript 기반 유형 테스트 Web POC 완성 - #22

Merged
ksubin-dev merged 20 commits into
mainfrom
develop
Aug 11, 2026
Merged

[Release] React · TypeScript 기반 유형 테스트 Web POC 완성#22
ksubin-dev merged 20 commits into
mainfrom
develop

Conversation

@ksubin-dev

@ksubin-dev ksubin-dev commented Aug 11, 2026

Copy link
Copy Markdown
Owner

작업 내용

기존 Android 유형 테스트의 금융 테스트 1개를 기준으로
React + TypeScript Web POC 구현을 완료했습니다.

이번 PR은 개별 기능을 새로 추가하는 PR이 아니라,
Issue #2 ~ #11에서 완료한 작업을 develop에서 main으로 최종 반영하는 통합 PR입니다.

기존 Android 앱 전체를 React로 마이그레이션한 것이 아니라,
Compose에서 구현했던 금융 테스트 1개를 동일한 데이터와 결과 규칙을 기준으로
React의 Component, State, Props / Callback 구조로 다시 구현했습니다.


구현 범위

금융 테스트 1개
질문 6개
각 질문 선택지 3개
결과 3개

전체 화면 흐름:

StartScreen
    ↓
QuizScreen 1 / 6
    ↓
QuizScreen 2 / 6
    ↓
...
    ↓
QuizScreen 6 / 6
    ↓
ResultScreen
    ↓
다시 테스트하기
    ↓
StartScreen

완료한 작업

프로젝트 기반

  • React + TypeScript + Vite 프로젝트 구성
  • ESLint / Prettier 적용
  • 금융 테스트 데이터 및 TypeScript 타입 정의

UI

  • StartScreen 구현
  • 공통 QuizScreen 구현
  • ResultScreen 구현
  • 질문 번호 및 진행률 표시
  • 모바일 / 데스크톱 반응형 UI 적용

State 및 데이터 흐름

App.tsx에서 다음 State를 관리합니다.

screen
currentQuestionIndex
selectedAnswers

데이터와 이벤트 흐름:

financeTest
    ↓
   App
    ↓ Props
QuizScreen
    ↓ Callback
   App
    ↓
selectedAnswers
    ↓
calculateResult()
    ↓
ResultScreen

공유 State가 현재 POC 규모에서 App으로 관리 가능한 수준이므로
Redux / Zustand 등의 별도 전역 상태 관리 라이브러리는 사용하지 않았습니다.


데이터 / UI / 결과 계산 역할 분리

프로젝트에서는 역할을 다음과 같이 단순하게 구분했습니다.

data
→ 금융 테스트 데이터

types
→ TypeScript 데이터 구조

components
→ 화면 UI와 사용자 이벤트

App
→ 화면 전환과 State 흐름

resultCalculator
→ 결과 계산 규칙

특정 Architecture 패턴을 적용한 것이 아니라,
현재 POC 규모에서 필요한 책임만 분리했습니다.


결과 계산

기존 Kotlin 금융 테스트의 결과 계산 규칙을 유지했습니다.

1. 선택한 Answer의 scores를 Result ID별로 누적
2. 가장 높은 점수의 Result 선택
3. 동점이면 results 배열에서 먼저 정의된 Result 선택
4. 선택 답변 없음 / 유효 점수 없음 / 전체 점수 0이면 Result ID 3

결과 계산은 React Component와 분리한 Pure Function으로 구현했습니다.

selectedAnswers
      ↓
calculateResult()
      ↓
Result

또한 Result는 selectedAnswers에서 계산할 수 있는 값이므로
별도 React State로 중복 저장하지 않았습니다.


Derived Value

기존 State에서 계산할 수 있는 값은 별도 State로 만들지 않았습니다.

currentQuestion
totalQuestions
progressPercent
result

필요한 최소 State만 유지하고
화면 표시용 값은 기존 데이터에서 계산하도록 구성했습니다.


마지막 Answer 처리

마지막 질문에서도 현재 선택한 Answer가 결과에서 누락되지 않도록
기존 선택값과 현재 Answer를 합친 nextSelectedAnswers를 먼저 생성한 뒤 State를 갱신합니다.

const nextSelectedAnswers = [
  ...selectedAnswers,
  answer,
];

이후 Result 화면으로 전환하고,
Re-render된 시점의 최신 selectedAnswers를 기준으로 결과를 계산합니다.


Vitest

resultCalculator의 계산 규칙을 Vitest로 검증했습니다.

Test Files : 1 passed
Tests      : 8 passed

검증 범위:

Result ID 1 / 2 / 3 반환
score 누적
동점 처리
선택 Answer 없음
유효 score 없음
전체 score 0

React Component를 렌더링하지 않고
결과 계산 함수만 독립적으로 테스트했습니다.


반응형 UI

다음 범위에서 주요 화면을 확인했습니다.

Mobile
390px / 400px

Desktop
1280px / 1440px

적용 내용:

width: 100% + max-width
100vh fallback + 100dvh
480px Media Query
긴 질문 / 선택지 줄바꿈
모바일 padding 조정
가로 overflow 확인

Start → Quiz → Result → Restart 전체 흐름도 모바일 환경에서 확인했습니다.


GitHub Actions CI

Pull Request 단계에서 다음 검증을 자동 수행합니다.

Pull Request
      ↓
Checkout
      ↓
Node.js 24 + npm cache
      ↓
npm ci
      ↓
ESLint
      ↓
Vitest
      ↓
Production Build

대상:

작업 branch → develop
develop → main

push trigger는 사용하지 않습니다.

개별 작업 PR에서는 각 변경을 검증하고,
이번 develop → main PR에서는 모든 작업이 합쳐진 최종 상태를 다시 검증합니다.


Compose ↔ React 비교

두 기술이 완전히 동일하다는 의미가 아니라,
이번 POC에서 맡은 역할과 데이터 흐름을 기준으로 비교했습니다.

Android Compose React 이번 구현에서 비교한 역할
@Composable Component UI를 함수 / Component 단위로 구성
Parameter Props 부모에서 자식으로 데이터 전달
Lambda Callback Callback Props 자식 이벤트를 부모로 전달
Compose State useState 화면 단계 / 질문 index / 선택 답변 관리
Recomposition Re-render State 변경에 따른 선언형 UI 갱신 관점 비교
Kotlin data class TypeScript type 테스트 데이터 구조 정의
계산 함수 분리 Pure Function UI와 결과 계산 규칙 분리

Tech Stack

React
TypeScript
Vite
CSS
ESLint
Prettier
Vitest
GitHub Actions

사용하지 않은 기술을 POC 규모 이상으로 추가하지 않았습니다.


README

Vite 기본 README를 제거하고 프로젝트 전용 README를 작성했습니다.

README에서 다음 내용을 확인할 수 있습니다.

프로젝트 배경 및 구현 범위
주요 화면
Tech Stack
프로젝트 구조
State / Props / Callback 흐름
Derived Value
결과 계산 및 Vitest
GitHub Actions CI
Compose ↔ React 비교
실행 방법

하위 작업


이번 POC에서 제외한 범위

전체 유형 테스트 React 전환
금융 테스트 외 다른 유형 테스트
서버 / API
인증
React Router
Redux / Zustand
Next.js / SSR
React Testing Library
Component UI 테스트
E2E
Playwright / Cypress
Coverage
자동 배포
Android 이미지 리소스 이전

금융 테스트 1개를 기준으로
React 기본 Component / State / Props 흐름과
테스트 / CI까지 확인하는 범위에 집중했습니다.


로컬 검증

npm.cmd run lint
npm.cmd run test:run
npm.cmd run build
npx.cmd prettier --check .

결과:

ESLint   passed
Vitest   1 file / 8 tests passed
Build    passed
Prettier passed

최종 확인


Closes #1
Closes #2
Closes #3
Closes #4
Closes #5
Closes #6
Closes #7
Closes #8
Closes #9
Closes #10
Closes #11

ksubin-dev and others added 20 commits August 11, 2026 11:48
- React + TypeScript + Vite 프로젝트 생성
- ESLint 및 Prettier 동작 확인
- Vite 기본 예제 코드 정리
- 기본 실행 화면 확인
[Setup] React + TypeScript + Vite 프로젝트 초기 설정
- 금융 테스트용 TypeScript 타입 정의 추가
- Kotlin 원본 banking.json 기준 질문 6개 데이터 이전
- 금융 테스트 결과 3개 데이터 이전
- 답변 점수 구조를 scores 방식으로 유지
- UI 코드와 테스트 데이터 분리
[Feature] 금융 테스트 데이터 및 TypeScript 타입 정의
- StartScreen 컴포넌트 추가
- 시작 화면 전용 CSS 추가
- financeTest 데이터를 사용해 제목과 질문 수 표시
- 시작 버튼 클릭 시 onStart callback 호출
- App에서 StartScreen에 필요한 Props 전달
- UI 전환, 상태 관리, 결과 계산 로직은 추가하지 않음
[Feature] 금융 유형 테스트 시작 화면 구현
- QuizScreen 컴포넌트 추가
- 기존 Question, Answer 타입 재사용
- 현재 질문 번호와 전체 질문 수 표시
- 진행률 bar 표시
- 질문 문구와 답변 선택지 버튼 렌더링
- 답변 클릭 시 onAnswerSelect callback으로 Answer 전달
- StartScreen 렌더링 상태는 유지
- 화면 전환, 상태 관리, 결과 계산 로직은 추가하지 않음
[Feature] 공통 QuizScreen 및 질문 화면 구현
- App에서 useState로 화면 상태 관리 추가
- StartScreen 시작 버튼 클릭 시 QuizScreen으로 전환
- 현재 질문 index 상태 관리 추가
- 답변 선택 시 selectedAnswers에 Answer 저장
- 답변 선택 후 다음 질문으로 이동
- 마지막 질문 선택 시 complete 상태로 전환
- 완료 화면에서 저장된 답변 개수 표시
- 결과 계산과 ResultScreen 구현은 제외
[Feature] React State 기반 테스트 진행 상태 관리
- 선택된 Answer 목록 기반 결과 계산 함수 추가
- Result ID별 score 합산 로직 구현
- 동점 시 results 배열에서 먼저 정의된 Result 선택
- 유효 점수가 없을 때 기본 Result ID 3 반환
- ResultScreen 컴포넌트 및 스타일 추가
- complete 임시 화면을 result 화면 흐름으로 교체
- 마지막 Answer가 누락되지 않도록 선택 답변 배열 갱신 방식 수정
- 다시 테스트하기 버튼으로 StartScreen 복귀 처리
[Feature] 결과 계산 로직 분리 및 결과 화면 구현
- resultCalculator Vitest 테스트 추가
- Result ID 1, 2, 3 반환 규칙 검증
- 동일 Result score 누적 규칙 검증
- 최고 점수 동점 시 먼저 정의된 Result 반환 검증
- 선택 답변 없음, 유효 score 없음, 모든 score 0일 때 기본 Result 반환 검증
- 실제 financeTest 데이터 대신 최소 테스트 데이터 사용
[Test] 결과 계산 로직 Vitest 단위 테스트 작성
- StartScreen, QuizScreen, ResultScreen 카드 폭을 width/max-width 구조로 정리
- 모바일 viewport 대응을 위해 100dvh 적용
- 모바일 화면에서 카드 내부 여백 조정
- QuizScreen 질문과 선택지 긴 문구 줄바꿈 처리 추가
- ResultScreen 결과 문구 overflow 대응 추가
- 390px, 400px, 1280px, 1440px 화면 폭에서 레이아웃 확인
- 기존 화면 흐름과 결과 계산 로직은 변경하지 않음
[Style] 모바일 및 데스크톱 반응형 UI 적용
- GitHub Actions CI workflow 추가
- develop, main 대상 pull_request에서만 실행되도록 구성
- Node 24와 ubuntu-latest 환경 사용
- npm ci로 의존성 설치
- ESLint, Vitest, production build 순서로 검증
- npm cache 설정 추가
- 같은 PR의 이전 CI 실행을 취소하는 concurrency 설정 추가
- 최소 권한 contents: read 적용
- push trigger, matrix, coverage, Prettier CI 검증은 제외
[CI] GitHub Actions 기반 PR 품질 검증 자동화
- Vite 기본 README를 프로젝트 전용 README로 교체
- Android 금융 테스트를 React Web POC로 구현한 배경 정리
- 주요 화면 이미지와 구현 범위 추가
- 프로젝트 구조와 State / Props / Callback 흐름 설명
- 결과 계산 로직과 Vitest 테스트 내용 정리
- GitHub Actions CI 흐름 문서화
- Compose와 React의 역할 비교 표 추가
- 실행 방법과 구현하며 확인한 점 정리
[Docs] 프로젝트 README 및 Compose-React 비교 정리
@ksubin-dev ksubin-dev self-assigned this Aug 11, 2026
@ksubin-dev
ksubin-dev merged commit f665fde into main Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment