# EARS 요구사항 구문을 예와 함께 설명

Canonical: https://specscore.md/ko/articles/ears-requirements/

마지막 업데이트: 2026년 11월 2일

[EARS](https://alistairmavin.com/ears/)(Easy Approach to Requirements Syntax)는 요구사항 표기법입니다. 조건, 트리거, 시스템 응답을 고정된 순서로 두는 영어 문장 패턴의 작은 집합이며, EARS 구문이라고도 합니다. 요구사항은 시스템이 충족해야 하는 검증 가능한 의무 하나입니다. [명세 주도 개발](https://specscore.md/ko/spec-driven-development/)(SDD, spec-driven development)은 그 의무를 코드보다 먼저 명세에 적고, 명세를 진실의 원천으로 다루는 방식입니다. 제품 요구사항 문서(PRD, product requirements document)는 일을 과제로 나누기 전에 문제와 범위를 적는 산문입니다. [SpecScore](https://specscore.md/)에서 요구사항(REQ)은 기능 안의 이름이 있는 규칙이고, 인수 기준(AC, acceptance criterion)은 그 규칙 하나 이상을 가리키는 선택적 추상 조건입니다. [지속적 통합](https://specscore.md/ko/validators/)(CI, continuous integration)은 제안된 변경마다 도는 자동 검사입니다. 그 검사는 [명령줄 인터페이스](https://specscore.md/ko/cli/)(CLI, command-line interface) 명령 `specscore spec lint`입니다. [Kiro](https://kiro.dev/)는 Amazon Web Services(AWS)의 에이전트형 통합 개발 환경(IDE, integrated development environment)이며, 이 패턴 중 하나를 씁니다. 표기법은 2009년 Alistair Mavin과 Rolls-Royce 동료들이 Institute of Electrical and Electronics Engineers(IEEE) 요구공학 학회에서 처음 발표했습니다.

## EARS는 어디서 왔는가

당시 Rolls-Royce PLC의 Alistair Mavin, Philip Wilkinson, Adrian Harwood, Mark Novak은 2009년 17th IEEE International Requirements Engineering Conference에서 “Easy Approach to Requirements Syntax (EARS)”를 발표했습니다. 문서 식별자는 [10.1109/RE.2009.9](https://doi.org/10.1109/RE.2009.9)입니다. 규칙은 감항 규정인 Certification Specification for Engines(CS-E)의 CS-E 50에서 엔진 제어 요구사항을 뽑으며 만들었습니다. 원문은 요구사항, 설계 안내, 주석이 섞여 있었습니다.

논문은 제약 없는 자연어의 여덟 문제를 꼽습니다. 모호함, 막연함, 복잡함, 누락, 중복, 장황함, 부적절한 구현, 검증 불가능성입니다. 작은 규칙 집합이 그런 요구사항마다 다섯 틀 중 하나를 쓰게 하려는 것이었습니다. 저자는 이 표기법이 상위 이해관계자 요구사항에 맞다고 하고, 시스템 분해의 모든 층을 다룬다고 주장하지 않습니다.

[Mavin 자신의 안내](https://alistairmavin.com/ears/)는 EARS를 텍스트 요구사항을 부드럽게 제약하는 방법으로 설명합니다. 절은 한 순서를 지키며, 그는 이를 시간 논리라고 부릅니다. 전제, 그다음 트리거, 그다음 시스템 이름과 응답입니다. 규칙은 전제 0개 이상, 트리거 0개 또는 1개, 시스템 이름 1개, 응답 1개 이상입니다. 2009년 논문은 이 형태를 다섯 틀로 나눕니다. 같은 안내는 키워드를 조합하는 복합 요구사항도 이름 붙입니다.

논문의 사례에서 원문 추출은 36개, 다시 쓴 집합은 47개였습니다. 평균 길이는 36.9단어에서 25.6단어로 줄었습니다. 저자는 그 연구에서 복잡함, 누락, 중복, 부적절한 구현, 검증 불가능성이 다시 쓴 집합에는 없었고, 모호함, 막연함, 장황함은 줄었으나 사라지지 않았다고 보고합니다. 한계도 적습니다. 표본이 작고, 상위 안전 요구사항만 다루며, 막연함의 분류에 판단이 들어갑니다. 이 숫자는 그 논문이 그 문서 하나에 대해 적은 숫자입니다.

## EARS 문장 패턴

키워드는 2009년 논문과 Mavin 안내에 있는 것입니다. 논문은 상태에 *While* 대신 같은 뜻의 *During*을, 더 잘 읽힐 때 허용합니다. 예문은 틀을 보여 주며 논문 인용이 아닙니다. Kiro는 사건 주도 패턴을 대문자로 씁니다. 원래 표기법은 문장 첫 글자를 대문자로 합니다. 예는 영어로 둡니다. EARS 구문이 영어이기 때문입니다.

### 항상

`The <system name> shall <system response>`

항상 유효합니다. 전제도 트리거도 없으므로 EARS 키워드가 없습니다. 2009년 논문 자신의 예는 엔진 과속을 막아야 하는 제어 시스템입니다.

**예:** The checkout system shall keep the order total equal to the sum of its line items.

### 사건 주도

`When <trigger>, the <system name> shall <system response>`

응답이 필요한 때는 시스템 경계에서 트리거가 감지될 때뿐이며, 그때만입니다. 키워드는 *When*입니다.

**예:** When a shopper submits the checkout form with invalid data, the checkout system shall show a validation error next to the invalid field.

### 상태 주도

`While <precondition>, the <system name> shall <system response>`

시스템이 이름 붙인 상태에 있는 동안 응답이 필요합니다. 키워드는 *While*입니다.

**예:** While the cart is empty, the checkout system shall keep the pay button disabled.

### 바라지 않는 동작

`If <trigger>, then the <system name> shall <system response>`

응답은 고장, 교란, 이탈, 그 밖의 바라지 않는 동작을 다룹니다. 키워드는 *If*와 *then*입니다. 논문은 이 패턴에 고유한 말을 주어 그 요구사항이 보이게 했습니다. 저자는 바라는 것과 바라지 않는 것이 때로 관점의 문제라고 적습니다.

**예:** If the submitted email is not a valid address, then the checkout system shall reject the form.

### 선택 기능

`Where <feature is included>, the <system name> shall <system response>`

제품이 이름 붙인 기능을 포함할 때만 응답이 적용됩니다. 키워드는 *Where*입니다.

**예:** Where the shop includes gift wrapping, the checkout system shall offer gift wrapping on the order review step.

### 복합

`While <precondition>, when <trigger>, the <system name> shall <system response>`

키워드가 둘 이상입니다. Mavin 안내는 같은 절 순서를 지킵니다. 전제는 *While*, 트리거는 *When*, 그다음 시스템 응답입니다. 2009년 논문은 어떤 상태의 바라지 않는 동작에 *While*과 *If / then* 조합도 씁니다. 그 조합의 한 예: While the shopper is signed out, if the shopper submits the checkout form, then the checkout system shall refuse the order.

**예:** While the shopper is signed in, when the shopper submits a valid checkout form, the checkout system shall place the order.

## 흔한 실수

### 한 문장에 여러 의무

논문은 복합문을 복잡함의 문제로 보고 나눕니다. [SpecScore 요구사항 명세](https://specscore.md/requirement-specification)도 같은 말을 자기 용어로 합니다. 각 `REQ`는 검증 가능한 의무를 정확히 하나 표현해야 합니다.

### 바라지 않는 동작을 When에 숨기기

*When*은 예상하는 트리거용입니다. *If / then*은 만나지 않기를 바라는 동작용입니다. 둘에 한 단어를 쓰면 바라지 않는 경우가 보통 경우처럼 보입니다. 논문이 지적한 누락 문제입니다.

### 구현을 쓰기

“The checkout system shall store the flag in Redis”는 설계를 지목합니다. 논문은 이를 부적절한 구현이라 부릅니다. 응답은 시스템이 무엇을 달성해야 하는지를 말해야 하며, 어느 부품이 하는지는 말하지 않습니다.

### 시스템 이름이 없음

“When the form is submitted, shall show an error”에는 주어가 없습니다. Mavin의 규칙은 시스템 이름 하나를 요구합니다.

### 응답 뒤에 트리거

“The checkout system shall show an error when the form is submitted”는 트리거를 끝에 둡니다. 발표된 순서는 전제, 그다음 트리거, 그다음 응답입니다.

### Kiro의 한 줄을 EARS 전체로 보기

Kiro 기능 명세 페이지가 공개한 패턴은 하나, `WHEN … THE SYSTEM SHALL …`입니다. 항상, *While*, *If / then*, *Where*, 복합은 논문과 Mavin 안내의 표기법에 속합니다. 그 Kiro 페이지에는 없습니다.

## Kiro가 EARS를 쓰는 방식

[Kiro 기능 명세 페이지](https://kiro.dev/docs/specs/feature-specs/)는 2026년 8월 4일 업데이트로 표시되어 있고, 2026년 11월 2일에 읽었습니다. `requirements.md`가 EARS를 쓴다고 합니다. 인쇄된 패턴은 `WHEN [condition/event]` 다음에 `THE SYSTEM SHALL [expected behavior]`입니다. 페이지 예: WHEN a user submits a form with invalid data, THE SYSTEM SHALL display validation errors next to the relevant fields.

[요구사항 우선 페이지](https://kiro.dev/docs/specs/feature-specs/requirements-first/)는 생성된 `requirements.md`가 인수 기준이 있는 사용자 이야기와, 같은 WHEN … THE SYSTEM SHALL … 형태의 시스템 동작을 포함한다고 합니다. 등록 예는 세 문장입니다. 유효한 등록 데이터는 계정을 만들고, 이미 있는 이메일은 “Email already registered”를 보이며, 잘못된 이메일 형식은 검증 오류를 보입니다.

설계 전에 Analyze Requirements가 논리적 불일치, 모호함, 서로 충돌하는 제약, 빈틈을 찾습니다. 기능 명세 페이지는 요구사항을 만든 뒤 채팅 옵션이나 편집기의 Continue 메뉴에서 고른다고 합니다. `design.md`와 `tasks.md`는 요구사항 옆에 둡니다. Quick Spec은 사이에 승인 정지 없이 요구사항, 설계, 과제를 실행합니다.

그 분석은 Kiro 안의 단계입니다. 기능 명세 페이지는 이를 자신의 CI에 넣는 형식 린터로 설명하지 않습니다. 다른 도구가 명세를 어떻게 검사하는지는 [도구 안내](https://specscore.md/ko/spec-driven-development/tools/)에 있습니다. 두 제품의 비교는 [SpecScore vs Kiro](https://specscore.md/ko/vs/kiro/)입니다.

## 같은 요구사항을 SpecScore로

SpecScore는 문장이 EARS 틀에 맞는지는 검사하지 않습니다. [specscore-cli](https://github.com/specscore/specscore-cli) 저장소의 `specscore spec lint`는 구조를 검사합니다. 도움말은 README 파일, Open Questions 절, 제목 수준, 기능 참조, 내부 링크, 색인 항목을 꼽습니다. EARS 문장은 `REQ` 제목 아래 산문이 될 수 있습니다. 린터는 영어를 채점하지 않습니다.

[요구사항 명세](https://specscore.md/requirement-specification)는 각 요구사항을 `## Behavior` 안의 주제 제목 아래, 한 단계 낮게 둡니다. 보통 `#### REQ: slug`입니다. slug는 소문자, 숫자, 하이픈입니다. 식별자는 `{feature-path}#req:{slug}`입니다. 명세는 요구사항이 RFC 2119(Request for Comments 2119) 키워드를 써야 한다고 합니다. MUST, MUST NOT, SHOULD, SHOULD NOT, MAY입니다. 아래 대응에서 EARS의 *shall*은 MUST로 씁니다.

[인수 기준](https://specscore.md/acceptance-criteria-specification)은 선택입니다. 쓸 때는 `## Acceptance Criteria` 안의 `### AC: slug`이고, 다음 줄이 그 식별자를 담은 `**Requirements:**`입니다. 인수 기준 명세는 AC가 추상 조건을 말하며 Given/When/Then 단계, 구체적 입력, 구현 세부 사항을 담아서는 안 된다고 합니다. 구체적 흐름은 기능 `_tests/` 디렉터리의 [시나리오](https://specscore.md/scenario-specification)입니다. [기능 명세](https://specscore.md/feature-specification)는 상태, 요약, 문제, 동작, 인수 기준, 열린 질문, 준수 바닥글도 요구합니다.

아래 파일은 결제 기능 하나입니다. `show-field-error`가 사건 주도 예이고, `reject-invalid-email`이 바라지 않는 동작의 예입니다. 2026년 11월 2일 `specscore spec lint`는 이 트리에 대해, 2026년 10월 30일 발표된 최신 릴리스 specscore 0.55.1과 [dogfood.yml](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml)에 고정된 specscore 0.39.1 모두에서 위반 0건을 보고했습니다. [형식 저장소](https://github.com/specscore/specscore)가 그 워크플로가 있는 곳입니다.

### spec/features/checkout/README.md

```markdown
---
format: https://specscore.md/feature-specification
status: Draft
---

# Feature: Checkout validation

> [SpecScore.**Studio**](https://specscore.studio): | [Explore](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=explore) | [Edit](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=edit) | [Ask question](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=ask) | [Request change](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=request-change) |

**Status:** Draft
**Source Ideas:** —

## Summary

The checkout form shows a validation error next to a field when the shopper submits invalid data, and it rejects an email that is not a valid address.

## Problem

A vague sentence such as "the form should handle bad input" does not say which event causes which response. Checkout needs those obligations written so a reviewer and a linter can point at them.

## Behavior

### Field validation

The checkout system checks the form when the shopper submits it.

#### REQ: show-field-error

When a shopper submits the checkout form with invalid data, the checkout system MUST show a validation error next to the invalid field.

#### REQ: reject-invalid-email

If the submitted email is not a valid address, then the checkout system MUST reject the form.

## Acceptance Criteria

### AC: invalid-submission

**Requirements:** checkout#req:show-field-error, checkout#req:reject-invalid-email

Submitting the checkout form with invalid data shows a validation error next to the invalid field, and an email that is not a valid address is rejected.

## Open Questions

None at this time.

---
*This document follows the https://specscore.md/feature-specification*
```

### spec/features/README.md — 설명 칸은 기능의 요약 문장입니다. 린터의 feature-index-row-sync 규칙은 더 짧은 설명을 거부했습니다.

```markdown
---
format: https://specscore.md/features-index-specification
---

# Features

| Feature | Status | Description |
|---|---|---|
| [Checkout validation](checkout/README.md) | Draft | The checkout form shows a validation error next to a field when the shopper submits invalid data, and it rejects an email that is not a valid address. |

## Open Questions

None at this time.

---
*This document follows the https://specscore.md/features-index-specification*
```

### spec/README.md — Open Questions 절을 빼면 oq-section: Open Questions section not found가 나옵니다.

```markdown
# Checkout specification

## Open Questions

None at this time.
```

### specscore.yaml — project.host, project.org, project.repo가 studio-toolbar 줄과 맞춰 보는 값입니다. 없으면 린터는 studio-toolbar: studio toolbar requires project host/org/repo를 보고했습니다.

```yaml
# SpecScore Repo Config Schema: https://specscore.md/repo-config

project:
  title: Checkout sample
  host: github.com
  org: example
  repo: checkout
```

이 예를 통과시키는 동안 오류가 두 개 더 나왔고, 둘 다 위 파일에서 고쳤습니다. `**Source Ideas:**`가 없는 기능은 `feature-source-ideas-required`로 실패했습니다. 빈 값은 `—`입니다. 기능 색인에는 프론트매터 `format: https://specscore.md/features-index-specification`도 필요했습니다.

린터가 통과한다는 것은 파일이 이 구조 규칙을 지킨다는 뜻입니다. 문장이 좋은 EARS라는 뜻도, 결제 제품이 존재한다는 뜻도 아닙니다. 이 동작의 Given/When/Then은 AC 안의 다른 문단이 아니라 `spec/features/checkout/_tests/` 아래 시나리오 파일입니다.

## 질문

### EARS는 무엇의 약자입니까?

Easy Approach to Requirements Syntax입니다. 요구사항을 위한 문장 패턴 집합으로, Rolls-Royce의 Alistair Mavin, Philip Wilkinson, Adrian Harwood, Mark Novak이 2009년 17th IEEE International Requirements Engineering Conference에서 발표했고 Mavin 사이트에서 설명합니다.

### Kiro 표기법이 EARS 전체입니까?

Kiro 기능 명세 페이지는 패턴 하나를 정합니다. WHEN … THE SYSTEM SHALL …입니다. 2009년 논문과 Mavin 안내는 항상 요구사항, 상태의 While, 바라지 않는 동작의 If/then, 선택 기능의 Where, 그 키워드의 복합도 정의합니다.

### SpecScore가 EARS 구문을 검증합니까?

아닙니다. `specscore spec lint`는 SpecScore 파일 구조를 검증합니다. EARS 문장은 `REQ`의 산문이 될 수 있습니다. 린터는 영어를 채점하지 않습니다.

### Given/When/Then 예는 어디에 둡니까?

기능의 `_tests/` 디렉터리에 있는 시나리오입니다. 인수 기준은 추상 조건으로 남으며, 인수 기준 명세에서는 Given/When/Then 단계를 담아서는 안 됩니다.

## 출처

2026년 11월 2일에 읽었습니다. 페이지가 자신의 업데이트 날짜를 인쇄한 경우는 그 날짜입니다. Kiro 기능 명세 페이지는 2026년 8월 4일 업데이트라고 적혀 있습니다.

- [Mavin, Wilkinson, Harwood, Novak — Easy Approach to Requirements Syntax (EARS), 17th IEEE International Requirements Engineering Conference, 2009, DOI 10.1109/RE.2009.9](https://doi.org/10.1109/RE.2009.9)
- [Alistair Mavin — EARS 안내](https://alistairmavin.com/ears/)
- [Kiro 문서 — 기능 명세와 EARS (페이지 업데이트 2026년 8월 4일)](https://kiro.dev/docs/specs/feature-specs/)
- [Kiro 문서 — 요구사항 우선 흐름](https://kiro.dev/docs/specs/feature-specs/requirements-first/)
- [specscore/specscore — 요구사항 명세](https://github.com/specscore/specscore/blob/main/spec/features/requirement/README.md)
- [specscore/specscore — 인수 기준 명세](https://github.com/specscore/specscore/blob/main/spec/features/acceptance-criteria/README.md)
- [specscore/specscore — 시나리오 명세](https://github.com/specscore/specscore/blob/main/spec/features/scenario/README.md)
- [specscore/specscore — 기능 명세](https://github.com/specscore/specscore/blob/main/spec/features/feature/README.md)
- [specscore/specscore — dogfood CI 워크플로](https://github.com/specscore/specscore/blob/main/.github/workflows/dogfood.yml)
- [specscore/specscore-cli](https://github.com/specscore/specscore-cli)
- [specscore/specscore](https://github.com/specscore/specscore)

## 관련

- [AI 코딩을 위한 Markdown PRD 템플릿](https://specscore.md/ko/articles/feature-spec-template/)
- [CI에서 명세 린터로 명세를 린트하기](https://specscore.md/ko/articles/lint-specs-in-ci/)
- [AI 에이전트가 검증할 수 있는 인수 기준을 쓰는 법](https://specscore.md/ko/articles/acceptance-criteria/)
- [SpecScore vs Kiro](https://specscore.md/ko/vs/kiro/)
- [명세 주도 개발 도구](https://specscore.md/ko/spec-driven-development/tools/)
- [명세 주도 개발](https://specscore.md/ko/spec-driven-development/)
- [요구사항 명세](https://specscore.md/requirement-specification)
- [인수 기준 명세](https://specscore.md/acceptance-criteria-specification)
- [기능 명세](https://specscore.md/feature-specification)
- [검증기와 CI](https://specscore.md/ko/validators/)
