동치 분할과 경계값
유효·무효 입력 공간과 경계를 구분하고 정원·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
정원 입력의 범위와 신청 상태의 경계를 구분한다
생성 입력을 검증하는 숫자 영역과 실행 중 참가자 수가 바뀌는 상태 전이는 서로 다른 경계입니다.
상단의 1~100은 정원 입력 정책입니다. 하단의 1→2는 신청 상태 변화입니다. 같은 만석 상태라도 기존 ID의 중복 거절은 우선순위를 확인하는 별도 사례입니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 한 자리 남음부터 새 신청 거절까지 진행합니다.
관계도의 보충 설명
| 구분 | 전체 도표의 내용 |
|---|---|
| 관계 설명 | 상단은 정원 입력 0 거절, 1부터 100까지 허용, 101 거절의 숫자 범위입니다. 하단은 정원 2의 열린 모임에서 참가자 1명에 hana를 등록해 2명이 된 뒤 새 jun 신청을 FULL로 거절하는 흐름입니다. 기존 min 신청은 중복으로 거절합니다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 한 자리 남음 모집은 열려 있고 참가자는 min뿐이다. |
|
|
| 정원 도달 신규 유효 ID hana를 추가한다. |
|
|
| 새 신청 거절 jun은 새 ID지만 정원이 찼다. |
|
|
정원 입력의 범위와 신청 상태의 경계를 구분한다
모집은 열려 있고 참가자는 min뿐이다. jun은 새 ID지만 정원이 찼다. 각 단계의 값과 전환 이유를 비교합니다.
SOFTWARE ENGINEERING · READING CLUB
정원 입력의 범위와 신청 상태의 경계를 구분한다
생성 입력을 검증하는 숫자 영역과 실행 중 참가자 수가 바뀌는 상태 전이는 서로 다른 경계입니다.
상단의 1~100은 정원 입력 정책입니다. 하단의 1→2는 신청 상태 변화입니다. 같은 만석 상태라도 기존 ID의 중복 거절은 우선순위를 확인하는 별도 사례입니다.
이 예의 조건
- 본문과 전체 도표의 예를 따라 한 자리 남음부터 새 신청 거절까지 진행합니다.
관계도의 보충 설명
| 구분 | 전체 도표의 내용 |
|---|---|
| 관계 설명 | 상단은 정원 입력 0 거절, 1부터 100까지 허용, 101 거절의 숫자 범위입니다. 하단은 정원 2의 열린 모임에서 참가자 1명에 hana를 등록해 2명이 된 뒤 새 jun 신청을 FULL로 거절하는 흐름입니다. 기존 min 신청은 중복으로 거절합니다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| 한 자리 남음 모집은 열려 있고 참가자는 min뿐이다. |
|
|
| 정원 도달 신규 유효 ID hana를 추가한다. |
|
|
| 새 신청 거절 jun은 새 ID지만 정원이 찼다. |
|
|
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분을 허용하는지, 초 단위인지 분으로 반올림하는지, 서버 시계인지 사용자 시계인지 확인합니다. 시작 시각을 지난 경우와 잘못된 시각 입력도 별도 영역입니다. 시간대나 시계 조정은 실제 서비스 요구에 따라 추가합니다. 정책이 미정인 기대 값을 구현에서 읽어 정답으로 만들지 않습니다.
경계만 확인하고 모든 내부 값은 안전하다고 단정하지 않습니다. 문자열 처리나 계산 규칙 때문에 같은 영역 안에도 다른 결함이 있을 수 있습니다.