대니
danny's blog@dannywon_dev
발행 55 · 대기 75

1인 개발자. 클로드 코드를 팀처럼 굴린다. 매일 겪은 것만 쓴다.

제품 만들기

React 조건부 렌더링 카드가 다시 뜨는 이유

고르기·건너뛰기 버튼만 달았더니, 카드를 무시하고 그냥 질문한 사람에게 카드가 매번 다시 나타났다

화면에 카드를 하나 띄우고 「나중에 할게요」 버튼을 달았다고 하자. 그 사람이 버튼을 누르지 않고 그냥 하던 일을 계속하면, 코드에서는 무슨 일이 일어나나. 대개 아무 일도 안 일어난다.

2026-08-09, 전시 관람 서비스의 AI 도슨트에 「연령대 눈높이」를 붙였다. QR을 찍고 들어오면 채팅방 위에 카드가 뜬다.

먼저 나이대를 알려주시겠어요? 초등학생 중·고등학생 20~40대 50대 이상 그냥 바로 물어볼게요

고르면 그 뒤 답변의 어휘와 문장 길이가 맞춰진다. 안 고르고 싶으면 「그냥 바로 물어볼게요」를 누르면 된다. 카드는 한 번만 뜨고 사라진다 — 그렇게 설계했고 컴포넌트 주석에도 그렇게 적었다.

{!ageAsked && <AgeBandPrompt
   onPick={(band) => { setAgeBand(band); setAgeAsked(true); }}
   onSkip={() => setAgeAsked(true)} />}

고르면 끝. 건너뛰면 끝. 깔끔해 보였다.

리뷰에서 걸린 지점

관람객이 카드를 무시하고 그냥 질문을 입력하면 ageAsked를 아무도 안 바꾼다. 답변이 오고 로딩이 끝나는 순간 카드가 답변 바로 밑에 다시 나타난다. 화면은 자동으로 맨 아래로 스크롤되니까 관람객 눈에 정확히 걸린다. 세 번 물으면 세 번 본다.

내가 센 건 버튼 두 개였다. 고르기, 건너뛰기.

그런데 사용자가 이 질문에 답하는 방법은 셋이었다.

  1. 고른다
  2. 건너뛰기를 누른다
  3. 무시하고 자기 할 일을 한다

3번이 제일 흔한 행동인데, 그건 내 화면에 버튼이 없다. 그래서 안 세어졌다.

상태를 무엇으로 바꾸는가

여기서 갈리는 건 이 질문이다.

  • UI 이벤트로 바꾸면 — 내가 만든 버튼만큼만 경로가 생긴다
  • 의미가 끝나는 시점으로 바꾸면 — 버튼이 없는 경로도 잡힌다

「연령대를 물었나?」라는 상태가 진짜로 끝나는 시점은 버튼을 누를 때가 아니다. 대화가 시작될 때다. 첫 질문이 날아간 순간, 물어볼 타이밍은 이미 지났다.

그래서 플래그를 켜는 자리를 버튼에서 메시지 전송 함수로 옮겼다.

const submitMessage = async (raw, clicked) => {
  const text = raw.trim();
  if (!text || thinking) return;

  // 질문을 보내는 순간 묻는 시점은 지났다 —
  // 카드를 무시하고 그냥 물어본 것도 대답이다.
  setAgeAsked(true);
  ...

한 줄이다. 그런데 이 한 줄이 세 번째 경로를 통째로 덮는다. 버튼을 하나 더 만드는 게 아니라, 상태의 정의를 「눌렀나」에서 「그 시점이 지났나」로 바꾼 것이다.

겉모습이 같은데 규칙이 다른 카드

같은 화면에 비슷한 게 하나 더 있었다. 가입 권유 카드는 「나중에 할게요」를 눌러야 사라진다. 그건 그대로 뒀다. 그 카드는 무시하고 대화를 이어가도 계속 있어야 맞기 때문이다.

둘 다 채팅방 위에 뜨는 카드고 둘 다 「나중에」 버튼이 있는데, 하나는 「물어보는 것」이고 하나는 「권하는 것」이라서 규칙이 달랐다.

화면에 「나중에」 버튼을 달 때 한 번 볼 만하다. 아무것도 안 누르고 그냥 하던 일을 하는 경로가 코드에 있는가. 그게 맞는 화면도 있고, 아닌 화면도 있다.

← 목록으로