애자일은 요구사항 변화가 잦은 소규모·중규모 개발에 적합하므로, 변화가 적은 대규모 시스템에 적합하다는 설명이 옳지 않다.
요구사항이 안정적이고 규모가 큰 시스템은 계획·문서 중심의 폭포수형 전통 방법론이 더 잘 맞는다.
- 포괄적인 문서보다 작동하는 소프트웨어를 중시하는 것은 애자일 선언의 가치이다.
- 프로세스와 도구보다 개인과 상호작용을 중시하는 것도 애자일 선언의 가치이다.
- XP와 DSDM은 모두 대표적인 애자일 방법론이다.
클라이언트가 구체 클래스에 의존해야 한다는 설명이 옳지 않다. 의존 역전 원칙(DIP)은 추상 클래스나 인터페이스에 의존하라고 요구한다.
구체 클래스에 직접 의존하면 구현이 바뀔 때마다 클라이언트도 수정해야 하므로, 추상화에 의존해 결합을 느슨하게 만든다.
- 확장에는 열리고 변경에는 닫혀야 한다는 것은 개방-폐쇄 원칙(OCP)이다.
- 상위 타입 객체를 하위 타입 객체로 교체해도 동작해야 한다는 것은 리스코프 치환 원칙(LSP)이다.
- 범용 인터페이스 하나보다 특화된 여러 인터페이스로 나누라는 것은 인터페이스 분리 원칙(ISP)이다.
워크스루를 문서 분석 기법으로 설명한 것이 옳지 않다. 업무 문서를 분석하는 기법은 문서 분석(자료 조사)이다.
워크스루는 작성자가 산출물을 설명하고 검토자들이 따라가며 오류를 찾는 비공식 검토 기법이다.
- 인터뷰는 사용자·이해관계자와의 직접 대화로 요구사항을 추출한다.
- JAD는 관리자·사용자·개발자가 함께 모여 집중 토론하는 기법이다.
- 관찰은 사용자가 실제 수행하는 활동을 살펴보는 기법이다.
(나) 모듈 내부에 존재하는 구성 요소 사이의 밀접한 정도를 나타내는 용어이다. 밀접한 정도가 높을수록 필요한 구성 요소만 모여 있고, 낮을수록 서로 관련성이 적은 구성 요소들이 모여 있다.
(가)는 결합도(coupling), (나)는 응집도(cohesion)이다.
모듈 사이의 의존 정도는 결합도로, 모듈 내부 구성 요소의 밀접한 정도는 응집도로 나타낸다. 좋은 설계는 결합도는 낮고 응집도는 높다.
- (가)를 응집도로 본 조합은 모듈 간 관계와 모듈 내부 관계를 뒤바꾼 것이다.
- 성숙성은 품질 특성(신뢰성의 하위 특성) 용어로, 모듈 내부의 밀접도를 뜻하지 않는다.
컴포넌트가 정적으로 바인딩되어 실행 시간에 인터페이스로 접근할 수 없다는 설명이 옳지 않다. 컴포넌트는 실행 시간에 인터페이스를 통해 동적으로 연결·접근된다.
그래서 컴포넌트는 내부 구현을 숨긴 채 독립적으로 교체·배포할 수 있다.
- 컴포넌트 기반 개발은 재사용 가능한 컴포넌트를 조립해 소프트웨어를 만드는 방법론이다.
- 컴포넌트는 독립적이고 교체 가능한 부품이다.
- 컴포넌트는 인터페이스를 통해 다른 컴포넌트와 연결된다.
ㄴ. 폭포수 모델의 변형으로 테스트 단계를 추가 확장한 것이다.
ㄷ. 폭포수 모델이 산출물 중심이라면, V 모델은 각 개발 단계를 검증하는 데 초점을 둔다.
ㄱ, ㄴ, ㄷ이 모두 옳다.
V 모델은 폭포수 모델을 변형해 각 개발 단계에 대응하는 테스트 단계를 짝지어 둔 모델이다.
- ㄱ: 요구사항 분석 단계에 대응하는 인수 테스트를 포함한다.
- ㄴ: 폭포수 모델에서 테스트 단계를 확장한 변형이다.
- ㄷ: 산출물 중심인 폭포수와 달리 각 개발 단계를 검증·확인하는 데 초점을 둔다.
정의(defined) 단계를 개발 과정이 임시방편·무질서한 단계로 설명한 것이 옳지 않다. 그것은 초기(initial) 단계의 특징이다.
정의 단계는 조직 차원의 표준 프로세스가 정의되어 프로젝트들이 이를 맞춤 적용하는 단계이다.
- 관리 단계는 프로젝트 단위로 비용·일정·기능을 추적·관리한다.
- 정량적 관리 단계는 프로세스와 제품 품질을 정량적으로 측정·통제한다.
- 최적화 단계는 정량적 피드백과 신기술로 프로세스를 지속적으로 개선한다.
○ OMG(Object Management Group)의 CORBA는 이 아키텍처의 대표적인 사례이다.
설명에 해당하는 아키텍처 패턴은 브로커(broker) 패턴이다.
브로커가 분리된 컴포넌트 사이의 원격 서비스 호출을 중개하며, CORBA가 대표 사례이다.
- MVC는 데이터(모델)·화면(뷰)·입력 처리(컨트롤러)를 분리하는 패턴이다.
- 계층 패턴은 시스템을 상하위 계층으로 나누어 각 계층이 아래 계층의 서비스를 이용한다.
- 파이프 필터는 데이터를 필터들이 차례로 변환하며 파이프로 넘기는 패턴이다.
(나) 기존 비대면 수업 등록 기능에서 발생한 오류 사항을 수정하고자 한다.
(가)는 적응(adaptive) 유지보수, (나)는 수정(corrective) 유지보수이다.
DBMS 같은 외부 환경이 바뀌어 프로그램을 맞추는 것은 적응 유지보수이고, 기존 기능의 오류를 고치는 것은 수정 유지보수이다.
- 예방 유지보수는 장래의 문제를 막으려 미리 구조를 개선하는 것으로, 어느 쪽에도 해당하지 않는다.
- 완전(perfective) 유지보수는 새 기능 추가나 성능 개선으로, 오류 수정이나 환경 변화 대응과 다르다.
설명은 블랙박스 테스트이며, 자료 흐름(data flow) 테스트는 여기에 해당하지 않는다.
자료 흐름 테스트는 변수의 정의와 사용 위치를 따라 경로를 고르는 화이트박스 테스트이다.
- 경곗값 분석은 입력 범위의 경계 부근 값을 시험하는 블랙박스 기법이다.
- 동등분할은 입력을 같은 결과를 내는 클래스로 나누어 대표값을 시험하는 블랙박스 기법이다.
- 원인-결과 그래프는 입력 조건과 출력의 관계를 그래프로 분석하는 블랙박스 기법이다.
메모리를 400 MB 이내로 사용해야 한다는 것이 비기능적 요구사항이다.
비기능적 요구사항은 시스템이 무엇을 하는지가 아니라 성능·자원 사용·보안 같은 제약과 품질을 규정한다.
- 남은 쿠킹 시간을 계산해 표시하는 것은 시스템이 수행할 기능이다.
- 문서의 음절·단어·문장 수를 분석해 표로 보여 주는 것은 기능 요구사항이다.
- 특정일 예약 고객 리스트를 출력하는 것도 기능 요구사항이다.
일관성 항목을 모순·충돌이 존재하는가로 설명한 것이 옳지 않다. 일관성은 요구사항 간 모순이나 충돌이 없는가를 검증한다.
검증 항목은 모두 바람직한 상태를 확인하는 질문이므로, 일관성도 충돌이 없음을 확인해야 한다.
- 완전성은 사용자 요구사항이 빠짐없이 반영되었는지 확인한다.
- 추적성은 개발 결과와 요구사항의 일치를 추적·검증할 수 있는지 확인한다.
- 명확성은 명세가 모호하지 않고 간결·명쾌한지 확인한다.
○ study()와 credit() 메서드는 각각 200라인 정도지만, 두 메서드는 100라인 정도가 중복되어 있다.
해결 기법은 메서드 추출(extract method)이다.
지나치게 긴 메서드와 중복 코드는 일부 코드를 별도 메서드로 뽑아내 나누고, 중복 부분을 공통 메서드로 만들어 호출하면 해결된다.
- 위임 숨기기는 클라이언트가 위임 객체를 직접 호출하지 않도록 중간 메서드를 두는 기법이다.
- 중개자 제거는 단순 위임만 하는 메서드를 없애고 직접 호출하게 하는 기법이다.
- 클래스 인라인화는 하는 일이 거의 없는 클래스를 다른 클래스에 합치는 기법이다.
나선형 모델의 반복 활동과 가장 거리가 먼 것은 유지보수이다.
나선형 모델은 각 회전마다 목표 결정 → 위험 분석·해결 → 개발·검증 → 다음 단계 계획을 반복한다.
- 개발은 각 회전에서 산출물을 만들고 검증하는 활동이다.
- 리스크 식별 및 해결은 나선형 모델의 핵심 활동이다.
- 목표 정의는 각 회전의 첫 활동이다.
설명에 해당하는 테스트는 회귀(regression) 테스트이다.
변경 후 기존 기능에 부작용이 생기지 않았는지 이미 쓴 테스트 케이스를 재실행해 확인한다.
- 베타 테스트는 실제 사용자가 자신의 환경에서 수행하는 인수 테스트이다.
- 스트레스 테스트는 한계 이상의 부하를 주어 시스템의 견딤을 확인한다.
- 신뢰성 테스트는 일정 기간 고장 없이 동작하는지를 확인한다.
스프린트를 인덱스 카드에 기능을 간략히 서술한 것으로 설명한 것이 옳지 않다. 그것은 사용자 스토리에 대한 설명이다.
스프린트는 보통 2~4주 정도의 고정된 반복 개발 주기로, 그 안에서 동작하는 증분을 만든다.
- 매일 15분 정도의 일일 스크럼 회의를 한다.
- 제품 백로그는 제품 요구사항을 우선순위로 정리한 목록이다.
- 반복 개발로 사용자 요구사항을 지속적으로 반영한다.
public class DesignManager {
private DesignManager() { }
private static DesignManager _instance = null;
public synchronized
static DesignManager Instance() {
if (_instance == null)
_instance = new DesignManager();
return _instance;
}
}코드에 적용된 패턴은 싱글톤(singleton)이다.
생성자를 private으로 막고, static 메서드가 유일한 인스턴스를 처음 한 번만 만들어 계속 반환한다.
- 데코레이터는 객체를 감싸 동적으로 기능을 덧붙이는 구조 패턴이다.
- 반복자는 내부 구조를 드러내지 않고 원소를 순회하는 행위 패턴이다.
- 옵서버는 상태 변화를 등록된 객체들에 통지하는 행위 패턴이다.

