24-3
아래 Java 프로그램이 출력하는 값을 적으시오.
class Parent {
int n = 4;
int calc() {
return n + 1;
}
}
class Child extends Parent {
int n = 9;
int calc() {
return n * 2;
}
}
public class Main {
public static void main(String[] args) {
Parent a = new Child();
Child b = new Child();
System.out.print(a.n + a.calc() + b.n - b.calc());
}
}13
[해설]
메서드는 실제 객체 기준(동적 바인딩)으로, 필드는 참조 변수의 선언 타입 기준으로 결정된다.
- a.n: a의 타입이 Parent이므로 Parent의 n → 4
- a.calc(): 실제 객체가 Child라 오버라이딩된 Child.calc() → 9 × 2 = 18
- b.n: Child의 n → 9
- b.calc(): 18
4 + 18 + 9 − 18 = 13이 출력된다. 자식이 같은 이름으로 다시 선언한 필드는 부모 필드를 숨길 뿐 오버라이딩되지 않는다.
24-3
빈칸 ( )에 알맞은 네트워크의 명칭을 적으시오.
( )은/는 기지국이나 무선 AP 같은 고정 기반 시설 없이, 이동 단말(노드)들이 서로 직접 연결하며 스스로 망을 꾸리는 네트워크이다. 각 노드가 라우터 역할을 함께 맡아 데이터를 중계하므로 빠르게 구축할 수 있어, 재난 현장 구조 활동이나 임시 회의, 군 작전 통신 등에 쓰인다.
애드혹 네트워크(Ad-hoc Network)
[해설]
기지국이나 AP 같은 기반 시설 없이 이동 노드끼리 스스로 꾸리는 망은 애드혹 네트워크(Ad-hoc Network)다.
각 노드가 라우터 역할도 맡아 데이터를 중계하므로 재난 현장이나 군 작전에서 빠르게 구축할 수 있다.
노드가 움직일 때마다 연결 구조가 바뀌므로 AODV·DSR 같은 동적 라우팅 프로토콜을 쓴다.
24-3
아래 Java 프로그램이 콘솔에 찍는 결과를 적으시오.
public class Main {
static void check(String[] w) {
for (int k = 1; k < w.length; k++) {
if (w[k].equals(w[k - 1]))
System.out.print("Y");
else
System.out.print("X");
}
for (String t : w)
System.out.print(t);
}
public static void main(String[] args) {
String[] w = new String[4];
w[0] = "K";
w[1] = new String("K");
w[2] = "k";
w[3] = new String("k");
check(w);
}
}YXYKKkk
[해설]
equals()는 참조 주소가 아니라 문자열 내용을 비교하므로, new String으로 만든 객체도 내용이 같으면 참이다.
- k=1: "K"와 new String("K") → 내용 같음 → "Y"
- k=2: "k"와 "K" → 대소문자가 달라 → "X"
- k=3: new String("k")와 "k" → 내용 같음 → "Y"
이어서 향상된 for문이 네 원소를 그대로 이어 찍어 "KKkk"가 붙는다. 최종 출력은 YXYKKkk다.
비교를 == 로 했다면 k=1, k=3은 서로 다른 객체라 "X"가 된다. 이 차이가 문항의 핵심이다.
24-3
UML에서 사물 사이의 관계를 설명한 것이다. 표의 ①~③에 알맞은 관계를 [보기]에서 골라 기호로 적으시오.
| 관계 | 설명 | 예시와 표기 |
|---|---|---|
| ( ① ) | 두 개 이상의 사물이 서로 관련되어 있음을 나타낸다. | [도서관] ──── [회원] (실선으로 연결) |
| ( ② ) | 한 사물이 다른 사물보다 더 일반적인지, 더 구체적인지를 나타낸다. | [원], [삼각형], [사각형] ──▷ [도형] (끝이 속 빈 삼각형인 실선 화살표) |
| ( ③ ) | 평소엔 무관하다가 필요할 때 짧게만 서로를 이용하며, 한쪽이 바뀌면 다른 쪽도 영향을 받는다. | [주문] - - - > [결제수단] (점선 화살표) |
[보기] ㉠ 연관(Association) ㉡ 의존(Dependency) ㉢ 일반화(Generalization) ㉣ 실체화(Realization) ㉤ 집합(Aggregation) ㉥ 포함(Composition)
① ㉠
② ㉢
③ ㉡
[해설]
실선으로 이어 서로 관련됨만 나타내는 것은 연관(Association) 관계다.
일반·구체(is-a)를 속 빈 삼각형 화살표로 나타내는 것은 일반화(Generalization), 짧게 이용하는 관계를 점선 화살표로 나타내는 것은 의존(Dependency)이다.
- 실체화: 인터페이스와 구현 클래스, 속 빈 삼각형 점선 화살표
- 집합: 전체와 부분이 독립적, 빈 마름모
- 포함: 전체가 사라지면 부분도 사라짐, 채운 마름모
24-3
[직원] 테이블과 [과제] 테이블이 다음과 같다. 아래 SQL 문을 실행했을 때 결과 ( )에 들어갈 값을 적으시오.
[직원]
| 번호 | 이름 | 부서코드 |
|---|---|---|
| 1 | 강민호 | D1 |
| 2 | 윤서아 | D2 |
| 3 | 정우진 | D1 |
| 4 | 한소율 | D3 |
| 5 | 조하람 | D2 |
| 6 | 임태오 | D1 |
[과제]
| 부서코드 | 과제명 |
|---|---|
| D1 | 관제 |
| D2 | 결제 |
| D3 | 배송 |
| D3 | 정산 |
| D4 | 인증 |
SELECT COUNT(*)
FROM 직원 e JOIN 과제 t
ON e.부서코드 = t.부서코드
WHERE t.과제명 IN (SELECT 과제명
FROM 과제
WHERE 부서코드 IN (SELECT 부서코드
FROM 직원
GROUP BY 부서코드
HAVING COUNT(*) <= 2));[결과]
| COUNT(*) |
|---|
| ( ) |
4
[해설]
중첩 서브쿼리는 가장 안쪽부터 푼다. 직원 수가 2명 이하인 부서는 D2(2명)·D3(1명)이고, 이 부서들의 과제명은 결제·배송·정산이다.
- D1 직원 3명 × 관제 — 과제명이 목록에 없어 제외된다.
- D2 직원 2명 × 결제 — 2행이 남는다.
- D3 직원 1명 × 배송·정산 — 과제가 둘이라 직원 1명이 2행으로 늘어난다.
조건을 통과한 조인 행은 2 + 2 = 4개다. D4는 직원이 없어 내부 조인에서 처음부터 빠진다.
24-3
관계 데이터베이스의 키에 관한 설명이다. ①~④에 알맞은 키를 [보기]에서 골라 적으시오.
- ( ① ): 이 릴레이션의 속성이면서 다른 릴레이션의 기본키를 가리키며, 릴레이션 간 참조 무결성을 지키는 데 쓰인다.
- ( ② ): 튜플을 유일하게 식별할 수 있으면서(유일성) 불필요한 속성이 없는(최소성) 속성 또는 속성 집합이다.
- ( ③ ): 기본키로 선택될 수 있었으나 선택되지 않고 남은 키이다.
- ( ④ ): 튜플을 유일하게 식별하지만 최소성은 갖추지 못한 속성 집합이다.
[보기] 기본 키(Primary Key), 대체 키(Alternate Key), 슈퍼 키(Super Key), 외래 키(Foreign Key), 후보 키(Candidate Key)
① 외래 키(Foreign Key)
② 후보 키(Candidate Key)
③ 대체 키(Alternate Key)
④ 슈퍼 키(Super Key)
[해설]
다른 릴레이션의 기본키를 참조하는 것은 외래 키, 유일성과 최소성을 모두 갖춘 것은 후보 키다.
후보 키 중 기본키로 뽑히지 않은 나머지는 대체 키, 유일성만 있고 최소성이 없는 것은 슈퍼 키다.
기본 키도 유일성·최소성을 갖추지만, 후보 키 가운데 설계자가 골라 지정한 하나라는 점에서 ②의 설명과 구별된다.
24-3
score 함수가 자료형마다 다른 값을 돌려줄 때, 아래 코드가 마지막에 찍는 수를 구하시오.
def score(v):
if type(v) == type(1):
return v * 2
elif type(v) == type("a"):
return len(v)
elif type(v) == type([]):
return 7
else:
return 3
p = "3.14"
q = 5
r = 2.5
s = [1, 2]
print(score(p) + score(q) + score(r) + score(s))24
[해설]
score는 type()으로 인자의 자료형을 비교해 반환값을 정한다.
- p = "3.14": 숫자처럼 보여도 str이므로 len → 4
- q = 5: int → 5 × 2 = 10
- r = 2.5: float은 어느 분기에도 맞지 않아 else → 3
- s = [1, 2]: list → 7
합계는 4 + 10 + 3 + 7 = 24다.
24-3
아래 [사원] 릴레이션은 ( ) 무결성 제약조건을 어기고 있다. 빈칸 ( )에 알맞은 말을 적으시오. (사원번호가 기본키이다.)
| 사원번호 | 성명 | 부서 | 입사연도 |
|---|---|---|---|
| E101 | 류지안 | 영업 | 2019 |
| NULL | 배시후 | 기획 | 2021 |
| E107 | 남도현 | 영업 | 2022 |
| E112 | 옥채원 | 인사 | 2020 |
| NULL | 탁은호 | 기획 | 2023 |
개체
[해설]
기본키인 사원번호에 NULL이 들어간 튜플이 있으므로 개체 무결성 위반이다.
개체 무결성은 기본키 속성이 NULL을 가질 수 없고 중복될 수도 없다는 규칙이다.
- 참조 무결성: 외래키는 NULL이거나 참조 릴레이션의 기본키 값이어야 한다.
- 도메인 무결성: 속성 값은 정의된 자료형·범위 안에 있어야 한다.
24-3
아래 Java 프로그램이 출력하는 값을 적으시오.
public class Main {
static void run() throws Exception {
throw new ArithmeticException();
}
public static void main(String[] args) {
int res = 5;
try {
run();
res += 1000;
} catch (ArithmeticException e) {
res *= 3;
} catch (RuntimeException e) {
res *= 7;
} catch (Exception e) {
res += 50;
} finally {
res += 200;
}
System.out.print(res);
}
}215
[해설]
run()이 던진 ArithmeticException 때문에 res += 1000은 실행되지 않는다.
catch는 위에서부터 검사하며 처음 맞는 하나만 실행된다. 첫 번째 ArithmeticException 블록이 잡아 res = 5 × 3 = 15가 된다.
RuntimeException·Exception 블록은 건너뛰고, finally는 항상 실행되어 15 + 200 = 215가 된다.
최종 출력은 215다. 하위 예외를 먼저, 상위 예외를 나중에 두어야 컴파일 오류가 나지 않는다.
24-3
화이트박스 테스트의 커버리지에 관한 설명이다. ①~③에 해당하는 것을 [보기]에서 골라 영문으로 적으시오.
- ( ① ): 프로그램의 모든 문장이 최소 한 번씩 실행되도록 테스트 케이스를 만든다.
- ( ② ): 모든 판정문(결정문)의 전체 결과가 참과 거짓을 각각 한 번 이상 갖도록 한다.
- ( ③ ): 판정문 안의 개별 조건식 하나하나가 참과 거짓을 각각 한 번 이상 갖도록 한다.
[보기] Branch, Condition, Condition/Decision, Default, Modified Condition/Decision, Multiple Condition, Statement
① Statement
② Branch
③ Condition
[해설]
모든 문장 실행은 구문(Statement) 커버리지, 판정 결과의 참·거짓은 결정(Branch) 커버리지다.
판정 전체가 아니라 그 안의 각 조건식을 참·거짓으로 만드는 것은 조건(Condition) 커버리지다.
- Condition/Decision: 조건과 결정 커버리지를 모두 만족한다.
- Modified Condition/Decision: 각 조건이 다른 조건과 무관하게 판정 결과를 바꿀 수 있음을 보인다.
- Multiple Condition: 조건들의 가능한 모든 조합을 시험한다.
24-3
아래 C 프로그램을 실행했을 때 출력 결과를 적으시오.
#include <stdio.h>
#include <stddef.h>
struct Box {
int val;
struct Box *nxt;
};
void swapPairs(struct Box *b) {
while (b != NULL && b->nxt != NULL) {
int tmp = b->val;
b->val = b->nxt->val;
b->nxt->val = tmp;
b = b->nxt->nxt;
}
}
int main(void) {
struct Box a = {5, NULL}, b = {8, NULL}, c = {2, NULL}, d = {6, NULL}, e = {9, NULL};
struct Box *cur;
a.nxt = &d;
d.nxt = &b;
b.nxt = &e;
e.nxt = &c;
swapPairs(&a);
for (cur = &a; cur != NULL; cur = cur->nxt)
printf("%d", cur->val);
return 0;
}65982
[해설]
main에서 연결한 순서는 변수 선언 순서가 아니라 nxt 포인터를 따라간 a(5) → d(6) → b(8) → e(9) → c(2)이다.
swapPairs는 이웃한 두 노드의 값을 맞바꾼 뒤 두 칸 건너뛴다.
- 1회: a와 d 교환 → 6, 5
- 2회: b와 e 교환 → 9, 8
- c는 짝이 없어(nxt가 NULL) 그대로 2
출력은 65982다. 노드 연결은 바뀌지 않고 값만 교환된다.
24-3
다음 설명에 해당하는 서비스 거부(DoS) 공격 기법의 이름을 적으시오.
- 공격자는 ICMP Echo Request 패킷의 송신지 IP 주소를 피해자의 주소로 위조한다.
- 이 패킷을 특정 네트워크의 브로드캐스트 주소로 보내면(Directed Broadcast), 그 망의 모든 호스트가 피해자에게 Echo Reply를 쏟아낸다.
- 대응책으로 라우터에서 직접 브로드캐스트 전달을 막는 방법이 쓰인다.
스머프(Smurf)
[해설]
송신지를 피해자로 위조한 ICMP Echo Request를 브로드캐스트 주소로 보내 응답을 증폭시키는 공격은 스머프(Smurf) 공격이다.
중간 네트워크의 호스트들이 증폭기 역할을 하므로 라우터에서 Directed Broadcast를 차단하는 것이 기본 대응이다.
혼동 주의: Ping of Death는 규정보다 큰 ICMP 패킷을 쓰고, Land 공격은 송신지와 수신지 주소를 같게 만든 패킷을 쓴다.
24-3
아래 Python 프로그램을 실행한 결과를 적으시오.
def flip(seq):
n = len(seq)
for k in range(n // 2):
seq[k], seq[n - 1 - k] = seq[n - 1 - k], seq[k]
nums = [2, 9, 4, 7, 1, 8, 5]
flip(nums)
print(sum(nums[1::2]) - sum(nums[::3]))10
[해설]
flip은 앞뒤 원소를 n//2번 맞바꿔 리스트를 뒤집는다. 길이가 7이라 3번 교환하고 가운데 7은 제자리다.
- 뒤집은 결과: [5, 8, 1, 7, 4, 9, 2]
- nums[1::2]: 인덱스 1, 3, 5 → 8 + 7 + 9 = 24
- nums[::3]: 인덱스 0, 3, 6 → 5 + 7 + 2 = 14
24 − 14 = 10이 출력된다. 슬라이스 [시작:끝:간격]에서 시작을 생략하면 0부터, 끝을 생략하면 마지막까지다.
24-3
GoF 디자인 패턴은 목적에 따라 생성·구조·( ) 패턴으로 나뉜다. 다음 설명의 빈칸 ( )에 알맞은 분류명을 적으시오.
- ( ) 패턴은 객체와 클래스 사이에서 책임을 어떻게 나누고, 서로 어떻게 소통하며 알고리즘을 수행할지를 다룬다.
- Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor 등이 여기에 속한다.
행위
[해설]
객체 간 상호작용과 책임 분배를 다루는 분류는 행위(Behavioral) 패턴이다.
- 생성(Creational) 패턴: 객체 생성 방식을 감춘다. Singleton, Factory Method, Builder 등
- 구조(Structural) 패턴: 클래스·객체를 조합해 더 큰 구조를 만든다. Adapter, Decorator, Proxy 등
- 행위 패턴: Observer, Strategy, Command 등
24-3
아래 C 프로그램을 실행하면 출력되는 결과를 적으시오.
#include <stdio.h>
void shift(int **pp, int len) {
for (int k = 0; k < len; k++)
*(*pp + k) = (*(*pp + k) * 2 + k) % len;
}
int main(void) {
int data[] = {6, 2, 5, 3, 4, 1};
int *p = data;
int **pp = &p;
shift(pp, 6);
printf("%d%d", data[1], data[4]);
return 0;
}50
[해설]
pp는 p의 주소를, p는 data의 시작 주소를 가지므로 *(*pp + k)는 data[k]와 같다.
shift는 각 원소를 (값 × 2 + k) % 6으로 바꾼다.
- data[1]: (2 × 2 + 1) % 6 = 5
- data[4]: (4 × 2 + 4) % 6 = 12 % 6 = 0
printf("%d%d")는 두 값을 붙여 찍으므로 50이 출력된다.
24-3
다음은 URL https://shop.example.org:8443/items/list?page=3#top을 구성 요소별로 나눈 것이다. 이 요소들이 URL 안에 나타나는 순서대로 기호를 나열하시오.
| 기호 | 구성 요소 | 이 URL에서의 값 |
|---|---|---|
| ㉠ | fragment | #top |
| ㉡ | path | /items/list |
| ㉢ | query | ?page=3 |
| ㉣ | authority | shop.example.org:8443 |
| ㉤ | scheme | https:// |
( ) → ( ) → ( ) → ( ) → ( )
㉤ → ㉣ → ㉡ → ㉢ → ㉠
[해설]
URL의 일반 구조는 scheme → authority → path → query → fragment 순이다.
- scheme(https://)은 접근 방식으로, 맨 앞에 온다.
- authority(shop.example.org:8443)는 호스트명과 포트다.
- path(/items/list)는 서버 안의 자원 위치다.
- query(?page=3)는 ? 뒤에 오는 이름=값 쌍이다.
- fragment(#top)는 # 뒤의 문서 내부 위치로, 맨 끝에 온다.
참고로 fragment는 브라우저만 쓰는 정보라서 서버로 전송되지 않는다.
24-3
아래 Java 프로그램의 출력 결과를 적으시오.
class Show {
void out(Long v) {
System.out.print("L" + v);
}
void out(Number v) {
System.out.print("N" + v);
}
void out(Object v) {
System.out.print("O" + v);
}
}
class Holder<E> {
E item;
Holder(E item) {
this.item = item;
}
void display() {
new Show().out(item);
}
}
public class Main {
public static void main(String[] args) {
Holder<Long> h = new Holder<>(7L);
h.display();
new Show().out(h.item);
}
}O7L7
[해설]
오버로딩된 메서드 중 무엇을 부를지는 실행 시점이 아니라 컴파일 시점의 인자 타입으로 정해진다.
Holder 클래스 안에서 컴파일러가 아는 item의 타입은 상한(bound)이 Object인 타입 변수 E뿐이라, Holder<Long>으로 만들어도 display()는 out(Object)를 호출해 "O7"을 찍는다.
main의 h.item은 Holder<Long>에서 꺼낸 값이라 컴파일러가 Long으로 알고 있다. 따라서 가장 구체적인 out(Long)이 호출되어 "L7"이 찍힌다.
합쳐서 O7L7이 출력된다.
24-3
주기억장치에 페이지 프레임이 3개 있고 처음에는 모두 비어 있다. 페이지가 아래 순서로 참조될 때 LRU(Least Recently Used) 교체 기법을 적용하면 페이지 부재(Page Fault)는 모두 몇 번 일어나는지 적으시오.
| 참조 순번 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 페이지 | 7 | 0 | 1 | 2 | 0 | 1 | 2 | 7 | 1 | 0 | 2 | 1 | 7 | 0 | 2 | 1 | 7 |
12회
[해설]
LRU는 프레임이 가득 찼을 때 가장 오랫동안 참조되지 않은 페이지를 내보낸다.
- 1~4번(7, 0, 1, 2): 부재 4회, 2가 들어올 때 7 교체
- 5~7번(0, 1, 2): 모두 적중
- 8번(7): 부재, 0 교체 → 9번(1) 적중
- 10~11번(0, 2): 부재 2회 → 12번(1) 적중
- 13~17번(7, 0, 2, 1, 7): 매번 방금 쫓겨난 페이지가 다시 참조되어 부재 5회
적중은 5회이므로 부재는 17 − 5 = 12회다.
24-3
아래 C 프로그램이 출력하는 값을 적으시오.
#include <stdio.h>
int bump(void) {
static int cnt = 1;
cnt *= 2;
return cnt;
}
int main(void) {
int cnt = 10;
int total = 0;
for (int k = 0; k < 3; k++) {
cnt--;
total += bump() + cnt;
}
printf("%d", total);
return 0;
}38
[해설]
bump 안의 cnt는 static 지역 변수라 처음 한 번만 1로 초기화되고, 호출이 끝나도 값이 유지된다.
main의 cnt는 이름만 같은 별개의 지역 변수로, 10에서 시작해 반복마다 1씩 줄어든다.
- k=0: bump()=2, main의 cnt=9 → total=11
- k=1: bump()=4, cnt=8 → total=23
- k=2: bump()=8, cnt=7 → total=38
최종 출력은 38이다.
24-3
빈칸 ( )에 공통으로 들어갈 용어를 적으시오.
- 인터넷 같은 공중망 위에 암호화된 터널을 만들어, 떨어진 지점끼리 마치 전용 사설망처럼 통신하게 해 주는 기술이다.
- IPSec ( )은/는 네트워크 계층(3계층)에서 IP 패킷 자체를 보호하므로 보안성이 높지만 전용 장비가 필요한 경우가 많다.
- SSL ( )은/는 전송 계층 이상에서 동작해 웹 브라우저만으로 접속할 수 있어 도입 비용이 낮다.
VPN
[해설]
공중망 위에 암호화된 터널을 만들어 전용 사설망처럼 쓰는 기술은 VPN(Virtual Private Network, 가상 사설망)이다.
IPSec VPN은 3계층에서 IP 패킷 자체를 보호하며 주로 사이트 간 연결에 쓰인다. SSL VPN은 전송 계층 이상에서 동작해 웹 브라우저만으로 원격 접속할 수 있다.