기능성 설명으로 제시된 ‘사용되는 자원의 양에 따라 적절한 성능을 제공하는 능력’은 효율성(efficiency)의 정의이므로 옳지 않다.
ISO/IEC 9126에서 기능성은 명시된 요구를 만족하는 기능을 제공하는 능력으로, 적합성·정확성·상호운용성·보안성 등을 하위 특성으로 둔다.
- 이식성: 다른 환경으로 옮겨져도 적응·설치될 수 있는 능력으로 옳다.
- 사용성: 이해·학습·사용이 쉬운 정도로 옳다.
- 신뢰성: 정해진 조건에서 성능 수준을 유지하는 능력으로 옳다.
○ 만약 프로젝트가 실패하거나 오류가 발생할 경우, 대규모 예산 낭비뿐만 아니라 국민 건강과 직결되는 심각한 위험(risk)이 도사리고 있다.
○ 따라서 단번에 시스템을 완성하기보다는 주기마다 [목표 결정→위험 분석→개발 및 평가→다음 단계 계획]의 4가지 활동을 반복하며 점진적으로 완성도를 높여 가야 한다.
요구사항이 불확실하고 위험이 크며 [목표 결정→위험 분석→개발 및 평가→다음 단계 계획]을 반복하는 구조는 나선형(spiral) 모델이다.
나선형 모델은 매 주기마다 위험 분석을 수행해 위험을 줄이며 점진적으로 시스템을 완성하므로 대규모·고위험 프로젝트에 적합하다.
- 폭포수 모델: 요구사항을 초기에 확정하고 단계를 순차 진행하므로 불확실한 요구에 부적합하다.
- 컴포넌트 기반 개발 모델: 기존 컴포넌트의 조립·재사용이 핵심으로, 위험 분석의 반복과는 무관하다.
- V 모델: 개발 단계와 테스트 단계를 대응시킨 폭포수의 확장형으로, 반복적 위험 관리를 특징으로 하지 않는다.
품질(성능·신뢰성·보안 등)은 비기능 요구사항에 속하므로, 기능 요구사항이 품질을 포함한다는 설명이 옳지 않다.
기능 요구사항은 시스템이 무엇을 수행하는지(입력·처리·출력)를 정의하고, 비기능 요구사항은 그 기능을 얼마나 잘 수행해야 하는지에 대한 품질 속성과 제약을 정의한다.
- 요구분석은 구현 방법(how)이 아니라 시스템이 할 일(what)에 초점을 두므로 옳다.
- 신뢰성은 믿고 사용할 수 있는 정도, 정확성은 사용자 요구·명세와 일치하는 정도로 옳다.
- 가용성은 으로 계산하므로 옳다.
지문은 스프린트 단위 반복과 변화 대응을 강조하는 애자일(스크럼) 방법론이므로, 모든 설계 결정을 초기에 고정하고 변경을 최소화한다는 설명이 옳지 않다.
설계를 초기에 확정하고 변경을 통제하는 방식은 계획 중심(폭포수형) 방법론의 특징이며, 애자일은 계획을 따르기보다 변화에 대응하는 것을 중시한다.
- 변화 수용과 고객과의 지속적 협업은 애자일 선언의 핵심 가치로 옳다.
- 반복 주기마다 기능을 점진적으로 추가·배포하는 것은 스프린트 방식과 일치한다.
- 포괄적인 문서보다 작동하는 소프트웨어를 중시하는 것도 애자일 선언의 가치이다.
(나) 단일 도서 객체가 시스템에 등록되어 대출 가능, 대출 중, 예약됨, 파손 및 폐기에 이르기까지 발생하는 외부 이벤트에 의해 객체 내부가 어떻게 전이되는지를 모델링한다.
(다) 사용자가 도서를 반납할 때 연체료 계산 처리와 반납 완료 안내 이메일 발송 처리가 동시에 병렬로 실행되고, 두 작업이 모두 완료된 후 다음 단계로 합쳐지는 전체적인 비즈니스 업무 흐름을 시각적으로 도식화한다.
B. 유스케이스 다이어그램(use case diagram)
C. 활동 다이어그램(activity diagram)
D. 상태 다이어그램(state diagram)
(가) (나) (다)
(가)는 순차, (나)는 상태, (다)는 활동 다이어그램이므로 A–D–C로 연결된다.
(가)는 객체 간 메시지 호출과 응답을 시간 순서로 표현하고, (나)는 한 객체가 외부 이벤트에 따라 상태를 전이하는 과정을 표현한다. (다)는 병렬 분기(fork)와 합류(join)를 포함한 업무 흐름이므로 활동 다이어그램이다.
- B–C–A: 메시지 상호작용인 (가)를 유스케이스 다이어그램으로 본 것부터 틀리다.
- C–D–A: (가)를 활동, (다)를 순차 다이어그램으로 뒤바꿨다.
- A–C–B: 상태 전이인 (나)를 활동으로, 업무 흐름인 (다)를 유스케이스 다이어그램으로 연결해 틀리다.
○ 기능: 사용자 로그인
○ 설명: 사용자는 로그인 단계에서 아이디와 비밀번호를 입력하여 로그인한다.
○ 제약조건: 비밀번호는 반드시 8자 이상이어야 하며, 대문자, 소문자와 숫자를 포함해야 한다.
설명 항목은 아이디와 비밀번호로 로그인한다는 무엇(what)을 기술할 뿐 구현 방법을 상세히 기술하지 않으므로 옳지 않다.
요구사항 명세는 시스템이 제공할 기능과 제약을 정의하는 문서이며, 암호화 방식이나 조회 절차 같은 구현 방법(how)은 설계 단계에서 다룬다.
- 요구사항 ID는 각 요구사항을 구분·추적하는 유일 식별자로 옳다.
- 기능 항목은 ‘사용자 로그인’처럼 핵심 기능을 서술하므로 옳다.
- 제약조건은 비밀번호 길이·문자 구성 같은 제한사항을 명확히 하므로 옳다.
void test(int x) {
int y;
String str;
if(x >= 90){
y = 100;
str = "Pass";
}
else{
str = "Not Yet";
if(x >= 80){
y = 80;
str = str + ": Try Again";
}
else
y = 50;
}
}기본경로 테스트 케이스 수는 순환 복잡도와 같으며, 이 코드의 순환 복잡도는 3이다.
결정문은 x≥90 판단과 x≥80 판단의 2개이므로 결정문 수에 1을 더한다.
독립 경로는 x≥90인 경로, 80≤x<90인 경로, x<80인 경로의 세 가지이다.
- 1개: 한 경로만 실행되어 나머지 두 독립 경로가 검증되지 않는다.
- 2개: 독립 경로 하나가 누락된다.
- 4개: 존재하는 독립 경로 수보다 많다.
int global_i;
void write_i (int x) {
global_i = x;
}
int read_i () {
return global_i;
}
int main() {
int ret;
write_i(4);
ret = read_i();
return 0;
}
두 함수가 전역 변수 global_i를 함께 쓰고 읽으므로 공통 결합(common coupling)이다.
공통 결합은 여러 모듈이 전역 데이터 영역을 공유할 때 발생하며, 한 모듈의 전역 변수 변경이 다른 모듈에 영향을 주어 결합도가 높다.
- 데이터 결합: 매개변수로 단순 데이터만 주고받는 경우로, 두 함수는 서로 값을 직접 전달하지 않는다.
- 스탬프 결합: 구조체·레코드 같은 자료구조를 매개변수로 전달하는 경우로 해당하지 않는다.
- 내용 결합: 한 모듈이 다른 모듈의 내부 코드나 지역 데이터를 직접 참조·변경하는 경우로 해당하지 않는다.
(나) 적응 유지보수(adaptive maintenance)
(다) 완전 유지보수(perfective maintenance)
(라) 예방 유지보수(preventive maintenance)
B. 기존 시스템을 새로운 자료나 운영체제, 하드웨어 환경으로 이식하기 위한 유지보수
C. 발견된 오류나 결함의 원인을 찾아 문제를 해결하는 유지보수
D. 장차 발생할 수 있는 오류나 성능 저하에 대비하여 사전에 방지하기 위한 유지보수
(가) (나) (다) (라)
수정은 C, 적응은 B, 완전은 A, 예방은 D에 대응하므로 C–B–A–D가 옳다.
수정 유지보수는 발견된 결함을 고치는 것이고, 적응 유지보수는 운영체제·하드웨어 등 환경 변화에 맞춰 이식하는 것이다. 완전 유지보수는 정상 작동 중에도 성능·품질을 개선하는 것이며, 예방 유지보수는 장래의 오류에 대비해 미리 방지하는 것이다.
- A–D–B–C: 수정 유지보수를 품질 개선으로, 예방 유지보수를 결함 수정으로 연결해 틀리다.
- A–D–C–B: 완전 유지보수를 결함 수정으로, 예방 유지보수를 환경 이식으로 연결해 틀리다.
- C–A–B–D: 적응 유지보수와 완전 유지보수의 설명을 뒤바꿨다.
(나) 신규 사용자는 2시간 이내의 교육으로 주요 기능을 사용할 수 있어야 한다.
(다) 시스템의 평균 고장 간격은 1,000시간 이상이어야 한다.
(라) 장애 발생 후 시스템은 30초 이내에 재시작되어야 한다.
(마) 시스템은 최소 3개의 대상 운영환경에서 실행될 수 있어야 한다.
(가) (나) (다) (라) (마)
순서대로 속도–사용성–신뢰성–견고성–이식성이다.
응답시간은 속도, 교육 시간은 사용성, 운영환경 수는 이식성의 척도이다. 평균 고장 간격은 고장 없이 동작하는 정도이므로 신뢰성, 장애 후 재시작 시간은 고장에서 회복하는 능력이므로 견고성의 척도이다.
- 신뢰성–사용성–속도–견고성–이식성: 응답시간을 신뢰성으로, 고장 간격을 속도로 뒤바꿨다.
- 속도–신뢰성–사용성–이식성–견고성: 교육 시간을 신뢰성, 고장 간격을 사용성으로 보고 재시작 시간과 운영환경 수의 속성도 뒤바꿨다.
- 속도–사용성–견고성–신뢰성–이식성: 고장 간격과 재시작 시간의 속성을 뒤바꿨다.
○ 고객(Customer)과 주문(Order) 클래스는 (가):(나) 관계이다. 하나의 고객은 여러 번 주문할 수 있으며, 아직 단 한 번도 주문하지 않은 신규 가입 고객도 시스템에 존재할 수 있다. 특정 주문은 오직 하나의 고객에게만 종속된다.
○ 주문(Order)과 주문품목(OrderItem) 클래스는 (다):(라) 관계이다. 하나의 주문에는 반드시 하나 이상의 주문품목이 포함되어야 하며, 특정 주문품목은 오직 하나의 주문 번호에만 종속된다.
(가) (나) (다) (라)

