Skip to content

v1.0.2 — 질문 투표 기능 + 공지 배너

Choose a tag to compare

@Lunas322 Lunas322 released this 18 Aug 04:44
· 37 commits to main since this release
c6c8a8c

질문에 투표를 붙여 토론이 성립하도록 하고, 그것을 알릴 공지 배너를 함께 추가했다.

질문 투표

질문 작성                 질문 상세                   답변 목록
┌─────────────┐        ┌────────────────┐        ┌──────────────────┐
│☑ 투표 붙이기 │        │ 당신의 선택은?  │        │[안 봐준다] 민지   │
│ ● 봐준다     │   →    │ 봐준다     23% │   →    │ 한 번 하면 또…    │
│ ● 안 봐준다  │        │ ▓▓▓░░░░░░░░░░░ │        │                  │
│ + 선택지 추가│        │ 안 봐준다  77% │        │[봐준다] 유키      │
└─────────────┘        │    52명 참여    │        │ 사정을 들어보는…   │
                       └────────────────┘        └──────────────────┘
  • 질문 작성 시 선택지를 2~4개까지 직접 입력한다. 선택 사항이며, 붙이지 않은 질문은 이전과 동일하게 동작한다
  • 투표는 로그인이 필요하다. 비로그인 사용자에게는 좋아요와 같은 방식으로 로그인을 유도한다
  • 결과는 투표해야 보인다. 투표 전에는 선택지와 참여 인원만 노출된다
  • 선택은 바꿀 수 있다. 다만 이미 작성한 답변의 뱃지는 작성 시점으로 고정되어, 그때의 입장이 보존된다
  • 선택지도 자동 번역된다. 제목·본문과 같은 요청에 실려 나가므로 DeepL 호출 횟수는 늘지 않는다

데이터 모델

poll.optionIds : ["o1", "o2"]        순서 보존용 배열
poll.labels    : { o1: { ko, ja } }  번역 결과
poll.counts    : { o1: 12 }          FieldValue.increment 대상

questions/{id}/votes/{userId} = { optionId, createdAt }

counts 를 배열이 아니라 맵으로 둔 이유는 FieldValue.increment 가 필드 경로를 대상으로 하기 때문이다. 배열이면 원소만 증가시킬 수 없어 통째로 덮어써야 하고, 동시에 두 명이 투표하면 한 명의 표가 유실된다.

votes 는 기존 likes 서브컬렉션과 동일한 구조이며, toggleLike 의 트랜잭션 패턴을 따랐다.

번역 파이프라인 변경

기존에는 최상위 필드만 번역할 수 있었다. 선택지는 poll.labels.o1 같은 중첩 경로에 있고 개수도 질문마다 다르다.

  • 번역 대상 목록을 상수 배열이 아니라 문서를 받아 계산하는 함수로 변경
  • 점 표기 경로를 읽는 readPath 를 추가. 쓰기(ref.update)는 점 경로를 원래 지원하므로 변경 없음

호환성

poll 필드가 없는 기존 질문은 투표 UI가 렌더되지 않는다. 마이그레이션이 필요 없다.

공지 배너

랜딩과 홈 상단에 공지 배너를 띄운다. 문구는 Firestore config/notice 문서 하나를 Firebase 콘솔에서 직접 수정해 배포 없이 갱신한다.

항목 선택 이유
캐싱 태그가 아니라 revalidate: 60 콘솔에서 사람이 고치는 데이터라 코드에서 updateTag 를 부를 수 없다. 공지에 1분 지연은 문제되지 않는다
닫기 상태 localStorage가 아니라 쿠키 서버가 읽어야 닫은 사용자에게 배너를 아예 렌더하지 않는다. localStorage면 한 번 그려졌다 사라져 깜빡인다
쿠키 값 true 가 아니라 공지 id id가 바뀌면 새 공지로 인식돼 다시 노출된다
렌더링 Suspense 로 격리 쿠키를 읽으면 페이지가 동적이 된다. 배너만 감싸 랜딩의 정적 프리렌더(◐)를 유지했다

운용

  • 문구만 수정 → message 만 변경 (이미 닫은 사용자에게는 계속 노출되지 않음)
  • 새 공지 → id 를 변경 (닫았던 사용자에게도 다시 노출됨)
  • 내리기 → active = false

배포 후 필요한 작업

Firebase 콘솔 → Firestore 에 아래 문서를 만들어야 배너가 노출된다. 투표 기능은 이 작업과 무관하게 즉시 동작한다.

  • 컬렉션 config / 문서 ID notice
  • id (string), active (boolean), message (map: ko, ja)

Full Changelog: v1.0.1...v1.0.2