본문 바로가기

동치 분할과 경계값

유효·무효 입력 공간과 경계를 구분하고 정원·ID·조건 조합에서 대표 사례를 선택합니다.

정원 1부터 100까지 매번 전부 테스트하면 상한이 1,000,000인 다음 요구에는 같은 방법을 쓰기 어렵습니다. 입력을 규칙에 따라 나누고 경계에서 실수하기 쉬운 사례를 선택합니다.

동치 분할은 같은 규칙으로 처리될 것으로 예상되는 입력을 집합으로 나누는 방법입니다. 집합 하나의 대표가 모든 결함을 찾는다는 보장은 없습니다. 경계값 분석은 유효·무효 영역이 만나는 끝과 바로 바깥의 값을 확인합니다.

정원 입력의 영역

이 교재의 정원은 정수 1~100입니다. 유효 정수, 1 미만 정수, 100 초과 정수, 정수가 아닌 숫자, 숫자가 아닌 값을 별도로 봅니다.

영역·경계사례기대
하한 바로 아래·하한0, 1거절, 허용
상한·상한 바로 위100, 101허용, 거절
정수 제약 위반1.5거절
타입 제약 위반"2", null거절

정원 입력의 경계와 참가자 수의 경계는 다릅니다. 정원 2에서 참가자가 1명일 때 새 신청을 허용하고 2명일 때 거절하는 사례도 필요합니다. 정원 입력 0을 거절하는 테스트가 만석 신청 규칙까지 검증하지는 않습니다.

정원 입력의 범위와 신청 상태의 경계를 구분한다

모집은 열려 있고 참가자는 min뿐이다. jun은 새 ID지만 정원이 찼다. 각 단계의 값과 전환 이유를 비교합니다.

SOFTWARE ENGINEERING · READING CLUB

정원 입력의 범위와 신청 상태의 경계를 구분한다

생성 입력을 검증하는 숫자 영역과 실행 중 참가자 수가 바뀌는 상태 전이는 서로 다른 경계입니다.

정원 입력의 범위와 신청 상태의 경계를 구분한다상단은 정원 입력 0 거절, 1부터100까지 허용,101 거절의 숫자 범위입니다. 하단은 정원2의 열린 모임에서 참가자1명에 hana를 등록해2명이 된 뒤 새jun 신청을 FULL로 거절하는 흐름입니다. 기존min 신청은 중복으로 거절합니다.① 모임 생성 입력: 정원은 정수 1~1000거절1허용100허용101거절… 유효한 정수 영역 …② 신청 시 상태: 정원 2인 열린 모임참가자 1명min새 ID hana 신청등록참가자 2명min, hana새 ID jun 신청거절FULLmin, hana 유지기존 ID min이면 중복
정원 입력의 범위와 신청 상태의 경계를 구분한다상단은 정원 입력 0 거절, 1부터100까지 허용,101 거절의 숫자 범위입니다. 하단은 정원2의 열린 모임에서 참가자1명에 hana를 등록해2명이 된 뒤 새jun 신청을 FULL로 거절하는 흐름입니다. 기존min 신청은 중복으로 거절합니다.① 정원 입력: 정수 1~1000거절1허용100허용101거절유효한 정수 영역② 참가자 수: 정원 2 · OPEN참가자 1명min새 ID hana 신청등록참가자 2명min, hana새 ID jun 신청거절FULLmin, hana 유지기존 ID min이면 중복

상단의 1~100은 정원 입력 정책입니다. 하단의 1→2는 신청 상태 변화입니다. 같은 만석 상태라도 기존 ID의 중복 거절은 우선순위를 확인하는 별도 사례입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 한 자리 남음부터 새 신청 거절까지 진행합니다.
관계도의 보충 설명
전체 도표의 표기·관계·조건
구분전체 도표의 내용
관계 설명상단은 정원 입력 0 거절, 1부터 100까지 허용, 101 거절의 숫자 범위입니다. 하단은 정원 2의 열린 모임에서 참가자 1명에 hana를 등록해 2명이 된 뒤 새 jun 신청을 FULL로 거절하는 흐름입니다. 기존 min 신청은 중복으로 거절합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
한 자리 남음