고객–주문은 1 : 0..*, 주문–주문품목은 1 : 1..* 로 표기하는 조합이 옳다.
다중성은 상대 클래스 쪽 끝에 적는다. 주문은 오직 한 고객에 종속되므로 고객 쪽은 1, 한 고객은 주문이 없을 수도 여러 개일 수도 있으므로 주문 쪽은 0..* 이다. 한 주문에는 주문품목이 반드시 하나 이상 있으므로 주문품목 쪽은 1..*, 주문품목은 한 주문에만 속하므로 주문 쪽은 1 이다.
- 주문 쪽을 1..* 로 둔 조합은 한 번도 주문하지 않은 신규 고객이 존재할 수 있다는 규칙을 반영하지 못한다.
- 고객 쪽을 1..* 로 둔 조합은 하나의 주문이 여러 고객에 속하는 것이 되어 규칙과 반대이다.
- 고객 쪽을 0..* 로 두고 주문품목 쪽을 1 로 둔 조합은 방향이 뒤바뀌어 주문이 고객 없이 존재하고 주문에 품목이 하나뿐인 것으로 된다.
(나) 소프트웨어 서브 시스템의 모듈 간 연관 관계와 이들이 어떻게 연결되는지에 초점을 둔다.
(다) 시스템의 기능을 제공하기 위해 필요한 클래스, 컴포넌트 및 이들의 관계에 초점을 둔다.
(라) 독자적인 제어 스레드를 가질 수 있는 클래스에 집중하며, 시스템의 동시성과 동기화에 초점을 둔다.
(가) (나) (다) (라)

