본문 바로가기

코딩 규칙과 코드 검토

이름·주석·형식 합의와 행동 검토를 구별하고 경계 결함을 재현·수정·회귀 확인합니다.

들여쓰기가 가지런하고 함수 이름이 친절해도 정원이 찬 모임에 한 명을 더 받는 코드는 잘못되었습니다. 반대로 규칙을 지키는 코드가 읽기 어려우면 다음 수정에서 결함이 생길 수 있습니다. 코딩 규칙은 읽기와 변경을 돕고, 코드 검토는 요구·설계·실행 사이의 차이를 찾습니다.

이번 단원에서는 숫자·이름·주석의 의미를 명확히 하고 경계 조건 결함을 검토합니다. 앞 본문의 계약·부수효과를 읽을 수 있으면 진행할 수 있습니다. 새 도구 설치나 리뷰 서비스 가입은 필요하지 않습니다.

합의할 규칙과 검증할 행동을 나눈다

코딩 규칙(coding convention)은 이름·공백·들여쓰기·오류 처리 등의 일관된 작성 합의입니다. 프로젝트가 두 칸 들여쓰기를 정하면 파일마다 다르게 쓰지 않습니다. 자동 포맷터는 그런 기계적인 차이를 줄입니다. 린터(linter)는 사용하지 않는 변수나 위험한 패턴 같은 설정된 규칙 위반을 찾는 도구입니다.

어떤 도구도 요구의 모든 의미를 대신 이해하지는 않습니다. ‘종료 뒤 참가 취소 허용’이라는 업무 약속을 린터가 자동으로 보장한다고 기대할 수 없습니다. 형식 검사와 행동 검증을 구분해야 합니다.

원자료의 명칭 31자·파일 200줄·함수 70줄 등 숫자는 모든 언어의 필수 한계로 쓰지 않습니다. 길이 가이드가 도움이 될 수 있지만 단위가 가진 책임과 읽기 흐름을 봐야 합니다. 69줄 함수가 전역 상태 다섯 개를 수정하면 71줄의 명확한 계산보다 낫다고 단정할 수 없습니다. 명시한 팀 규칙과 실제 언어 제약을 혼동하지 않습니다.

이름은 값의 의미와 단위를 드러낸다

n과 c 대신 participantCount와 capacity를 쓰면 비교 의미가 보입니다. hasAvailableSeat는 boolean 결과를 예상하게 하고 register는 상태 변화가 있는 연산임을 드러냅니다. 단순 조회처럼 보이는 getMembers가 파일을 저장한다면 이름과 동작이 어긋납니다.

같은 개념에는 같은 이름을 씁니다. ‘모집 종료’를 closed, finished, done으로 섞으면 모임 진행 완료인지 신청 마감인지 읽기 어렵습니다. 서로 다른 개념에는 이름을 구분합니다. status와 resultCode는 앞 장처럼 대상 상태와 요청 결과를 나눕니다.

프로그래밍 식별자와 업무 식별 코드도 구분합니다. memberId는 변수 이름이고 member-42는 한 회원을 가리키는 데이터 값입니다. 업무 코드는 고유성·변경 가능성·정렬 의미를 검토합니다. 회원 이름이 바뀌었다고 ID까지 바뀌게 만들면 과거 관계가 끊길 수 있습니다. ID에 부서나 학년을 넣을 때는 이동·진급 뒤 의미가 낡는 경우를 생각합니다. 단순 축약이나 숫자 치환은 암호화가 아닙니다.

주석은 왜 필요한지 설명한다

// 1을 더한다 다음 줄에 count += 1이 있으면 새 정보가 적습니다. 반면 ‘중복 검사를 정원보다 먼저 해 이미 참가한 회원에게 같은 결과를 돌려준다’는 주석은 검사 순서의 이유를 알려 줍니다. 설명이 코드와 달라지면 주석도 결함이 되므로 같이 검토합니다.

이력·작성자는 버전 관리에 남길 수 있지만 라이선스와 출처 등 보존해야 할 표시는 임의로 지우지 않습니다. 개인 정보·비밀 값은 코드 예시나 로그에 넣지 않습니다. 이 교재의 회원 ID는 가상 값입니다.

검토 의견을 재현 입력과 회귀 확인으로 연결한다

경계에서 새 신청을 실행한다. 같은 입력을 회귀 사례로 남겨 결함의 재발을 막는다. 각 단계의 값과 전환 이유를 비교합니다.

SOFTWARE ENGINEERING · CH4-4

검토 의견을 재현 입력과 회귀 확인으로 연결한다

형식 합의와 별도로 요구 위반을 구체적인 입력으로 확인합니다.