모집은 열려 있고 참가자는 min뿐이다.

  • 정원·신청자 1: capacity2
  • 정원·신청자 2: OPEN
  • 정원·신청자 3: participants [min]
  • hana 신청
정원 도달

신규 유효 ID hana를 추가한다.

  • 정원·신청자 1: REGISTERED
  • 정원·신청자 2: participants [min,hana]
  • 정원·신청자 3: OPEN 유지
  • 참가 수 1→2
새 신청 거절

jun은 새 ID지만 정원이 찼다.

  • 정원·신청자 1: FULL
  • 정원·신청자 2: participants [min,hana] 유지
  • 정원·신청자 3: min 재신청은 별도 ALREADY_REGISTERED
  • 명단 유지

정원 입력의 범위와 신청 상태의 경계를 구분한다

모집은 열려 있고 참가자는 min뿐이다. jun은 새 ID지만 정원이 찼다. 각 단계의 값과 전환 이유를 비교합니다.

SOFTWARE ENGINEERING · READING CLUB

정원 입력의 범위와 신청 상태의 경계를 구분한다

생성 입력을 검증하는 숫자 영역과 실행 중 참가자 수가 바뀌는 상태 전이는 서로 다른 경계입니다.

정원 입력의 범위와 신청 상태의 경계를 구분한다상단은 정원 입력 0 거절, 1부터100까지 허용,101 거절의 숫자 범위입니다. 하단은 정원2의 열린 모임에서 참가자1명에 hana를 등록해2명이 된 뒤 새jun 신청을 FULL로 거절하는 흐름입니다. 기존min 신청은 중복으로 거절합니다.① 모임 생성 입력: 정원은 정수 1~1000거절1허용100허용101거절… 유효한 정수 영역 …② 신청 시 상태: 정원 2인 열린 모임참가자 1명min새 ID hana 신청등록참가자 2명min, hana새 ID jun 신청거절FULLmin, hana 유지기존 ID min이면 중복
정원 입력의 범위와 신청 상태의 경계를 구분한다상단은 정원 입력 0 거절, 1부터100까지 허용,101 거절의 숫자 범위입니다. 하단은 정원2의 열린 모임에서 참가자1명에 hana를 등록해2명이 된 뒤 새jun 신청을 FULL로 거절하는 흐름입니다. 기존min 신청은 중복으로 거절합니다.① 정원 입력: 정수 1~1000거절1허용100허용101거절유효한 정수 영역② 참가자 수: 정원 2 · OPEN참가자 1명min새 ID hana 신청등록참가자 2명min, hana새 ID jun 신청거절FULLmin, hana 유지기존 ID min이면 중복

상단의 1~100은 정원 입력 정책입니다. 하단의 1→2는 신청 상태 변화입니다. 같은 만석 상태라도 기존 ID의 중복 거절은 우선순위를 확인하는 별도 사례입니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 한 자리 남음부터 새 신청 거절까지 진행합니다.

관계도의 보충 설명

전체 도표의 표기·관계·조건
구분전체 도표의 내용
관계 설명상단은 정원 입력 0 거절, 1부터 100까지 허용, 101 거절의 숫자 범위입니다. 하단은 정원 2의 열린 모임에서 참가자 1명에 hana를 등록해 2명이 된 뒤 새 jun 신청을 FULL로 거절하는 흐름입니다. 기존 min 신청은 중복으로 거절합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
한 자리 남음

모집은 열려 있고 참가자는 min뿐이다.

  • 정원·신청자 1: capacity2
  • 정원·신청자 2: OPEN
  • 정원·신청자 3: participants [min]
  • hana 신청
정원 도달

신규 유효 ID hana를 추가한다.

  • 정원·신청자 1: REGISTERED
  • 정원·신청자 2: participants [min,hana]
  • 정원·신청자 3: OPEN 유지
  • 참가 수 1→2
새 신청 거절

