Fullstack 88

heo4·2026년 8월 20일

Fullstack

목록 보기
43/70

풀스택

EasyPrompt 개발일지

wizard 완성도 보완 + 자동화 테스트 구축

오늘은 "질문 설계 위저드"(/wizard)를 실사용 가능한 수준으로 다듬고, 그 결과를 사람이 일일이 클릭해보지 않아도 되도록 자동화 테스트로 전부 검증했다.


1. 위저드 완성도 보완 6종

기존 위저드는 문구 조립·화면 흐름은 되는데, 로그인 연동·이탈 방지·입력 검증 같은 "완성형 제품"에 필요한 디테일이 빠져 있었다. 오늘 그 6가지를 순서대로 채웠다.

로그인 사용자 저장 기능

  • histories 테이블에 source(curated | wizard) 컬럼과 wizard_category 컬럼을 추가했다. 위저드 결과는 prompts 테이블에 대응하는 행이 없어서 prompt_id도 NULL을 허용하도록 스키마를 바꿨다.
  • SQLite는 ALTER TABLE로 NOT NULL 제약을 못 풀어서, 마이그레이션은 "새 테이블 만들고 → 데이터 옮기고 → 기존 테이블 지우고 → 이름 바꾸기" 방식으로 작성했다.
  • 완성 화면에 "이 질문 저장하기" / "로그인하고 저장하기" 버튼을 추가했다. 비로그인 상태면 답변을 sessionStorage에 잠깐 담아두고 로그인 페이지로 보낸 뒤, 로그인에 성공하면 다시 위저드로 돌아와 자동으로 저장을 이어가도록 만들었다.
  • 마이페이지에 "내가 만든 질문" 섹션을 새로 만들어 위저드로 만든 결과만 따로 보여준다.

진행 상태 보존 (이탈 방지)

  • 새로고침/탭 닫기(beforeunload), 브라우저 뒤로가기(popstate), 헤더·푸터 링크 클릭까지 3중으로 가로채서 "작성 중인 내용이 사라집니다. 나가시겠어요?" 확인창을 띄운다.
  • 뒤로가기는 더미 히스토리 엔트리를 하나 쌓아두는 트릭으로 구현했다.

입력 검증

  • getQuestionError(question, answers) 함수 하나로 필수 입력/공백-only/최소 글자 수/최대 글자 수를 전부 판정하도록 정리했다.
  • "정리하기" 카테고리의 원본 붙여넣기 항목은 2000자를 넘겨도 입력 자체는 자르지 않고, 글자 수 카운터와 경고 문구만 보여주는 방식을 선택했다.
  • "다음" 버튼을 비활성화하는 대신, 클릭했을 때 검증해서 실패하면 그 자리에서 인라인 에러를 보여주는 방식으로 바꿨다. (버튼만 비활성화하면 "왜 안 넘어가지?"를 사용자가 알 수 없어서)

문구 자연스러움

  • 글쓰기 카테고리에서 "누구에게 보여줄지"를 "잘 모르겠어요"로 고르면, 예전엔 "~에게" 절 전체가 사라져서 "글을 정중하게 써주세요"처럼 어색했다. → "보여줄 글을 정중하게 써주세요"로, "보여줄"은 남기게 수정.
  • 결정하기 카테고리는 선택지 개수·판단 기준이 "모르겠음"일 때 아예 다른 문장 구조로 조립되도록(예: "아직 선택지를 정하지 못했습니다. 상황에 맞는 선택지부터 제안해주세요") buildPrompt를 다시 짰다.

카테고리 매핑

  • 위저드 완성 화면 하단에 "이런 프롬프트들도 있어요" CTA를 만들고, 5개 대분류마다 어울리는 기존 프롬프트 카테고리로 연결했다(일반사용자용/AI 코딩 입문은 전용 페이지로, 나머지는 /prompts?category=이름 쿼리스트링으로).

placeholder 보강

  • "정리하기" 원본 붙여넣기 placeholder를 막연한 안내에서 "예: 오늘 회의에서 나온 카톡 대화 내용을 그대로 붙여넣어 보세요"처럼 구체적인 예시로 바꿨다.

2. README 정리

홈 화면이 "찾기 / 만들기" 2-카드 구조로 크게 바뀌었는데, 루트/frontend README가 예전 "4개 카테고리" 구조 설명으로 남아있어서 최신 구조에 맞게 갱신했다.