검토 의견을 재현 입력과 회귀 확인으로 연결한다요구의 기대값을 실행 결과와 비교하고 차이의 원인을 수정한 뒤 같은 입력을 회귀 확인에 남겨 검토를 반복합니다.요구와 기대값경계 입력을 고른다실행 결과기대와 실제를 비교한다차이의 원인조건 · 상태 · 계약 확인수정과 회귀 확인문제 입력을 검증에 남긴다

요구의 기대값을 실행 결과와 비교하고 차이의 원인을 수정한 뒤 같은 입력을 회귀 확인에 남겨 검토를 반복합니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 반례 입력부터 수정과 회귀까지 진행합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
반례 입력

경계에서 새 신청을 실행한다.

  • 반례·차이 1: capacity2
  • 반례·차이 2: count2
  • 반례·차이 3: 기대 거절
  • 경계 입력 재현
차이 찾기

true 반환으로 세 번째 회원을 받는 것은 요구 위반이다.

  • 반례·차이 1: 기대 거절
  • 반례·차이 2: 실제 true
  • 조건·상태·계약의 원인 검토
수정과 회귀

같은 입력을 회귀 사례로 남겨 결함의 재발을 막는다.

  • 반례·차이 1: count>=capacity이면 거절
  • 반례·차이 2: 실패 명단 유지 확인
  • 수정 후 경계 사례를 회귀에 추가

검토 의견을 재현 입력과 회귀 확인으로 연결한다

경계에서 새 신청을 실행한다. 같은 입력을 회귀 사례로 남겨 결함의 재발을 막는다. 각 단계의 값과 전환 이유를 비교합니다.

SOFTWARE ENGINEERING · CH4-4

검토 의견을 재현 입력과 회귀 확인으로 연결한다

형식 합의와 별도로 요구 위반을 구체적인 입력으로 확인합니다.

검토 의견을 재현 입력과 회귀 확인으로 연결한다요구의 기대값을 실행 결과와 비교하고 차이의 원인을 수정한 뒤 같은 입력을 회귀 확인에 남겨 검토를 반복합니다.요구와 기대값경계 입력을 고른다실행 결과기대와 실제를 비교한다차이의 원인조건 · 상태 · 계약 확인수정과 회귀 확인문제 입력을 검증에 남긴다

요구의 기대값을 실행 결과와 비교하고 차이의 원인을 수정한 뒤 같은 입력을 회귀 확인에 남겨 검토를 반복합니다.

이 예의 조건

  • 본문과 전체 도표의 예를 따라 반례 입력부터 수정과 회귀까지 진행합니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
반례 입력

경계에서 새 신청을 실행한다.

  • 반례·차이 1: capacity2
  • 반례·차이 2: count2
  • 반례·차이 3: 기대 거절
  • 경계 입력 재현
차이 찾기

true 반환으로 세 번째 회원을 받는 것은 요구 위반이다.

  • 반례·차이 1: 기대 거절
  • 반례·차이 2: 실제 true
  • 조건·상태·계약의 원인 검토
수정과 회귀

같은 입력을 회귀 사례로 남겨 결함의 재발을 막는다.

  • 반례·차이 1: count>=capacity이면 거절
  • 반례·차이 2: 실패 명단 유지 확인
  • 수정 후 경계 사례를 회귀에 추가

검토를 시작할 질문

관점읽을 질문확인 방법
요구정원에 도달하면 새 신청을 막는가경계 입력과 기대값
상태실패할 때 명단을 바꾸지 않는가전후 상태 비교
계약같은 결과 코드·반환 형태를 유지하는가호출부·문구 변환 확인
오류저장 실패를 성공으로 표시하지 않는가실패 경로 실행
이해함수 이름과 부수효과가 일치하는가이름·입력·출력 설명

검토 의견은 ‘이 코드 이상해요’보다 관찰 가능한 입력을 제시합니다. ‘정원 2, 현재 2명일 때 true를 반환해 세 번째 회원을 받습니다’처럼 쓸 수 있습니다. 작성자가 취향 논쟁 대신 요구 위반을 재현하고 고칠 수 있습니다.

경계 결함을 실제로 드러낸다

faultyHasSeat는 <=를 써서 정원과 같은 인원도 자리가 있다고 판단합니다. 수정 함수는 <를 사용합니다. 빈 명단만 테스트하면 두 구현 모두 성공하므로 잘못된 연산자를 놓칩니다.

저장소 최상위 폴더에서 다음 명령을 실행합니다. Node.js가 설치되어 있어야 하며 패키지를 추가로 설치하지 않습니다. 두 번째 인수를 생략하면 이 장의 예제를 모두 실행합니다.

