실패 응답 분류
140분 안팎
학습 목표
조건문 예제로 정상·입력 오류·서버 오류를 구분합니다.
개념
오류 건수를 셀 때 무엇을 성공이라고 부를지 정합니다
신청 요청 기록을 살펴볼 때 HTTP 201과 200을 서로 다른 열로만 세면 전체 흐름이 잘 보이지 않습니다. 반대로 200이 아닌 값을 전부 실패로 세면 생성 성공 201도 오류에 포함됩니다. 이번 레슨은 상태 코드 목록을 조건문으로 분류하고 경계값 테스트로 판단 기준을 확인합니다. 작은 프로그램을 읽을 수 있으면 개발자가 제안한 집계 규칙에서 무엇이 빠졌는지 질문할 수 있습니다. 이 집계는 HTTP 범주를 연습하는 것이며 승인 완료율을 계산하는 지표는 아닙니다.
표준 범주와 연습의 집계 이름을 구분합니다
이 과제는 200부터 299까지를 정상, 400부터 499까지를 클라이언트 오류, 500부터 599까지를 서버 오류, 나머지를 기타로 셉니다. 출력 순서는 정상·클라이언트 오류·서버 오류·기타입니다. 계획에서 입력 오류라고 부른 범주를 실제 상태 분류에서는 클라이언트 오류로 명확히 이름 붙입니다. 4xx에는 입력 문제뿐 아니라 인증, 권한, 자원 없음 등도 들어갈 수 있습니다. 네 숫자를 출력했다는 이유로 모든 클라이언트 오류의 원인이 잘못된 입력이라고 단정하지 않습니다.
1xx는 중간 정보를, 3xx는 리디렉션 등을 나타낼 수 있지만 이번 과제는 둘을 기타에 묶습니다. 기타는 실패라는 동의어가 아닙니다. 302가 하나 있다고 사용자 작업이 실패했다고 결론내릴 수 없습니다. 실제 작업 성공을 분석할 때는 리디렉션 뒤 최종 응답이나 화면 결과가 추가로 필요합니다. 숫자 범주와 사용자 경험 사이에 해석 단계를 남기는 것이 기획자의 역할입니다. 범주를 단순화한 목적과 잃는 정보도 함께 적습니다.
한 상태를 정확히 한 곳에 넣습니다
조건문은 어떤 조건이 참일 때 실행할 일을 고릅니다. code가 200 이상이고 300 미만인지 두 비교를 함께 확인합니다. 자바스크립트에서는 두 조건을 &&로 연결합니다. 수학식처럼 200 <= code < 300이라고 쓰면 기대한 범위 비교가 되지 않습니다. 먼저 얻은 참·거짓을 다시 숫자와 비교할 수 있으므로 경계 테스트에서 뜻밖의 결과가 나옵니다. 두 비교를 분리하고 명시적으로 연결한 표현을 사용합니다.
if 다음에 else if를 쓰면 앞 조건이 맞았을 때 뒤 분기를 건너뜁니다. 이번 네 범주는 겹치지 않도록 정했으며 마지막 else는 나머지를 받습니다. code가 599일 때 서버 오류이고 600일 때 기타인지 직접 확인합니다. 조건 하나를 code > 500으로 쓰면 500 자체가 빠집니다. 다른 조건 하나를 code <= 600으로 쓰면 600이 잘못 들어갑니다. 오류는 문법보다 포함할 끝값을 잘못 읽어서 생기기 쉬우므로 범위를 말로 먼저 적습니다.
입력 목록을 반복해서 읽습니다
브라우저 실습에는 공백이나 줄바꿈으로 나눈 HTTP 상태 정수 목록이 들어옵니다. 첫 줄에 개수는 없습니다. 빈 입력은 요청이 없는 경우이며 네 개수 모두 0을 출력합니다. 유효한 입력의 숫자는 100부터 599까지지만 경계 분기 확인을 위해 99와 600도 테스트 값으로 허용합니다. 그 밖의 문자나 소수는 입력하지 않는 과제입니다. 일반 사용자 입력을 안전하게 검증하는 기능을 이 코드가 구현했다고 주장하지 않습니다.
시작 코드는 표준 입력 문자열을 읽고 trim으로 앞뒤 공백을 제거합니다. 입력이 빈 문자열이면 빈 배열을 만들고, 아니면 공백 패턴으로 나눈 뒤 Number로 숫자로 바꿉니다. 이 분기가 없으면 빈 문자열을 숫자 0으로 처리해서 기타 한 건이 생길 수 있습니다. 빈 입력 테스트가 필요한 이유입니다. for...of는 배열의 값을 하나씩 꺼냅니다. 각 값을 분류한 뒤 해당 개수를 하나 올리고 마지막에 공백으로 네 숫자를 연결해 한 줄을 출력합니다.
출력 형식도 계약입니다
입력 201 422 503 302의 기대 결과는 1 1 1 1입니다. 한국어 범주 이름을 함께 출력하거나 JSON 객체로 출력하면 사람이 읽기 편해도 이번 채점 계약과 다릅니다. 0을 0.0으로 바꾸거나 쉼표를 끼우지 않고 정수 네 개를 공백으로 구분합니다. 출력 순서가 바뀌면 합계가 맞아도 오답입니다. 화면에서 보는 안내와 채점기가 받는 값은 다른 용도이므로 안내는 prompt에 두고 결과는 약속한 형식만 출력합니다.
시작본은 모든 값을 기타로 넣도록 남겨 두었습니다. 입력 파싱과 출력 부분은 준비되어 있어 조건 분류에 집중할 수 있습니다. counts의 0번 칸은 정상, 1번은 클라이언트 오류, 2번은 서버 오류, 3번은 기타입니다. 배열 칸 번호는 코드에서 쓰는 번호이며 확인 문제의 보기 위치를 의미하지 않습니다. 어떤 칸을 올릴지 말로 설명한 뒤 코드를 고치면 조건이 맞는데 집계 순서만 틀리는 실수를 줄일 수 있습니다.
작은 테스트부터 반례를 찾습니다
한 요청만 넣어 200, 400, 500이 각각 어느 칸에 들어가는지 봅니다. 이후 199·200·299·300·399·400·499·500·599·600을 한꺼번에 넣어 양 끝을 비교합니다. 정상은 두 개, 클라이언트 오류는 두 개, 서버 오류는 두 개, 기타는 네 개입니다. 섞인 목록에서도 입력 순서가 집계 결과에 영향을 주지 않아야 합니다. 같은 코드 500을 세 번 보내면 서버 오류가 세 개이고 다른 범주로 중복 계산되지 않아야 합니다.
오답이 나오면 기대값과 실제값의 차이를 범주별로 읽습니다. 서버 오류가 하나 부족하고 기타가 하나 많으면 500이나 599가 빠졌는지 작은 입력으로 확인합니다. 모든 범주가 0인데 기타만 전체 개수라면 시작본의 임시 분기가 남아 있는지 봅니다. SyntaxError는 괄호·중괄호·연산자 위치를 먼저 확인하라는 뜻이며 ReferenceError는 사용한 변수 이름이 선언과 다른지 확인합니다. 실제 브라우저가 제시한 오류 문장을 읽고 가장 작은 재현 입력을 남깁니다.
집계 결과를 지원 판단에 연결할 때 주의합니다
HTTP 200과 PENDING은 동시에 존재할 수 있습니다. 범주상 정상 한 건이지만 승인 한 건으로 세면 안 됩니다. 404 한 건은 조회한 ID를 찾지 못했다는 응답이지 모든 신청이 사라졌다는 증거가 아닙니다. 503을 서버 오류로 분류할 수 있어도 저장 전 실패인지 응답 전송 중 문제인지는 별도 기록이 필요합니다. 범주 집계는 조사 순서를 정할 단서이며 요청 ID와 오류 본문을 대체하지 않습니다.
조건문을 완료한 뒤에는 각 범주에 다음 확인 항목을 하나씩 붙여 설명합니다. 정상은 응답 계약과 화면 표시, 클라이언트 오류는 error.code와 요청 입력 또는 접근 조건, 서버 오류는 요청 ID로 내부 기록, 기타는 응답 종류와 최종 결과를 확인합니다. 모든 4xx를 사용자의 실수라고 말하거나 모든 5xx에서 반복 제출을 권하지 않습니다. 숫자를 분류하는 구현과 사용자에게 필요한 다음 행동을 구별해서 설명할 수 있으면 레슨 목표를 달성한 것입니다.
따라하기
생성 성공과 오류를 나눕니다
배열은 준비된 HTTP 숫자입니다. code라는 변수에 값을 하나씩 넣고 두 비교를 연결합니다. Node로 그대로 실행하면 아래 집계가 나옵니다.
const codes = [201, 422, 503, 302];
const counts = [0, 0, 0, 0];
for (const code of codes) {
if (code >= 200 && code < 300) counts[0]++;
else if (code >= 400 && code < 500) counts[1]++;
else if (code >= 500 && code < 600) counts[2]++;
else counts[3]++;
}
console.log(counts.join(" "));실행 결과
1 1 1 1
빈 입력 파싱을 확인합니다
요청이 없는 경우를 빈 배열로 만들어 검사합니다. 빈 문자열이 숫자 0으로 바뀌지 않도록 분기했습니다.
const raw = "".trim();
const codes = raw === "" ? [] : raw.split(/\s+/).map(Number);
console.log(codes.length);실행 결과
0
서버 오류 양 끝을 실행합니다
500과 599만 서버 오류 조건에 맞고 600은 맞지 않는지 출력과 비교합니다.
for (const code of [500, 599, 600]) {
console.log(code, code >= 500 && code < 600);
}실행 결과
500 true 599 true 600 false
시작 분기를 완성합니다
아래 브라우저 실습에서 counts[3]++만 있는 부분을 네 범주 분기로 바꿉니다. 빈 입력·경계 목록·반복 코드·줄바꿈 혼합을 각각 실행합니다. 네 합계가 입력 코드 개수와 일치하는지도 확인합니다.
확인 문제
실습
공백·줄바꿈으로 나눈 정수 상태 목록을 읽습니다. 개수 줄은 없습니다. 200~299는 정상, 400~499는 클라이언트 오류, 500~599는 서버 오류, 나머지는 기타입니다. 정수 네 개를 정상·클라이언트 오류·서버 오류·기타 순서로 공백 구분해 한 줄 출력합니다. 빈 입력은 0 0 0 0입니다. 입력에는 정수 99~600만 오며 문자와 소수는 없습니다. 4xx 전체가 입력 오류를 뜻하는 것은 아닙니다. 입력 파싱과 출력은 제공되며 반복문 안의 임시 분기를 수정합니다.
모범 답안
const fs = require('fs');
const raw = fs.readFileSync(0, 'utf8').trim();
const codes = raw === '' ? [] : raw.split(/\s+/).map(Number);
const counts = [0, 0, 0, 0];
for (const code of codes) {
if (code >= 200 && code < 300) counts[0]++;
else if (code >= 400 && code < 500) counts[1]++;
else if (code >= 500 && code < 600) counts[2]++;
else counts[3]++;
}
console.log(counts.join(' '));
더 읽기
면접 질문
- 화면에서 저장 버튼을 눌렀을 때의 데이터 흐름을 설명해 주시면 됩니다.