3. 자동화 테스트 스위트 구축 (Vitest + Playwright)

여기가 오늘의 메인 작업. 아래 체크리스트 7개 항목을 사람이 직접 클릭해서 확인하지 않고 전부 코드로 검증했다.

  1. 플로우 정상 동작 (질문 개수/뒤로가기 값 유지/단계 인디케이터)
  2. 입력 검증 (필수값/공백/2000자 초과)
  3. 문구 조립 엣지 케이스 ("모르겠어요류" 선택지 조합)
  4. 저장/로그인 연동 (비로그인 리다이렉트, DB 저장, 마이페이지 반영)
  5. 카테고리 매핑 (CTA 링크 href)
  6. 이탈 방지 (뒤로가기/새로고침 confirm)
  7. 반응형/접근성 (모바일 375px에서 버튼 높이·2-카드 배치)

단위 테스트 (Vitest, 50개)

buildPrompt/getQuestionError처럼 AI 호출 없이 순수 함수로 동작하는 로직을 직접 실행해서 검증했다.

  • 글쓰기 "잘 모르겠어요", 결정하기 "선택지 모름 단독 / 기준 모름 단독 / 둘 다 모름" 3가지 조합의 완성 문구를 문자열로 정확히 비교.
  • 정리하기 원본 텍스트 2000자(경계값)와 2001자(초과)를 각각 넣어서 통과/경고 여부 확인.
  • 5개 대분류의 모든 필수 질문을 순회하면서 "비워두면 막히는지", "공백만 넣으면 막히는지"를 전수 검사.

e2e 테스트 (Playwright, 31개)

wrangler dev(백엔드)와 vite dev(프론트)를 Playwright의 webServer 옵션으로 동시에 띄운 뒤, 실제 크로미움 브라우저로 클릭·입력·화면 전환을 검증했다. 특히:

  • DB 검증: wrangler d1 execute --local을 자식 프로세스로 호출하는 헬퍼를 만들어서, 위저드로 저장한 결과가 로컬 D1의 histories 테이블에 source='wizard'로 실제로 들어갔는지 SELECT로 직접 확인했다. GET /histories API 응답과 마이페이지 화면 노출도 함께 확인.
  • 이탈 방지: Playwright의 dialog 이벤트로 confirm 창이 실제로 뜨는지, 취소를 누르면 입력값이 그대로인지까지 확인했다. beforeunload 다이얼로그도(환경에 따라 안 뜰 수도 있어서 방어 로직을 넣긴 했지만) 이번 환경에서는 정상적으로 잡혔다.
  • 반응형: 375px 뷰포트에서 버튼/입력창의 실제 렌더링 높이가 56px 이상인지 boundingBox()로, 홈 화면 2-카드가 가로가 아니라 세로로 쌓이는지 좌표 비교로 확인했다.

삽질 포인트

  • 이 개발 환경(sudo 없는 샌드박스)에서는 playwright install-deps가 막혀서, apt-get download(root 불필요)로 libnspr4/libnss3/libasound2t64 세 패키지만 받아 압축을 풀고 LD_LIBRARY_PATH로 지정해 헤드리스 크로미움을 띄웠다. 재현용 스크립트로 만들어서 프로젝트에 같이 커밋해뒀다.
  • 처음 테스트를 돌렸을 때 2개가 실패했는데, 둘 다 위저드 코드 버그가 아니라 테스트 스크립트 실수였다(단계를 하나 건너뛰고 버튼을 클릭하려 했던 것, 선택 입력값을 override 안 해서 기대값이 어긋난 것). 둘 다 고치고 나니 81개 전부 통과.

결과

  • 단위 테스트 50개 + e2e 테스트 31개 = 총 81개 전부 통과
  • 테스트 코드는 frontend/tests/unit, frontend/tests/e2e에 정식으로 남겨둬서 npm run test:unit, npm run test:e2e로 언제든 재실행 가능
  • 위저드 결과 문구 확인용으로 data-testid 하나만 추가했고, 실제 동작은 건드리지 않았다

커밋

  • 8481a01 /wizard 위저드 자동화 테스트 스위트 추가 (Vitest 단위 50개 + Playwright e2e 31개)

0개의 댓글