상자가 인형 또는 상자를 반드시 하나 이상 포함해야 한다는 설명이 옳지 않다. 아이템 쪽 다중성이 *(0개 이상)이므로 빈 상자도 허용된다.
이 도해는 컴포지트(Composite) 패턴 구조다. 인형과 상자는 아이템을 일반화(상속)하고, 상자만 아이템과 집약(빈 마름모) 관계를 맺어 상자 1개가 아이템을 0개 이상 포함한다.
- 인형에는 포함 관계가 없으므로 인형은 상자를 포함할 수 없다 — 옳은 설명이다.
- 인형과 상자 모두 빈 삼각형 화살표로 아이템을 상속하므로 아이템의 종류이다 — 옳은 설명이다.
- 상자가 포함하는 대상은 아이템이고 상자도 아이템이므로, 인형을 담은 상자를 다른 상자가 재귀적으로 포함할 수 있다 — 옳은 설명이다.
정통법이 각 기능에 평균 복잡도를 적용한다는 설명이 옳지 않다. 평균 복잡도를 적용하는 것은 간이법이다.
정통법은 도출한 각 기능의 세부 요소를 따져 기능별 복잡도를 직접 산정한다.
- 기능 점수는 계획뿐 아니라 분석·설계·구현 단계에서도 쓸 수 있고, 진행될수록 정확해진다.
- 구현 기술·언어·도구·개발자 능력과 무관하게 규모를 일관되게 측정한다.
- 소프트웨어 기능을 정량화해 개발 비용 산정에 활용한다.
class Student {
private String name;
protected String department;
private static int nextAvailID = 1;
protected void passed(Course theCourse) {...}
public static void getNextAvailID() {...}
}| Student |
|---|
| +name: String #department: String -nextAvailID: int = 1 |
| +passed(theCourse: Course) +getNextAvailID() |
| Student |
|---|
| -name: String #department: String -nextAvailID: int = 1 |
| #passed(theCourse: Course) +getNextAvailID() |
| Student |
|---|
| -name: String -department: String -nextAvailID: int = 1 |
| #passed(theCourse: Course) +getNextAvailID() |
| Student |
|---|
| -name: String #department: String -nextAvailID: int = 1 |
| #passed(theCourse: Course) +getNextAvailID() |
name은 -(private), department와 passed는 #(protected), static 멤버는 밑줄로 표시한 다이어그램이 맞다.
UML 가시성은 public +, private -, protected # 이며, static 속성·연산은 밑줄로 나타낸다. 따라서 nextAvailID는 밑줄 친 -nextAvailID: int = 1, getNextAvailID는 밑줄 친 +getNextAvailID()이다.
- name을 +, passed를 +로 표시한 다이어그램은 가시성이 틀렸다.
- department를 -로 표시한 다이어그램은 protected를 private으로 잘못 나타냈다.
- static 멤버에 밑줄이 없는 다이어그램은 정적 멤버를 표현하지 못했다.
if (x >= 0 || y < 4)
z = x + y;
else
z = x - y;
{(x = 2, y = 2), (x = -2, y = 6)}이 조건 커버리지와 분기 커버리지를 모두 100% 만족한다.
(2, 2)는 x >= 0 참·y < 4 참으로 if 분기, (-2, 6)은 두 조건 모두 거짓으로 else 분기를 탄다. 각 조건이 참·거짓을 모두 가지고 두 분기도 모두 실행된다.
- {(-1, 2), (1, 6)}은 두 경우 모두 결과가 참이라 else 분기를 실행하지 못한다.
- {(-1, 2), (2, 2)}는 y < 4가 항상 참이라 조건 커버리지를 채우지 못하고 else 분기도 없다.
- {(1, 6), (-2, 6)}은 y < 4가 항상 거짓이라 조건 커버리지를 채우지 못한다.
○ 비즈니스 프로세스와 같은 고수준의 흐름을 표현한다.
○ 병행 처리를 표현하기 위해 포크와 조인을 이용한다.
설명에 해당하는 다이어그램은 액티비티(activity) 다이어그램이다.
작업 흐름과 비즈니스 프로세스를 표현하고, 병행 처리를 포크와 조인으로 나타낸다.
- 배치 다이어그램은 하드웨어 노드와 그 위에 배치된 소프트웨어 산출물을 표현한다.
- 컴포넌트 다이어그램은 컴포넌트와 인터페이스 간 구성·의존을 표현한다.
- 패키지 다이어그램은 모델 요소를 패키지로 묶고 패키지 간 의존을 표현한다.
작업 패키지를 계층 상위의 여러 작업을 묶은 단위로 설명한 것이 옳지 않다. 작업 패키지는 WBS의 최하위 단계 작업 단위이다.
작업 패키지 수준에서 일정·비용·담당자를 배정하고 관리·통제한다.
- WBS는 프로젝트에서 수행할 모든 작업을 포함해야 한다.
- 작업 프로세스 중심으로도, 산출물 중심으로도 작성할 수 있다.
- 목표 달성과 결과물 산출에 필요한 작업을 계층적으로 분할한 것이다.
| 라인 번호 | C++ 코드 |
|---|---|
| 1 | #include<iostream> |
| 2 | using namespace std; |
| 3 | |
| 4 | class A { |
| 5 | private: |
| 6 | int size; |
| 7 | public: |
| 8 | A(int size) { size = size; }; //오류 확인 |
| 9 | virtual void print() { cout << size; }; |
| 10 | }; |
| 11 | |
| 12 | class B : public A { |
| 13 | public: |
| 14 | B(int size) : A(size) { }; |
| 15 | void print() { cout << size; }; //오류 확인 |
| 16 | }; |
| 17 | |
| 18 | int main() { |
| 19 | A *b = new B(10); |
| 20 | b.print(); //오류 확인 |
| 21 | return 0; |
| 22 | } |
밑줄 친 8행, 15행, 20행 모두 오류가 있다.
8행의 size = size는 매개변수를 자기 자신에 대입할 뿐 멤버 size는 초기화되지 않으므로 this->size = size처럼 써야 한다.
- 15행: size는 A의 private 멤버라 파생 클래스 B에서 접근할 수 없어 컴파일 오류가 난다.
- 20행: b는 포인터이므로 b.print()가 아니라 b->print()로 호출해야 한다.
| 작업 | 소요기간(일) | 선행작업 |
|---|---|---|
| T1 | 7 | - |
| T2 | 8 | T1 |
| T3 | 3 | T1 |
| T4 | 5 | T2, T3 |
| T5 | 6 | T3 |
| T6 | 10 | T5 |
| T7 | (가) | T4 |
| T8 | 5 | T6, T7 |
(가)에 들어갈 계획 소요기간은 10일이다.
(가)를 x라 하면 지연 후 T5는 13일, T7은 x+5일이다. 경로별 길이는 다음과 같다.
T1→T3→T5→T6→T8:
T1→T2→T4→T7→T8:
T1→T3→T4→T7→T8은 T2 경로보다 5일 짧아 임계 경로가 될 수 없다.
최소 완료 시간이 40일이고 38일 경로보다 길므로 T7을 지나는 경로가 임계 경로이다.