node dev-note/scripts/software-engineering-lab/examples/ch4.mjs ch4-4
ch4-4 실행 예제
function faultyHasSeat(participantCount, capacity) {
  return participantCount <= capacity;
}
function hasSeat(participantCount, capacity) {
  return participantCount < capacity;
}
const reviewCases = [
  { count: 0, capacity: 2, expected: true },
  { count: 2, capacity: 2, expected: false },
  { count: 3, capacity: 2, expected: false },
];
for (const item of reviewCases) {
  const before = faultyHasSeat(item.count, item.capacity);
  const after = hasSeat(item.count, item.capacity);
  console.log(item.count, item.capacity,
    "기대:", item.expected, "수정 전:", before, "수정 후:", after);
}

첫 경우는 기대·수정 전·수정 후가 모두 true입니다. 두 번째 경우는 기대 false, 수정 전 true, 수정 후 false라서 차이가 드러납니다. 세 번째 경우는 모두 false입니다. 결함을 찾은 입력을 수정 후에도 검증에 남기면 같은 실수를 다시 잡는 회귀 테스트(regression test)가 됩니다.

이 작은 계산의 통과가 신청 전체의 완료를 뜻하지는 않습니다. 회원 ID 검사·모집 상태·중복·상태 보존도 각각 요구와 연결해 확인해야 합니다. 검토 범위를 적으면 한 조건만 확인하고 전 기능이 안전하다고 말하는 일을 줄일 수 있습니다.

의사코드와 실행 코드의 역할

복잡한 절차는 자연어와 조건문을 섞은 의사코드(pseudocode)로 먼저 설명할 수 있습니다. ‘유효한 ID가 아니면 거절, 종료되면 거절, 중복이면 기존 상태 반환’처럼 작성합니다. 이는 설계 설명이며 바로 실행하는 언어 문법은 아닙니다. 필요한 경우 순서도는 분기 위치를 보여 주고 표는 경계 입력을 보여 줍니다.

실제 코드로 옮길 때는 언어의 비교·복사·예외 규칙을 확인해야 합니다. ‘한 줄씩 실행하는 언어는 인터프리터, 사전에 모두 바꾸는 언어는 컴파일러’처럼 언어 자체를 단순 이분법으로 고정하지 않습니다. 런타임은 여러 처리 방식을 결합할 수 있습니다. 이 교재는 Node.js에서 실행한 JavaScript 결과로 동작을 검증하며 다른 언어 규칙을 섞지 않습니다.

검토의 중간 과정을 기록한다

좋은 기록에는 문제 입력, 기대 결과, 실제 결과, 수정 이유, 확인 범위가 있습니다. 여기서는 ‘정원과 같은 인원’이 문제 입력, 신규 신청 거절이 기대, 자리 있음이 실제이며 <= → <가 수정입니다. 빈 경우와 초과 경우도 다시 확인했습니다.

검토를 한 사람이 모든 실수를 찾는다고 가정하지 않습니다. 다른 관점의 독자에게 요구 설명 없이 코드를 읽어 보게 하고 이름만으로 의미를 알 수 있는지도 확인할 수 있습니다. 사람 검토는 자동 검사와 역할이 다릅니다.

독립 문제: 읽기 쉬운 할인 조건 검토

동아리 굿즈는 수량이 5개 이상이면 할인을 적용합니다. 아래 식을 검토합니다.

const d = n > 5 ? 0.1 : 0;

의미가 드러나는 함수·인수·결과 이름을 제안하고, 최소한의 경계 사례 세 개와 기대값을 씁니다. ‘짧아졌으니 좋은 코드’라는 설명을 평가하고 수정 이유를 한 문장으로 작성합니다.

힌트

요구의 ‘이상’과 코드의 ‘초과’를 비교합니다. 할인 비율인지 할인 금액인지 결과 단위를 정합니다.

풀이

discountRate(quantity)처럼 수량에서 할인 비율을 반환하는 함수로 나타낼 수 있습니다. quantity >= 5 ? 0.1 : 0가 요구에 맞습니다. 수량 4는 0, 5는 0.1, 6은 0.1이며 원래 식은 5에서 틀립니다.

d는 금액·비율·여부 중 무엇인지 알 수 없어 이름을 구체화합니다. 수정 이유는 ‘5개 이상 할인 요구를 만족하도록 경계 수량 5도 할인 분기에 포함한다’입니다. 코드가 짧다는 사실은 요구 일치나 읽기 쉬움을 보장하지 않습니다.

다음에 사용할 검토 기준

이 장에서 책임 경계·의존·행동 계약·검토 근거를 함께 배웠습니다. 테스트 장에서는 정상·경계·실패 사례를 더 체계적으로 만들고, 아키텍처 장에서는 이 경계를 저장 방식과 구조 변경에 적용합니다.


원자료와 더 읽기

장원사이버평생교육원 「소프트웨어공학」 PDF 물리 201–217쪽의 주제를 바탕으로 설명·도표·실습을 새로 구성했습니다.

언어별 공개 구조는 MDN JavaScript 모듈과 클래스를 참고합니다. 원자료의 고정 길이 규칙을 보편적 언어 제한으로 옮기지 않았습니다.