(가)~(라)는 차례로 배치·구현·논리적·프로세스 관점이다.
4+1 뷰는 유스케이스 관점을 중심에 두고 네 관점을 둘러 배치한다. 처리 장치 간 물리적 배치는 배치 관점(배치 다이어그램), 서브시스템 모듈의 연결은 구현 관점(컴포넌트 다이어그램), 기능 제공에 필요한 클래스와 관계는 논리적 관점(클래스 다이어그램), 제어 스레드와 동시성·동기화는 프로세스 관점(순차 다이어그램 등 동적 표현)에 해당한다.
- (가)를 구현 관점으로 본 연결은 물리적 하드웨어 배치를 다루는 배치 관점과 모듈 구성을 다루는 구현 관점을 혼동한 것이다.
- (나)를 논리적 관점, (다)를 프로세스 관점으로 본 연결은 모듈 연결과 클래스 구조, 동시성의 대응을 모두 어긋나게 짝지은 것이다.
- (나)를 프로세스 관점, (라)를 구현 관점으로 본 연결은 동시성·동기화가 프로세스 관점의 관심사라는 점과 맞지 않는다.
Shape p1 = new Rectangle();
Shape p2 = new Triangle();
p1.getArea();
p2.getArea();

p1.getArea()는 Rectangle의 메서드가, p2.getArea()는 Triangle의 메서드가 실행된다 — 오버라이딩과 동적 바인딩의 결과이다.
다이어그램에서 getArea()는 Shape에 선언되어 있고 두 하위 클래스가 이를 재정의한다. 참조 변수의 타입이 Shape여도 호출될 메서드는 실행 시점의 실제 객체 타입으로 결정되므로 각 하위 클래스의 구현이 호출된다.
- getArea()가 하위 클래스에만 있어 컴파일 오류가 난다는 설명은 틀렸다. Shape에도 선언되어 있으므로 Shape 타입 참조로 호출할 수 있다.
- 두 호출 모두 Shape의 getArea()가 실행된다는 설명은 정적 바인딩을 가정한 것으로, 재정의된 메서드는 실제 객체의 것이 실행된다.
- 상속받기 때문에 각 하위 클래스의 getArea()가 실행되지 않는다는 설명은 재정의 메서드가 상위 메서드를 대체한다는 점과 반대이다.
E-R 다이어그램은 개체와 관계로 데이터를 표현하는 데이터 모델링 기법이므로 객체지향 방법이라는 설명이 옳지 않다.
E-R 다이어그램은 개체·속성·관계를 표기할 뿐 클래스·상속·메서드 같은 객체지향 개념을 표현하지 않으며, 구조적 분석에서 데이터 사전과 함께 쓰인다.
- 자연어 모델링은 이해하기 쉽지만 모호성 때문에 해석이 갈릴 수 있어 옳다.
- 형식 언어는 수학적 표기로 복잡한 요구를 간결·정확하게 표현할 수 있어 옳다.
- DFD는 데이터 흐름과 처리를 표현하는 구조적 분석 도구로 옳다.
각 개별 조건이 다른 조건과 무관하게 전체 결정 결과에 독립적으로 영향을 주도록 설계하는 것은 변경 조건/결정 커버리지(MC/DC)이므로, 이를 조건/결정 커버리지로 설명한 것이 옳지 않다.
조건/결정 커버리지는 각 개별 조건의 참·거짓과 전체 결정문의 참·거짓이 모두 최소 한 번씩 나오도록 하는 기준이다.
- 기본경로 테스트: 독립 경로를 최소 한 번씩 실행하도록 설계하므로 옳다.
- 다중조건 커버리지: 조건의 참·거짓 모든 조합을 실행하므로 옳다.
- 조건 커버리지: 각 조건의 참·거짓을 최소 한 번씩 실행하므로 옳다.

