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

이미 아는 사실에 대봐

~12 min · validation, canary, testing, verification

Level 0원석
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"어떤 순위든 이미 아는 사실에 대봐."

검사 두 종류, 그리고 여기서 먹히는 건 하나뿐

유효성 검사는 데이터가 잘 생겼냐를 물어. 타입 맞나, 범위 맞나, 널 금지된 자리에 널 없나, 개수가 그럴듯한가. 내부적이야. 필요한 게 전부 응답 안에 있어.

검증은 데이터가 맞냐를 묻고, 필연적으로 외부적이야. 대볼 바깥 사실이 필요해.

거의 모든 코드베이스에 첫 번째는 많고 두 번째는 거의 없어. 유효성 검사는 싸고 범용이고 스키마에서 생성할 수 있는데, 검증은 도메인에 대해 뭔가를 알고 그걸 적어야 하거든. 그리고 그 절단 버그는 딱 검증만 볼 수 있는 결함이었어. 알파벳 순 1,083 종목은 완벽히 유효한 응답이고, 거기서 나온 명단은 어떤 스키마도 표현 못 하는 방식으로 틀렸으니까.

제일 싼 검증: 아는 구성원 하나

포괄적인 신탁이 필요한 게 아니야. 순위라면 아는 구성원 하나로 보통 충분하고, 그걸 고르는 기준은 안정성이야. 달마다 안 바뀔 이유로 집합에 반드시 들어 있어야 하는 것.

미국 최대 기업 목록이라면 초대형주 몇 개가 자격이 돼. 정확한 순위가 예측 가능해서가 아니라 존재가 그렇거든. 시총 기준 미국 상위 열 개 목록에 세계 최고 가치 기업 여럿이 빠져 있으면 그건 고장난 거고, 그 주에 시장에서 뭐가 일어났든 상관없이 고장난 거야.

아는 구성원 하나가 타입 검사 백 개를 이겨. 집합을 만드는 작업이면 반드시 들어 있어야 할 구성원 이름을 대고 단언해. 한 줄이면 되고, 조용한 절단 실패 일가를 통째로 잡고, 응답의 모든 부분이 유효한데 전체가 틀린 경우를 잡을 수 있는 유일한 검사야.

맞는 이유로 떨어지게 사실을 골라

기술은 헛발질 안 할 만큼 안정적이면서 진짜 결함은 잡을 만큼 구체적인 사실을 고르는 데 있어.

너무 구체적이면 — 정확한 순위나 정확한 시총을 단언하면 — 세상이 움직일 때마다 떨어지고, 그러면 다들 무시하도록 훈련돼. 사람들이 건너뛰기를 배운 단언은 없는 것보다 나빠. 진짜 단언이 들어갈 자리를 차지하고 있으니까.

너무 느슨하면 — 목록이 비어 있지 않다거나 열 개라고만 단언하면 — 잘린 데이터에서 신나게 통과하고, 그게 실제로 벌어진 일이야.

중간은 순서 없는 멤버십이야. 이 이름들은 결과 어딘가에 반드시 나와야 한다. 시장이 움직여도 안정적이고, 어떤 절단이나 필터 오류나 모집단 설정 실수에도 즉시 위반돼.

도메인 지식 비용이 바로 요점이야. 이런 검사는 자동 생성이 안 돼. 사람이 주제에 대해 아는 뭔가를 인코딩하니까. 약점이 아니야. 도메인 지식이 애초에 테스트 스위트로 들어가는 유일한 기제야. 어떤 스키마도 못 잡았을 버그를 고칠 때마다, 단언할 값어치가 있는 사실을 하나 배운 거고.

Code

유효성 검사, 검증, 그리고 그 사이 틈·python
# VALIDATION -- internal. All of this passed on the truncated data.
assert response.status_code == 200
assert isinstance(payload["results"], list)
assert all("ticker" in row for row in payload["results"])
assert 500 < len(symbols) < 20_000     # 1,083 sits happily inside


# VERIFICATION -- external. This is the one that fails.
#
# Membership, not ordering: these must APPEAR, at any rank.
# Stable across market moves; violated instantly by truncation,
# a broken filter, or a misconfigured universe.
ANCHORS = {"MSFT", "NVDA", "GOOGL"}  # illustrative megacaps, all
                                     # past C -- so this set fires
                                     # on the A-C truncation itself

missing = ANCHORS - set(symbols)
if missing:
    raise RuntimeError(
        f"universe is missing known megacaps: {sorted(missing)} "
        f"(got {len(symbols)} symbols, "
        f"first={symbols[0]}, last={symbols[-1]})")

# The error message names the two facts that diagnose it instantly:
# how many came back, and where the list stops alphabetically.

External links

Exercise

네 시스템이 만드는 데이터셋 하나를 골라서, 데이터 자체에서는 유도 안 되는 아는 사실을 하나 적어봐. 반드시 있어야 할 구성원, 어떤 범위 안이어야 할 총량, 반드시 성립해야 할 두 필드 사이 관계. 그걸 단언으로 바꿔. 그다음 왜 이미 없었는지 물어봐. 답은 거의 항상 그 사실을 적어둘 값어치가 있다고 느끼게 만든 일을 아직 안 당해서야.
Hint
좋은 기준점은 심심하고 유명해. 제일 큰 고객이 고객 목록에 있어야 하고, 주력 지역이 지역별 분해에 나와야 하고, 어제 아는 총계가 오늘 총계랑 몇 퍼센트 안이어야 하고. 심심한 게 요점이야. 그럴듯하게 바뀔 수 있는 기준점은 아무 이유 없이 새벽에 호출기를 울릴 기준점이거든.

Progress

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

댓글 0

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

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