본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

그 prop 이 없는 자리에서 검증해

~14 min · testing, sampling, layout, failure

Level 0흩어진 부품
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

선택적 슬롯 하나로 열하나 중 아홉

호스트가 임베드 프레임 위에 뭔가를 그릴 수 있게 공용 패널에 슬롯이 붙었어. 앱 둘이 필요로 했지. 만들어서 둘 다에 물렸고, 둘 다에서 제대로 보였어.

소비자 열하나 중 아홉의 프레임을 깨뜨렸어. 아무것도 안 넘기는 앱 전부.

기계는 그리드 디테일인데 결과가 커. 슬롯 노드가 내용이 주어질 때만 그려졌고, 그리드에선 노드가 없어도 그 행이 안 접혀. 행은 남고, 아래 전부가 그 안으로 밀려 올라가. 프레임이 가운데 자동 크기 행에 내려앉았고, 자동 행의 임베드 프레임은 자기 고유 높이로 떨어져. 측정된 패널 하나에선 그게 전체 높이 프레임을 작은 토막으로 만들고 그 아래 큰 빈 구역을 두고 임베드 작성기를 보이는 영역 밑으로 밀어냈어.

표본 오류, 그게 진짜 교훈

검증은 소비자 둘에서 이뤄졌고 꼼꼼했어. 문제는 어느 둘이냐야. 정확히 그 슬롯을 넘기는 둘. 표본 전체가 그 기능의 사용자였던 거지.

다수는 한 번도 안 열렸어. 아무것도 안 넘기고 따라서 새 코드 경로를 기본 상태로 밟는 소비자 전부. 그리고 그 상태는 예외 경우가 아냐. 그 변경이 거의 모두한테 하는 짓이야.

공용 표면이 선택적 prop 을 기르면, 그걸 안 넘기는 소비자에서 검증해. 선택적 기능의 저자는 그 사용자들을 열어놓고 있어. 일이 벌어진 자리고 확인하기 쉬운 자리니까. 그 소비자들이 볼 정보가 제일 적은 쪽이야. 기본 경우가 다수 경우고, 그게 아무도 안 열어놓은 쪽이니까 우연이 아니라 일부러 검증해야 해.

두 번 고쳐서 다시 못 나게

변경이 하나가 아니라 둘이고, 두 번째가 재밌는 쪽이야. 첫째, 슬롯 노드는 이제 언제나 DOM 에 있고 안 쓸 땐 그냥 비어 있어. 빈 상태는 자기 테두리를 떨구고. 그래서 있음과 없음이 같은 구조를 내. 둘째, 프레임이랑 그 대체 표면이 명시적인 그리드 행에 고정돼서, 앞으로 그 위에 추가되는 어떤 슬롯도 그것들을 아예 못 움직여.

첫 번째 처방은 이 버그를 고쳐. 두 번째는 부류 전체를 없애. 다음에 슬롯을 붙이는 사람이 이걸 다시 만들 수가 없어. 프레임 위치가 앞에 노드가 몇 개냐에 더는 안 달렸으니까. 그게 사고를 고치는 것과 그 사고를 만든 모양을 고치는 것의 차이고, 십 분을 더 쓸 값이 있는 건 다음 사람이 이 이야기를 안 읽었을 거라서야.

Code

조건부 노드, 그게 부른 붕괴, 그리고 처방 둘·typescript
// BEFORE - the slot node exists only when content is supplied.
// Looks correct in the two apps that pass it. In the nine that do
// not, the grid row remains and everything below shifts UP into it.
<div className="panel">
  <Header />
  {beforeFrame && <div className="slot">{beforeFrame}</div>}
  <iframe className="frame" src={embedUrl} />
</div>

/*  .panel { display: grid; grid-template-rows: auto auto 1fr; }

    with the slot:      38px  |  90px   |  520px   frame fills 1fr
    without the slot:   38px  |  150px  |  460px
                                  ^^^^^
    the FRAME is now in the middle AUTO row, where an iframe falls
    back to its intrinsic 150px - a stub, with 460px of nothing
    under it and the embedded composer below the fold.            */


// FIX 1 - the node is ALWAYS in the DOM; absence and presence
// produce the same structure. :empty drops the border so an unused
// slot is invisible rather than a stray line.
<div className="panel">
  <Header />
  <div className="slot">{beforeFrame}</div>
  <iframe className="frame" src={embedUrl} />
</div>

/*  .slot:empty { border: 0; padding: 0; }                        */


// FIX 2 - the one that removes the CLASS. The frame is pinned to an
// explicit row, so no future slot added above it can move it at all.
// The next person adding a slot cannot reintroduce this bug, which
// matters because they will not have read this story.

/*  .frame,
    .unavailable { grid-row: 3; }                                 */


// THE TEST THAT WOULD HAVE CAUGHT IT - note the second case is the
// one nobody writes, because it is the case with nothing in it.
test("frame keeps its height WITHOUT the optional slot", () => {
  const { frame } = renderPanel({ beforeFrame: undefined });
  expect(frame.clientHeight).toBeGreaterThan(400);
});

External links

Exercise

네가 관리하는 공용 컴포넌트에 제일 최근 붙은 선택적 prop 이나 설정 플래그를 찾아. 그걸 넘기는 소비자랑 안 넘기는 소비자를 나열해. 그다음 두 번째 목록에서 하나를 열어서 동작을 확인해. 그 경우를 아무도 본 적 없으면, 이번에 버그가 났든 안 났든 같은 표본 오류를 찾은 거야.
Hint
그 기능을 넣은 PR 을 확인하고 거기 어느 소비자가 나오는지 읽어. 언급된 소비자가 전부 새 prop 을 넘기는 쪽이면 기본 경우는 한 번도 관찰 안 된 거고, 기본 경우가 네 사용자 대부분이 돌리는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.