jun은 새 ID지만 정원이 찼다.

  • 정원·신청자 1: FULL
  • 정원·신청자 2: participants [min,hana] 유지
  • 정원·신청자 3: min 재신청은 별도 ALREADY_REGISTERED
  • 명단 유지

ID 형식과 조합

ID의 길이는 1, 24, 25자로, 첫 문자는 소문자/숫자/대문자로, 이후 문자는 허용 하이픈/공백/한글로 나누어 봅니다. a와 24자 소문자는 허용, 25자 소문자와 1min은 거절입니다. 여러 무효 조건을 한 사례에 몰아넣으면 어떤 검사가 결함을 발견했는지 알기 어려워집니다.

모임 상태·이미 참가 여부·남은 자리의 조합은 길이 경계만으로 다루기 어렵습니다. 이때 결정표로 조건과 결과를 대응합니다. ID가 유효하다고 가정하면 CLOSED는 항상 CLOSED, OPEN의 기존 ID는 중복, OPEN의 새 ID는 남은 자리에 따라 등록 또는 FULL입니다. “OPEN·기존 ID·만석”은 두 거절 조건의 우선순위를 확인하는 핵심 사례입니다.

실제로 확인

다음 코드를 examples/ch5.mjs로 저장해 실행합니다. 두 번째 절의 작은 논리식은 다음 문서에서 조건 검증을 비교하기 위해 포함했습니다.

import assert from "node:assert/strict";
import { createSession, register } from "../core.mjs";
for (const capacity of [0, 1, 100, 101, 1.5, "2", null]) {
  let actual;
  try {
    createSession({ id: "boundary", title: "경계 실습", capacity });
    actual = "ACCEPT";
  } catch (error) {
    actual = error.name;
  }
  const expected = capacity === 1 || capacity === 100 ? "ACCEPT" : "RangeError";
  assert.equal(actual, expected);
  console.log("capacity", JSON.stringify(capacity), actual);
}
function decision(x, y) { return x > 1 && y === 0; }
const inputs = [[2, 0], [1, 0], [2, 1]];
for (const [x, y] of inputs) console.log("decision", x, y, decision(x, y));
let s = createSession({ id: "one-seat", title: "한 자리", capacity: 1 });
s = register(s, "min").state;
assert.equal(register(s, "min").code, "ALREADY_REGISTERED");
assert.equal(register(s, "hana").code, "FULL");
console.log("overlapping conditions", "ALREADY_REGISTERED", "FULL");
node examples/ch5.mjs

출력에서 0·101·1.5·문자열 "2"·null은 RangeError, 1·100은 ACCEPT입니다. 각 결과는 단언으로 확인합니다. 마지막 ALREADY_REGISTERED FULL은 같은 만석 상태의 기존 ID와 새 ID가 서로 다른 거절 이유를 받았음을 보여 줍니다. 유효하지 않은 ID 때문에 중복·정원 로직에 도달하지 못한 사례와 혼동하지 않습니다.

독립 문제: 경계를 다른 규칙으로 찾기

다음 버전의 취소 정책은 “시작 30분 전까지 취소 가능”입니다. 시간 계산 함수는 별도로 있다고 할 때 테스트할 경계와 아직 결정되지 않은 정책 질문을 적으세요. 정확히 30분 전이 허용인지도 근거 없이 정하지 마세요.

힌트

시간 단위·포함 여부·기준 시계를 먼저 결정합니다. 정원 숫자와 똑같은 사례를 복사하지 않습니다.

해설

정확히 30분, 바로 전후(예: 30분 1초와 29분 59초)를 선택합니다. 정확히 30분을 허용하는지, 초 단위인지 분으로 반올림하는지, 서버 시계인지 사용자 시계인지 확인합니다. 시작 시각을 지난 경우와 잘못된 시각 입력도 별도 영역입니다. 시간대나 시계 조정은 실제 서비스 요구에 따라 추가합니다. 정책이 미정인 기대 값을 구현에서 읽어 정답으로 만들지 않습니다.

경계만 확인하고 모든 내부 값은 안전하다고 단정하지 않습니다. 문자열 처리나 계산 규칙 때문에 같은 영역 안에도 다른 결함이 있을 수 있습니다.