Vector처럼 크기가 변하는 객체 집합에는 적용할 수 없다는 설명이 옳지 않다. Iterator 패턴은 집합의 내부 구조와 무관하게 순회 방법을 제공하는 것이 목적이다.
Client는 Aggregate의 createIterator()로 Iterator를 얻고 hasNext()·getNext()로 순회하므로, 배열·리스트·가변 크기 컬렉션 어느 쪽이든 ConcreteIterator만 맞게 구현하면 적용된다. 실제로 Java의 Vector도 Iterator를 제공한다.
- 복합 객체의 내부 구조를 노출하지 않고 요소에 순차 접근하게 한다는 설명은 Iterator 패턴의 의도 그대로이다.
- Aggregate 인터페이스가 createIterator()를 선언해 Client가 Iterator를 생성할 수 있게 한다는 설명은 다이어그램과 맞다.
- ConcreteAggregate가 알맞은 ConcreteIterator 인스턴스를 반환하는 생성 인터페이스를 구현한다는 설명도 옳다. 메모처럼 createIterator()는 factory method 역할을 한다.
interface Member{ void printType(); }
class Student implements Member {
public void printType()
{ System.out.println("Student"); }
}
class Staff implements Member {
public void printType()
{ System.out.println("Staff"); }
}
class Professor implements Member {
public void printType()
{ System.out.println("Professor"); }
}
class MemberGenerator {
public Member newMember(String memberType){
if(memberType.equals("Student"))
return new Student();
else if(memberType.equals("Staff"))
return new Staff();
else if(memberType.equals("Professor"))
return new Professor();
return null;
}
}MemberGenerator가 문자열에 따라 알맞은 Member 구현 객체를 생성해 반환하므로 factory method 패턴이고, Student와는 의존 관계이다.
MemberGenerator는 Student를 필드로 보유하지 않고 newMember() 안에서 일시적으로 생성해 반환만 하므로, 지속적 참조인 연관이 아니라 사용 관계인 의존에 해당한다.
- singleton 패턴–연관 관계: 인스턴스를 하나로 제한하는 구조가 없고, Student를 필드로 참조하지도 않는다.
- singleton 패턴–의존 관계: private 생성자나 정적 인스턴스가 없어 singleton이 아니다.
- factory method 패턴–연관 관계: Student를 멤버 변수로 보유하지 않으므로 연관이 아니다.
신속한 경보(성능)를 위해 핵심 연산을 소수의 컴포넌트에 집중하고, 변경이 잦은 기능을 작고 독립적인 컴포넌트로 나누는 설계가 옳다.
성능은 컴포넌트 간 통신을 줄일수록 높아지고, 유지보수성은 변경 영향이 국소화되는 작고 독립적인 컴포넌트에서 높아진다.
- 경보 연산을 다수 컴포넌트에 분산하면 상호 통신 부담으로 응답이 느려진다.
- 안전 관련 기능은 분산하지 않고 소수의 컴포넌트에 모아야 검증과 보호가 쉽다.
- 가용성은 컴포넌트 중복(이중화)으로 높이며, 공유 데이터 구조는 변경 파급을 키워 유지보수성을 떨어뜨린다.
지속적 배포에서 릴리스와 설치의 설명이 뒤바뀌어 옳지 않다.
릴리스는 배포 가능한 소프트웨어 패키지를 작성하는 단계이고, 설치는 서버 자원을 할당하고 인프라를 구성해 사용자에게 서비스를 여는 단계이다.
- 지속적 통합은 여러 개발자의 코드를 자주 통합·빌드·검증하는 프로세스로 옳다.
- 데브옵스는 자동화 테스트 도구로 코드 품질을 유지하므로 옳다.
- 데브옵스는 운영 중 지속적 모니터링과 신속한 대응을 강조하므로 옳다.
void method(int x, int y, int z) {
if (x > 20 && y == 5) {
x = 10;
z = 5;
}
if (x == 10 || z % 2 == 0) {
z += 10;
}
}단축 연산 없이 네 조건의 참·거짓 8가지를 세면, (x=10, y=10, z=4)와 (x=5, y=5, z=3)의 조합이 7가지를 충족해 가장 크다.
조건은 x>20, y==5, x==10, z%2==0이며, 두 번째 if는 첫 번째 if 실행 후의 x·z 값으로 평가한다.
(10,10,4): 거짓, 거짓, 참, 참
(5,5,3): 거짓, 참, 거짓, 거짓
x>20만 거짓 하나뿐이고 나머지 세 조건은 참·거짓이 모두 나온다.
- (x=25, y=5, z=3), (x=8, y=5, z=3): 첫 입력이 x=10, z=5로 바뀌어 z%2==0은 거짓만, y==5는 참만 나와 6가지이다.
- (x=10, y=10, z=4) 단독: 각 조건이 한 값씩만 나와 4가지이다.
- (x=25, y=5, z=3), (x=10, y=5, z=3), (x=5, y=5, z=1): y==5는 참만, z%2==0은 거짓만 나와 6가지에 그친다.
public class Employee {
public static final int EMP1 = 0;
public static final int EMP2 = 1;
public static final int EMP3 = 2;
private int empType;
public Employee(int empType) {
this.empType = empType;
}
public int paySalary() {
switch (empType) {
case EMP1:
return 5000;
case EMP2:
return 6000;
case EMP3:
return 9000;
default:
throw new IllegalArgumentException(
"Invalid employee type");
}
}
}이 코드의 스멜은 타입 코드에 따른 switch 문 분기이며, 여러 데이터 항목이 늘 함께 다니는 데이터 뭉치(data clumps)는 나타나지 않으므로 옳지 않다.
data clumps는 같은 매개변수·필드 묶음이 여러 곳에 반복되는 스멜인데, 이 코드는 empType 하나의 값으로 분기할 뿐이다. 해결책은 조건문을 다형성으로 바꾸기이다.
- 새 직원 유형이 생길 때마다 switch 문을 고쳐야 하므로 버그 가능성이 커진다는 설명은 옳다.
- empType별 서브클래스로 분리하고 paySalary()를 재정의하는 리팩토링은 옳다.
- 확장 시 기존 코드를 수정해야 하므로 OCP 위반이라는 설명은 옳다.
<표 1> 기능별 개수 및 평균 복잡도
| 기능 유형 | 개수 | 평균 복잡도 |
|---|---|---|
| 외부입력 | 15 | 4.0 |
| 외부출력 | 5 | 5.2 |
| 외부조회 | 12 | 3.9 |
| 내부 논리 파일 | 4 | 7.5 |
| 외부 인터페이스 파일 | 2 | 5.4 |
| 사업규모(FP) | 1인 생산성(FP/MM) |
|---|---|
| 1,000 미만 | 19 |
| 1,000 이상 ~ 2,000 미만 | 22 |
| 2,000 이상 ~ 3,000 미만 | 24 |
| 3,000 이상 | 22 |
기능점수에 보정 계수 1.5를 곱하고 1인 생산성으로 나누면 평균 노력은 약 13.71 MM이다.
기능점수는 유형별 개수와 평균 복잡도의 곱을 합한다.
보정 후 규모는 로 1,000 FP 미만이므로 생산성 19 FP/MM을 적용한다.
- 약 9.14 MM: 보정 계수를 적용하지 않고 173.6을 19로 나눈 값이다.
- 약 0.25 MM: 계산 결과보다 지나치게 작아 성립하지 않는다.
- 약 17.27 MM: 계산 결과보다 커서 성립하지 않는다.
정의(defined) 수준은 조직 표준 프로세스를 정의하고 이를 프로젝트에 맞게 조정해 쓰는 단계이므로, 표준 프로세스가 없다는 설명이 옳지 않다.
프로젝트별로만 프로세스를 관리하는 것은 그 아래 관리(managed) 수준의 특징이다.
- CMMI는 개발·서비스·획득 등 여러 도메인에 적용되는 프로세스 개선 프레임워크로 옳다.
- 단계적 표현은 성숙도 수준, 연속적 표현은 역량 수준으로 평가하므로 옳다.
- 협력업체 계약 관리는 관리 수준의 프로세스 영역으로 옳다.
ISO/IEC 25000(SQuaRE)은 9126과 14598을 통합한 것은 맞지만 5개 영역으로 구성되므로 4개 영역이라는 설명이 옳지 않다.
SQuaRE는 품질 모델·품질 측정 영역 외에도 품질 관리, 품질 요구, 품질 평가 영역을 포함한다.
- ISO/IEC 9126은 내부·외부·사용 품질로 구성되고 여섯 가지 품질 특성을 정의하므로 옳다.
- ISO/IEC 14598은 제품 품질 평가의 절차와 방법을 정의한 표준으로 옳다.
- ISO/IEC 12119는 패키지 소프트웨어의 품질 요구사항과 테스트 지침을 정의하므로 옳다.
| 작업 | 소요 기간 | 선행 작업 |
|---|---|---|
| A | 4일 | 없음 |
| B | 3일 | A |
| C | 6일 | A |
| D | 4일 | A |
| E | 6일 | B |
| F | 4일 | C, D |
| G | 5일 | E, F |
| H | 3일 | D |
| I | 4일 | G, H |
작업 D는 여유 시간이 2일뿐이므로 3일 지연되면 프로젝트 완료가 1일 늦어져, 지연되지 않는다는 설명이 옳지 않다.
전진 계산하면 A(0~4), C(4~10), D(4~8), F(10~14), G(14~19), I(19~23)로 최소 완료 기간은 23일이다. 후진 계산에서 D의 가장 늦은 종료는 F의 가장 늦은 시작인 10일이므로 여유는 2일이다.
D가 7일이 되면 D 종료 11일 → F 11~15 → G 15~20 → I 20~24로 24일이 된다.
- 임계 경로 A→C→F→G→I와 최소 완료 기간 23일은 옳다.
- B의 여유가 1일이므로 2일 지연되면 A→B→E→G→I가 24일로 늘어나 임계 경로가 바뀐다는 설명은 옳다.
- H는 가장 이른 시작 8일, 가장 늦은 시작 16일로 여유 8일이며 B·E(1일), D(2일)보다 커 옳다.