본문 바로가기
  • 코딩, 허쌤이 떠먹여 줄게
BackEnd/정보처리기사

2025년 정보처리기사 실기 1회 복원 문제 해설

by 허쌤 2026. 2. 16.

2025년 정보처리기사 실기 1회 복원 문제 해설

📋 목차

  1. 네트워크 보안 문제
  2. 제약조건 문제
  3. CRC 오류 검출 문제
  4. 악성코드 문제
  5. Java 예외 처리 문제
  6. ARP/RARP 문제
  7. SQL 조인 문제
  8. 데이터베이스 용어 문제
  9. 서브넷 브로드캐스트 문제
  10. C언어 배열 문제
  11. C언어 2차원 배열 문제
  12. 결합도 문제
  13. Java 상속 문제
  14. 디자인 패턴 문제
  15. 문장 커버리지 문제
  16. Java 재귀 함수 문제
  17. 파이썬 트리 문제
  18. C언어 연결 리스트 문제
  19. C언어 비트 연산 문제
  20. Java 메서드 오버로딩 문제

1. 네트워크 보안 문제

문제

다음은 네트워크 보안에 관련된 문제이다. 괄호안에 알맞는 용어를 작성하시오.

( )은/는 '세션을 가로채다.' 라는 의미로 다른 사람의 세션 상태를 훔치거나 도용하여 액세스하는 해킹 기법이다.

TCP ( )은/는 TCP의 3-way 핸드셰이크가 완료된 후에 공격자가 시퀀스 번호 등을 조작하여 정상적인 세션을 가로채고 인증 없이 통신을 탈취하는 공격이다.

정답

  • 세션 하이재킹 (Session Hijacking)
  • 세션 하이재킹 (Session Hijacking)

해설

용어 설명 공격 방식
세션 하이재킹 세션을 가로채는 공격 세션 ID 탈취, 시퀀스 번호 조작
TCP 세션 하이재킹 TCP 연결을 가로채는 공격 시퀀스 번호 예측 및 조작

세션 하이재킹 과정:

1. 정상 연결: 클라이언트 ↔ 서버
2. 공격자: 세션 정보 탈취
3. 공격자: 시퀀스 번호 조작
4. 공격자: 정상 클라이언트 대신 서버와 통신

TCP 3-way 핸드셰이크:

클라이언트          서버
    |               |
    |--- SYN ------>|
    |<-- SYN+ACK ---|
    |--- ACK ------>|
    |               |

보안 대책:

  • HTTPS 사용 (SSL/TLS)
  • 세션 ID 암호화
  • 시퀀스 번호 랜덤화
  • 세션 타임아웃 설정

2. 제약조건 문제

문제

다음은 제약조건과 관련된 문제이다. 괄호안에 알맞는 용어를 보기에 골라 작성하시오.

[보기]
개체, 참조, 도메인

정답

  • ㄱ. 도메인
  • ㄴ. 개체
  • ㄷ. 참조

해설

제약조건 설명 예시
도메인 (Domain) 속성에 입력될 수 있는 값의 범위 나이: 0~150
개체 (Entity) 데이터베이스에 저장되는 객체 학생, 교수, 과목
참조 (Reference) 외래키를 통한 테이블 간 관계 학생.학과코드 → 학과.학과코드

제약조건 종류:

제약조건
├── 도메인 제약조건 (Domain Constraint)
│   └── 속성 값의 범위 제한
├── 개체 무결성 (Entity Integrity)
│   └── 기본키는 NULL 불가, 중복 불가
├── 참조 무결성 (Referential Integrity)
│   └── 외래키는 참조하는 기본키 값이 존재해야 함
└── 사용자 정의 제약조건
    └── CHECK, UNIQUE 등

3. CRC 오류 검출 문제

문제

아래의 내용에서 설명 글의 괄호안의 용어를 영문 약자로 작성하시오.

( ) 은/는 3글자의 영어 약자로 이루어진 오류 기법으로 데이터를 전송하거나 저장할 때 데이터의 오류를 감지하는 데 사용되는 오류 검출 코드이다.

( ) 은/는 데이터에 체크섬을 추가하여 데이터를 전송하거나 저장한 후, 수신 또는 읽을 때 이 체크섬을 다시 계산하여 데이터가 변경되었는지 확인하는 기법이다.

( ) 은/는 데이터 전송의 안정성을 높이는 데 중요한 역할을 한다.

데이터는 이진수(0과 1)로 표현되며 정해진 다항식(x³ + x + 1)을 기반으로 데이터를 2진수 나눗셈하고 나머지를 ( ) 값으로 삼는다.

정답

CRC (Cyclic Redundancy Check)

해설

용어 약자 설명
CRC Cyclic Redundancy Check 순환 중복 검사, 오류 검출 코드

CRC 동작 원리:

1. 데이터 전송 전:
   데이터: 101101
   생성 다항식: x³ + x + 1 = 1011

2. CRC 계산:
   101101000 ÷ 1011
   나머지: 011 (CRC 값)

3. 전송:
   원본 데이터 + CRC = 101101011

4. 수신 측 검증:
   101101011 ÷ 1011
   나머지가 0이면 오류 없음

CRC 특징:

  • 순환 코드 기반
  • 하드웨어로 빠르게 구현 가능
  • 단일 비트 오류, 버스트 오류 검출 가능
  • 체크섬보다 정확도 높음

다항식 예시:

x³ + x + 1 = 1·x³ + 0·x² + 1·x¹ + 1·x⁰
           = 1011 (2진수)

4. 악성코드 문제

문제

다음은 악성코드 관련된 문제이다. 아래 내용을 확인하여 보기에 골라 작성하시오.

사용자가 원치 않는 소프트웨어를 구매하도록 조작하기 위해 사회 공학을 사용하여 충격, 불안 또는 위협에 대한 인식을 유발하는 악성 소프트웨어의 한 형태이다.

'겁을 주다'라는 영어 단어에서 유래한 것으로 공포를 이용하여 피해자를 속여 대가를 지불 하거나 특정 행동을 유도하는 랜섬웨어이다.

가짜 바이러스 경고나 시스템 문제를 표시하여 사용자가 돈을 지불하거나 특정 소프트웨어를 설치하도록 속이는 방식으로 작동한다.

[보기]
ㄱ. 컴포넌트 웨어 ㄴ. 유즈웨어 ㄷ. 셔블웨어 ㄹ. 스캐어 웨어 ㅁ. 안티 스파이 웨어 ㅂ. 네트웨어 ㅅ. 그룹웨어 ㅇ. 애드웨어

정답

ㄹ. 스캐어웨어 (Scareware)

해설

악성코드 종류 설명 특징
스캐어웨어 공포를 이용한 악성 소프트웨어 가짜 경고, 위협 메시지
랜섬웨어 파일 암호화 후 금전 요구 데이터 인질
애드웨어 광고 표시 과도한 팝업
스파이웨어 사용자 정보 수집 개인정보 유출

스캐어웨어 공격 과정:

1. 가짜 경고 표시
   "바이러스 감지됨!"
   "시스템이 손상되었습니다!"

2. 공포 유발
   "지금 즉시 치료하지 않으면
    모든 데이터가 삭제됩니다!"

3. 대응 유도
   "이 소프트웨어를 구매하세요"
   "이 링크를 클릭하세요"

4. 피해 발생
   - 금전 피해
   - 개인정보 유출
   - 추가 악성코드 설치

대응 방법:

  • 신뢰할 수 있는 백신 프로그램 사용
  • 의심스러운 경고 무시
  • 공식 사이트에서만 소프트웨어 다운로드

5. Java 예외 처리 문제

문제

다음은 Java 코드에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

public class Main {
    public static void main(String[] args) {
        int a=5,b=0;
        try{
            System.out.print(a/b);
        }catch(ArithmeticException e){
            System.out.print("출력1");
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.print("출력2");
        }catch(NumberFormatException e) {
            System.out.print("출력3");
        }catch(Exception e){
            System.out.print("출력4");
        }finally{
            System.out.print("출력5");
        }
    }
}

정답

출력1출력5

해설

코드 실행 흐름:

단계 코드 실행 결과
1 int a=5,b=0; a=5, b=0 초기화
2 System.out.print(a/b); 5/0 → ArithmeticException 발생
3 catch(ArithmeticException e) "출력1" 출력
4 finally 블록 "출력5" 출력 (항상 실행)

예외 처리 순서:

try {
    // 예외 발생 가능 코드
    a/b  → ArithmeticException 발생
}
catch (ArithmeticException e) {  ← 첫 번째 매칭
    "출력1" 출력
}
catch (ArrayIndexOutOfBoundsException e) {
    // 실행 안 됨
}
catch (NumberFormatException e) {
    // 실행 안 됨
}
catch (Exception e) {
    // 실행 안 됨 (위에서 처리됨)
}
finally {
    "출력5" 출력  ← 항상 실행
}

예외 계층 구조:

Exception
├── RuntimeException
│   ├── ArithmeticException  ← 5/0 발생
│   ├── ArrayIndexOutOfBoundsException
│   └── NumberFormatException
└── ...

핵심 포인트:

  • 5/0ArithmeticException 발생
  • catch 블록은 위에서부터 순서대로 매칭
  • finally 블록은 항상 실행됨

6. ARP/RARP 문제

문제

아래 내용은 ARP/RARP에 대한 설명이다. 각 설명에 해당하는 것을 작성하시오.

( 1 ) 은/는 네트워크상에서 IP 주소를 MAC 주소로 변환하는 프로토콜이고,

( 2 ) 은/는 MAC 주소를 IP 주소로 변환하는 프로토콜이다.

정답

  • (1) ARP (Address Resolution Protocol)
  • (2) RARP (Reverse Address Resolution Protocol)

해설

프로토콜 약자 변환 방향 용도
ARP Address Resolution Protocol IP → MAC IP 주소로 MAC 주소 찾기
RARP Reverse ARP MAC → IP MAC 주소로 IP 주소 찾기

ARP 동작 과정:

1. 호스트 A가 호스트 B의 MAC 주소 필요
   IP: 192.168.1.2 → MAC: ?

2. ARP 요청 브로드캐스트
   "192.168.1.2의 MAC 주소가 누구야?"

3. 호스트 B가 ARP 응답
   "192.168.1.2는 나야! MAC: AA:BB:CC:DD:EE:FF"

4. 호스트 A가 ARP 캐시에 저장

RARP 동작 과정:

1. 디스크 없는 워크스테이션 부팅
   MAC: AA:BB:CC:DD:EE:FF → IP: ?

2. RARP 요청 브로드캐스트
   "내 MAC 주소의 IP 주소가 뭐야?"

3. RARP 서버가 응답
   "너의 IP는 192.168.1.100이야"

4. 워크스테이션이 IP 주소 획득

비교표:

┌─────────┬──────────┬──────────────┬─────────────┐
│ 프로토콜│ 변환 방향 │ 사용 시점    │ 현재 상태   │
├─────────┼──────────┼──────────────┼─────────────┤
│ ARP     │ IP→MAC   │ 통신 시작 시 │ 널리 사용   │
│ RARP    │ MAC→IP   │ 부팅 시      │ 거의 사용 안 함 │
└─────────┴──────────┴──────────────┴─────────────┘

참고: RARP는 현재 거의 사용되지 않으며, DHCP가 대체하고 있습니다.


7. SQL 조인 문제

문제

다음은 SQL 문제이다. 아래 두 테이블을 참고하여 보기에 쿼리 실행 결과를 작성하시오.

emp 테이블:
| id | name |
|----|------|
| 1 | 이순신 |
| 2 | 강감찬 |

sal 테이블:
| id | incentive |
|----|-----------|
| 1 | 1000 |
| 2 | 300 |

쿼리:

SELECT name, incentive 
FROM emp, sal 
WHERE emp.id = sal.id and incentive >= 500

정답

name  |  incentive  
이순신 | 1000

해설

테이블 조인 과정:

단계 설명 결과
1 FROM emp, sal 두 테이블의 카티션 곱
2 WHERE emp.id = sal.id 내부 조인 (INNER JOIN)
3 WHERE incentive >= 500 조건 필터링

조인 결과 (단계 2):

emp.id | emp.name | sal.id | sal.incentive
-------|----------|--------|--------------
   1   | 이순신    |   1    |    1000
   2   | 강감찬    |   2    |    300

최종 결과 (단계 3):

name  |  incentive  
이순신 | 1000

조건 분석:

  • emp.id = sal.id: 조인 조건
  • incentive >= 500: 필터 조건
    • 이순신: 1000 ≥ 500 ✅
    • 강감찬: 300 ≥ 500 ❌

동등한 쿼리 (명시적 JOIN):

SELECT name, incentive 
FROM emp
INNER JOIN sal ON emp.id = sal.id
WHERE incentive >= 500

8. 데이터베이스 용어 문제

문제

아래는 데이터베이스에 관련된 설명이다. 알맞는 용어를 보기에서 골라 괄호를 작성하시오.

  1. 릴레이션에서 속성의 개수를 의미 : ( 1 )
  2. 릴레이션에서 튜플의 개수를 의미 : ( 2 )
  3. 한 릴레이션의 속성이 다른 릴레이션의 기본 키를 참조할 때, 참조하는 속성을 의미 : ( 3 )
  4. 특정 속성에 대해 입력될 수 있는 값의 유형이나 범위를 의미하고 무결성을 보장하는 기준 : ( 4 )

[보기]
ㄱ. domain ㄴ. primary ㄷ. degree ㄹ. candidate ㅁ. cardinality ㅂ. attribute ㅅ. foreign

정답

  • (1) ㄷ. degree (차수)
  • (2) ㅁ. cardinality (기수)
  • (3) ㅅ. foreign (외래키)
  • (4) ㄱ. domain (도메인)

해설

용어 영문 설명 예시
차수 Degree 속성(열)의 개수 학생 테이블: 학번, 이름, 나이 → 차수 3
기수 Cardinality 튜플(행)의 개수 학생 테이블에 100명 → 기수 100
외래키 Foreign Key 다른 테이블의 기본키 참조 학생.학과코드 → 학과.학과코드
도메인 Domain 속성 값의 범위 나이: 0~150, 성별: 'M'/'F'

릴레이션 구조:

학생 테이블
┌────────┬────────┬──────┬──────────┐
│ 학번   │ 이름   │ 나이 │ 학과코드 │ ← 차수: 4
├────────┼────────┼──────┼──────────┤
│ 2024001│ 홍길동 │  20  │    CS    │
│ 2024002│ 김철수 │  21  │    EE    │ ← 기수: 2
│ 2024003│ 이영희 │  19  │    CS    │
└────────┴────────┴──────┴──────────┘

도메인 예시:

속성: 나이
도메인: 0 이상 150 이하의 정수
유효 값: 0, 1, 2, ..., 150
무효 값: -1, 151, "스무살" 등

외래키 관계:

학생 테이블              학과 테이블
┌──────────┐           ┌──────────┐
│ 학번(PK) │           │ 학과코드(PK) │
│ 이름     │           │ 학과명   │
│ 학과코드(FK) ───────→│          │
└──────────┘           └──────────┘

9. 서브넷 브로드캐스트 문제

문제

IP 주소가 192.168.35.10, 서브넷 마스크 255.255.252.0인 PC에서 브로드캐스팅으로 다른 IP로 정보를 전달한다고 할 때 수신할 수 있는 알맞는 IP를 보기에서 골라 모두 작성하시오.

[보기]
ㄱ. 192.168.34.1
ㄴ. 192.168.32.19
ㄷ. 192.168.35.200
ㄹ. 192.168.33.138
ㅁ. 192.168.35.50

정답

ㄱ, ㄴ, ㄷ, ㄹ, ㅁ (모두)

해설

서브넷 계산:

항목 2진수
IP 주소 192.168.35.10 11000000.10101000.00100011.00001010
서브넷 마스크 255.255.252.0 11111111.11111111.11111100.00000000
네트워크 주소 192.168.32.0 11000000.10101000.00100000.00000000
브로드캐스트 주소 192.168.35.255 11000000.10101000.00100011.11111111

서브넷 마스크 분석:

255.255.252.0 = /22
11111111.11111111.11111100.00000000
            ↑
        호스트 비트: 10비트

네트워크 범위:

네트워크 주소: 192.168.32.0
브로드캐스트:  192.168.35.255
사용 가능 범위: 192.168.32.1 ~ 192.168.35.254

각 IP 확인:

IP 2진수 (3번째 옥텟) 범위 확인 결과
192.168.34.1 00100010 (34) 32 ≤ 34 ≤ 35
192.168.32.19 00100000 (32) 32 ≤ 32 ≤ 35
192.168.35.200 00100011 (35) 32 ≤ 35 ≤ 35
192.168.33.138 00100001 (33) 32 ≤ 33 ≤ 35
192.168.35.50 00100011 (35) 32 ≤ 35 ≤ 35

계산 방법:

서브넷 마스크: 255.255.252.0
→ 3번째 옥텟: 252 = 11111100 (6비트 네트워크, 2비트 호스트)

네트워크 부분: 192.168.001000xx (32~35)
              └─ 32: 00100000
              └─ 33: 00100001
              └─ 34: 00100010
              └─ 35: 00100011

모든 IP가 192.168.32.0 ~ 192.168.35.255 범위 내에 있음

10. C언어 배열 문제

문제

다음은 C언어에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

#include <stdio.h>
char Data[5] = {'B', 'A', 'D', 'E'};
char c;

int main(){
    int i, temp, temp2;

    c = 'C';
    printf("%d\n", Data[3]-Data[1]);

    for(i=0;i<5;++i){
        if(Data[i]>c)
            break;
    }

    temp = Data[i];
    Data[i] = c;
    i++;

    for(;i<5;++i){
        temp2 = Data[i];
        Data[i] = temp;
        temp = temp2;
    }

    for(i=0;i<5;i++){
        printf("%c", Data[i]);
    }
}

정답

4
BACDE

해설

초기 상태:

Data[0] = 'B'
Data[1] = 'A'
Data[2] = 'D'
Data[3] = 'E'
Data[4] = '\0' (초기화 안 됨, 0)
c = 'C'

단계별 실행:

단계 코드 실행 내용 Data 상태
1 printf("%d\n", Data[3]-Data[1]); 'E' - 'A' = 69 - 65 = 4 출력 -
2 for(i=0;i<5;++i) i=0: 'B' > 'C'? No
i=1: 'A' > 'C'? No
i=2: 'D' > 'C'? Yes → break
i=2
3 temp = Data[i]; temp = 'D' -
4 Data[i] = c; Data[2] = 'C' ['B','A','C','E','\0']
5 i++ i = 3 -
6 for(;i<5;++i) i=3: temp2='E', Data[3]='D', temp='E'
i=4: temp2='\0', Data[4]='E', temp='\0'
['B','A','C','D','E']

문자 삽입 과정:

초기: ['B', 'A', 'D', 'E', '\0']
      i=0  i=1  i=2  i=3  i=4

1. 'C'를 삽입할 위치 찾기 (i=2)
   ['B', 'A', 'D', 'E', '\0']
            ↑
          'C' 삽입

2. 'D'를 temp에 저장
   temp = 'D'

3. Data[2]에 'C' 삽입
   ['B', 'A', 'C', 'E', '\0']
            ↑
          'C' 삽입됨

4. 나머지 요소들을 오른쪽으로 시프트
   i=3: Data[3] = 'D' (temp)
   i=4: Data[4] = 'E' (temp2)

최종: ['B', 'A', 'C', 'D', 'E']

문자 코드 값:

'A' = 65
'B' = 66
'C' = 67
'D' = 68
'E' = 69

Data[3] - Data[1] = 'E' - 'A' = 69 - 65 = 4

11. C언어 2차원 배열 문제

문제

다음은 C언어에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

#include <stdio.h>
#include <stdlib.h>

void set(int** arr, int* data, int rows, int cols) {
    for (int i = 0; i < rows * cols; ++i) {
        arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
    }
}

int main() {
    int rows = 3, cols = 3, sum = 0;
    int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9}; 
    int** arr;
    arr = (int**) malloc(sizeof(int*) * rows);
    for (int i = 0; i < cols; i++) {
        arr[i] = (int*) malloc(sizeof(int) * cols);
    }

    set(arr, data, rows, cols);

    for (int i = 0; i < rows * cols; i++) {
        sum += arr[i / rows][i % cols] * (i % 2 == 0 ? 1 : -1);
    }

    for(int i=0; i<rows; i++) {
        free(arr[i]);
    }
    free(arr);

    printf("%d", sum);
}

정답

13

해설

set 함수 분석:

i (i+1)/rows ((i+1)/rows)%rows (i+1)%cols data[i] arr[행][열]
0 1/3 = 0 0%3 = 0 1%3 = 1 5 arr[0][1] = 5
1 2/3 = 0 0%3 = 0 2%3 = 2 2 arr[0][2] = 2
2 3/3 = 1 1%3 = 1 3%3 = 0 7 arr[1][0] = 7
3 4/3 = 1 1%3 = 1 4%3 = 1 4 arr[1][1] = 4
4 5/3 = 1 1%3 = 1 5%3 = 2 1 arr[1][2] = 1
5 6/3 = 2 2%3 = 2 6%3 = 0 8 arr[2][0] = 8
6 7/3 = 2 2%3 = 2 7%3 = 1 3 arr[2][1] = 3
7 8/3 = 2 2%3 = 2 8%3 = 2 6 arr[2][2] = 6
8 9/3 = 3 3%3 = 0 9%3 = 0 9 arr[0][0] = 9

배열 상태:

arr[0][0] = 9    arr[0][1] = 5    arr[0][2] = 2
arr[1][0] = 7    arr[1][1] = 4    arr[1][2] = 1
arr[2][0] = 8    arr[2][1] = 3    arr[2][2] = 6

sum 계산:

i i/rows i%cols arr[행][열] i%2==0? 부호
0 0 0 arr[0][0] = 9 Yes +1 +9
1 0 1 arr[0][1] = 5 No -1 -5
2 0 2 arr[0][2] = 2 Yes +1 +2
3 1 0 arr[1][0] = 7 No -1 -7
4 1 1 arr[1][1] = 4 Yes +1 +4
5 1 2 arr[1][2] = 1 No -1 -1
6 2 0 arr[2][0] = 8 Yes +1 +8
7 2 1 arr[2][1] = 3 No -1 -3
8 2 2 arr[2][2] = 6 Yes +1 +6

최종 계산:

sum = 9 - 5 + 2 - 7 + 4 - 1 + 8 - 3 + 6
    = (9 + 2 + 4 + 8 + 6) - (5 + 7 + 1 + 3)
    = 29 - 16
    = 13

12. 결합도 문제

문제

다음은 결합도와 관련된 내용이다. 보기에 알맞는 답을 골라 작성하시오.

(1) 다른 모듈 내부에 있는 변수나 기능을 다른 모듈에서 사용하는 경우의 결합도

(2) 모듈 간의 인터페이스로 배열이나 오브젝트, 자료구조 등이 전달되는 경우의 결합도

(3) 파라미터가 아닌 모듈 밖에 선언되어 있는 전역 변수를 참조하고 전역 변수를 갱신하는 식으로 상호작용하는 경우의 결합도

[보기]
ㄱ. 자료 결합도 ㄴ. 스탬프 결합도 ㄷ. 제어 결합도 ㄹ. 공통 결합도 ㅁ. 내용 결합도 ㅂ. 외부 결합도

정답

  • (1) ㅁ. 내용 결합도 (Content Coupling)
  • (2) ㄴ. 스탬프 결합도 (Stamp Coupling)
  • (3) ㄹ. 공통 결합도 (Common Coupling)

해설

결합도 설명 예시 강도
내용 결합도 다른 모듈 내부 직접 접근 모듈A가 모듈B의 내부 변수 직접 사용 가장 강함
공통 결합도 전역 변수 공유 여러 모듈이 같은 전역 변수 사용 강함
외부 결합도 외부 선언 공유 여러 모듈이 같은 외부 선언 사용 강함
제어 결합도 제어 플래그 전달 모듈A가 모듈B의 동작 제어 중간
스탬프 결합도 자료구조 전달 배열, 객체 등 구조체 전달 약함
자료 결합도 기본 자료형 전달 int, char 등 단순 값 전달 가장 약함

결합도 강도 순서:

내용 > 공통 > 외부 > 제어 > 스탬프 > 자료
(강함)                    (약함)

예시 코드:

내용 결합도 (Content Coupling):

// 모듈 A
int x = 10;

// 모듈 B (내용 결합도 - 나쁨)
extern int x;  // 모듈 A의 내부 변수 직접 접근
x = 20;        // 직접 수정

공통 결합도 (Common Coupling):

// 전역 변수
int global_var = 0;

// 모듈 A
void funcA() {
    global_var = 10;  // 전역 변수 사용
}

// 모듈 B
void funcB() {
    global_var = 20;  // 같은 전역 변수 사용
}

스탬프 결합도 (Stamp Coupling):

// 구조체 정의
struct Student {
    int id;
    char name[20];
};

// 모듈 A
void process(struct Student s) {  // 구조체 전달
    // ...
}

// 모듈 B
struct Student student;
process(student);  // 구조체 전달

13. Java 상속 문제

문제

다음은 Java 코드에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

public class Main {
    public static void main(String[] args) {
        new Child();
        System.out.println(Parent.total);
    }
}

class Parent {
    static int total = 0;
    int v = 1;

    public Parent() {
        total += (++v);
        show();    
    }

    public void show() {
        total += total;
    }
}

class Child extends Parent {
    int v = 10;

    public Child() {
        v += 2;
        total += v++;
        show();
    }

    @Override
    public void show() {
        total += total * 2;
    }
}

정답

54

해설

실행 순서:

단계 코드 실행 내용 total Parent.v Child.v
초기 - total=0 0 - -
1 new Child() Child 객체 생성 시작 0 - -
2 super() (자동) Parent 생성자 호출 0 1 -
3 ++v Parent.v = 2 0 2 -
4 total += 2 total = 0 + 2 = 2 2 2 -
5 show() Parent.show() 호출 2 2 -
6 total += total total = 2 + 2 = 4 4 2 -
7 v += 2 Child.v = 10 + 2 = 12 4 2 12
8 total += v++ total = 4 + 12 = 16, v=13 16 2 13
9 show() Child.show() 호출 (오버라이드) 16 2 13
10 total += total * 2 total = 16 + 32 = 48 48 2 13
11 System.out.println(...) 출력: 48 48 - -

상세 분석:

1. Parent 생성자 실행:

public Parent() {
    total += (++v);  // v는 Parent.v (1 → 2)
                     // total = 0 + 2 = 2
    show();          // Parent.show() 호출
}

2. Parent.show() 실행:

public void show() {
    total += total;  // total = 2 + 2 = 4
}

3. Child 생성자 실행:

public Child() {
    v += 2;          // v는 Child.v (10 → 12)
    total += v++;     // total = 4 + 12 = 16
                      // v = 13
    show();          // Child.show() 호출 (오버라이드)
}

4. Child.show() 실행 (오버라이드):

@Override
public void show() {
    total += total * 2;  // total = 16 + 32 = 48
}

변수 구분:

  • Parent.v: 부모 클래스의 인스턴스 변수 (값: 2)
  • Child.v: 자식 클래스의 인스턴스 변수 (값: 13)
  • total: 정적 변수 (클래스 변수)

핵심 포인트:

  • 생성자는 부모부터 실행됨
  • show()는 오버라이드되어 Child의 메서드가 호출됨
  • v는 각 클래스의 인스턴스 변수 (별도 존재)

최종 total 값:

초기: 0
Parent 생성자: +2 → 2
Parent.show(): +2 → 4
Child 생성자: +12 → 16
Child.show(): +32 → 48

14. 디자인 패턴 문제

문제

아래는 디자인 패턴에 대한 설명이다. 알맞는 답을 보기에 골라 작성하시오.

서로 다른 인터페이스를 가진 클래스들을 연결해 사용 가능하게 한다.

기존 클래스(Adaptee)를 원하는 인터페이스(Target)에 맞게 변환하는 어댑터(Adapter)를 만든다.

기존 클래스를 감싸서(wrapper) 인터페이스를 변환해주는 역할을 한다.

정답

Adapter Pattern (어댑터 패턴)

해설

패턴 목적 구조
어댑터 패턴 호환되지 않는 인터페이스를 연결 Adaptee → Adapter → Target
데코레이터 패턴 기능 추가 Component → Decorator
퍼사드 패턴 복잡한 서브시스템 단순화 Facade → Subsystem
프록시 패턴 접근 제어 Client → Proxy → RealSubject

어댑터 패턴 구조:

Client
  │
  │ 요청
  ↓
Target (인터페이스)
  ↑
  │ 구현
Adapter (어댑터)
  │
  │ 사용
  ↓
Adaptee (기존 클래스)

예시 코드:

// Target: 원하는 인터페이스
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// Adaptee: 기존 클래스
class AdvancedMediaPlayer {
    void playVlc(String fileName) { }
    void playMp4(String fileName) { }
}

// Adapter: 어댑터
class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer advancedPlayer;

    public MediaAdapter(String audioType) {
        if (audioType.equals("vlc")) {
            advancedPlayer = new VlcPlayer();
        } else if (audioType.equals("mp4")) {
            advancedPlayer = new Mp4Player();
        }
    }

    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equals("vlc")) {
            advancedPlayer.playVlc(fileName);
        } else if (audioType.equals("mp4")) {
            advancedPlayer.playMp4(fileName);
        }
    }
}

사용 예시:

기존 시스템: VLC 플레이어 (playVlc 메서드)
새 시스템: MediaPlayer 인터페이스 (play 메서드)
→ MediaAdapter가 중간에서 변환

장점:

  • 기존 코드 재사용 가능
  • 클라이언트와 Adaptee 분리
  • 인터페이스 호환성 확보

15. 문장 커버리지 문제

문제

문장(Statement) 커버리지 테스트를 수행하려고 한다. 코드를 아래의 제어 흐름도 빈칸에 연결되도록 작성하고 문장 커버리지 순서대로 작성하시오.

int Main(int b[], int m, int x) {
    int a = 0;
    while (a < m || b[a] < x) {
        if (b[a] < 0)
            b[a] = -b[a];
        a++;
    }
    return 1;
}

정답

  • int a = 0
  • a < m || b[a] < x
  • b[a] < 0
  • b[a] = -b[a];
  • a++;
  • return 1;
  • ③ → ④ → ⑤ → ② → ⑥

해설

제어 흐름도:

시작
  ↓
① int a = 0
  ↓
② a < m || b[a] < x
  ├─ Yes ─→ ③ b[a] < 0
  │           ├─ Yes ─→ ④ b[a] = -b[a];
  │           └─ No  ─→ ⑤ a++;
  │                       ↓
  └─ No ───────────────→ ⑥ return 1;

문장 커버리지:

  • 모든 문장을 최소 한 번씩 실행해야 함
  • 조건문의 True/False 경로 모두 실행

테스트 케이스:

테스트 케이스 입력 실행 경로 커버리지
TC1 b=[-1, 2], m=2, x=5 ①→②(Yes)→③(Yes)→④→⑤→②(Yes)→③(No)→⑤→②(No)→⑥ 모든 문장 실행

실행 순서 (TC1):

1. ① int a = 0
2. ② a < m || b[a] < x  (0 < 2 || -1 < 5) = true
3. ③ b[a] < 0  (-1 < 0) = true
4. ④ b[a] = -b[a]  (b[0] = 1)
5. ⑤ a++  (a = 1)
6. ② a < m || b[a] < x  (1 < 2 || 2 < 5) = true
7. ③ b[a] < 0  (2 < 0) = false
8. ⑤ a++  (a = 2)
9. ② a < m || b[a] < x  (2 < 2 || ?) = false
10. ⑥ return 1

문장 커버리지 순서:

1 → 2 → 3 → 4 → 5 → 2 → 3 → 5 → 2 → 6

간단히 표현:

③ → ④ → ⑤ → ② → ⑥

각 문장 설명:

  • ①: 변수 초기화
  • ②: while 조건 (루프 진입 조건)
  • ③: if 조건 (음수 체크)
  • ④: 음수를 양수로 변환
  • ⑤: 인덱스 증가
  • ⑥: 함수 종료

16. Java 재귀 함수 문제

문제

다음은 Java 코드에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

public class Main {
    public static void main(String[] args) {
        int[] data = {3, 5, 8, 12, 17};
        System.out.println(func(data, 0, data.length - 1));
    }

    static int func(int[] a, int st, int end) {
        if (st >= end) return 0;
        int mid = (st + end) / 2;
        return a[mid] + Math.max(func(a, st, mid), func(a, mid + 1, end));
    } 
}

정답

20

해설

재귀 호출 트리:

func([3,5,8,12,17], 0, 4)
├─ mid = 2, a[2] = 8
├─ func([3,5,8,12,17], 0, 2)
│  ├─ mid = 1, a[1] = 5
│  ├─ func([3,5,8,12,17], 0, 1)
│  │  ├─ mid = 0, a[0] = 3
│  │  ├─ func([3,5,8,12,17], 0, 0) → 0 (st >= end)
│  │  └─ func([3,5,8,12,17], 1, 1) → 0 (st >= end)
│  │  └─ return 3 + max(0, 0) = 3
│  └─ func([3,5,8,12,17], 2, 2) → 0 (st >= end)
│  └─ return 5 + max(3, 0) = 8
└─ func([3,5,8,12,17], 3, 4)
   ├─ mid = 3, a[3] = 12
   ├─ func([3,5,8,12,17], 3, 3) → 0 (st >= end)
   └─ func([3,5,8,12,17], 4, 4) → 0 (st >= end)
   └─ return 12 + max(0, 0) = 12

최종: 8 + max(8, 12) = 8 + 12 = 20

단계별 계산:

호출 st end mid a[mid] 왼쪽 재귀 오른쪽 재귀 결과
func(0,4) 0 4 2 8 func(0,2)=8 func(3,4)=12 8+12=20
func(0,2) 0 2 1 5 func(0,1)=3 func(2,2)=0 5+3=8
func(0,1) 0 1 0 3 func(0,0)=0 func(1,1)=0 3+0=3
func(3,4) 3 4 3 12 func(3,3)=0 func(4,4)=0 12+0=12

상세 계산:

func(0, 1):

st=0, end=1
mid = (0+1)/2 = 0
a[0] = 3
func(0,0) = 0 (st >= end)
func(1,1) = 0 (st >= end)
return 3 + max(0, 0) = 3

func(0, 2):

st=0, end=2
mid = (0+2)/2 = 1
a[1] = 5
func(0,1) = 3
func(2,2) = 0 (st >= end)
return 5 + max(3, 0) = 8

func(3, 4):

st=3, end=4
mid = (3+4)/2 = 3
a[3] = 12
func(3,3) = 0 (st >= end)
func(4,4) = 0 (st >= end)
return 12 + max(0, 0) = 12

func(0, 4):

st=0, end=4
mid = (0+4)/2 = 2
a[2] = 8
func(0,2) = 8
func(3,4) = 12
return 8 + max(8, 12) = 8 + 12 = 20

알고리즘 분석:

  • 분할 정복 방식
  • 배열을 반으로 나누어 재귀 호출
  • 각 구간의 중간값을 더함
  • 왼쪽과 오른쪽 중 큰 값을 선택

17. 파이썬 트리 문제

문제

다음은 파이썬에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

class Node:
    def __init__(self, value):
        self.value = value
        self.children = []

def tree(li):
    nodes = [Node(i) for i in li]
    for i in range(1, len(li)):
        nodes[(i - 1) // 2].children.append(nodes[i])
    return nodes[0]

def calc(node, level=0):
    if node is None:
        return 0
    return (node.value if level % 2 == 1 else 0) + sum(calc(n, level + 1) for n in node.children)

li = [3, 5, 8, 12, 15, 18, 21]

root = tree(li)

print(calc(root))

정답

13

해설

트리 구조 생성:

i (i-1)//2 부모 인덱스 자식 인덱스 트리 구조
1 0 nodes[0] nodes[1] 3 → 5
2 0 nodes[0] nodes[2] 3 → 8
3 1 nodes[1] nodes[3] 5 → 12
4 1 nodes[1] nodes[4] 5 → 15
5 2 nodes[2] nodes[5] 8 → 18
6 2 nodes[2] nodes[6] 8 → 21

트리 구조:

        3 (level 0)
       / \
      5   8 (level 1)
     / \ / \
   12 15 18 21 (level 2)

calc 함수 실행:

노드 level level%2 조건 자식 합계 결과
3 0 0 level%2==0 0 5+8=13 0+13=13
5 1 1 level%2==1 5 12+15=27 5+27=32
8 1 1 level%2==1 8 18+21=39 8+39=47
12 2 0 level%2==0 0 0 0
15 2 0 level%2==0 0 0 0
18 2 0 level%2==0 0 0 0
21 2 0 level%2==0 0 0 0

재귀 호출 트리:

calc(3, 0)
├─ level=0, level%2=0 → 값=0
├─ calc(5, 1)
│  ├─ level=1, level%2=1 → 값=5
│  ├─ calc(12, 2) → level=2, 값=0
│  └─ calc(15, 2) → level=2, 값=0
│  └─ return 5 + 0 + 0 = 5
└─ calc(8, 1)
   ├─ level=1, level%2=1 → 값=8
   ├─ calc(18, 2) → level=2, 값=0
   └─ calc(21, 2) → level=2, 값=0
   └─ return 8 + 0 + 0 = 8

최종: 0 + 5 + 8 = 13

계산 과정:

level 0 (짝수): 값 무시
level 1 (홀수): 값 사용 (5, 8)
level 2 (짝수): 값 무시

합계: 5 + 8 = 13

핵심 포인트:

  • (i-1)//2: 완전 이진 트리 부모 인덱스 계산
  • level % 2 == 1: 홀수 레벨만 값 사용
  • 재귀적으로 모든 노드 탐색

18. C언어 연결 리스트 문제

문제

다음은 C언어에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

#include <stdio.h>   
#include <stdlib.h>  

typedef struct Data {
    int value;
    struct Data *next;
} Data;

Data* insert(Data* head, int value) {
    Data* new_node = (Data*)malloc(sizeof(Data));
    new_node->value = value;
    new_node->next = head;
    return new_node;
}

Data* reconnect(Data* head, int value) {
    if (head == NULL || head->value == value) return head;
    Data *prev = NULL, *curr = head;
    while (curr != NULL && curr->value != value) {
        prev = curr;
        curr = curr->next;
    }

    if (curr != NULL && prev != NULL) {
        prev->next = curr->next;
        curr->next = head;
        head = curr;
    }
    return head;
}

int main() {
    Data *head = NULL, *curr;
    for (int i = 1; i <= 5; i++)
        head = insert(head, i);
    head = reconnect(head, 3);
    for (curr = head; curr != NULL; curr = curr->next)
        printf("%d", curr->value);
    return 0; 
}

정답

35421

해설

insert 함수 동작:

i head 새 노드 리스트 상태
1 NULL 1 1 → NULL
2 1 2 2 → 1 → NULL
3 2→1 3 3 → 2 → 1 → NULL
4 3→2→1 4 4 → 3 → 2 → 1 → NULL
5 4→3→2→1 5 5 → 4 → 3 → 2 → 1 → NULL

insert 후 리스트:

head → 5 → 4 → 3 → 2 → 1 → NULL

reconnect 함수 동작:

단계 설명 리스트 상태
초기 head → 5 → 4 → 3 → 2 → 1 -
1 value=3 찾기 prev=4, curr=3
2 prev->next = curr->next 4 → 2 (3 제거)
3 curr->next = head 3 → 5
4 head = curr head = 3

reconnect 과정 상세:

초기: head → 5 → 4 → 3 → 2 → 1 → NULL
                    ↑
                  찾는 값

1. prev = NULL, curr = head (5)
2. curr->value (5) != 3 → prev = 5, curr = 4
3. curr->value (4) != 3 → prev = 4, curr = 3
4. curr->value (3) == 3 → 루프 종료

prev = 4, curr = 3

5. prev->next = curr->next
   4 → 2 (3을 리스트에서 제거)

6. curr->next = head
   3 → 5

7. head = curr
   head = 3

최종: head → 3 → 5 → 4 → 2 → 1 → NULL

시각적 표현:

Before reconnect:
5 → 4 → 3 → 2 → 1
        ↑
      찾는 값

After reconnect:
3 → 5 → 4 → 2 → 1
↑
head (맨 앞으로 이동)

핵심 포인트:

  • insert: 리스트 앞에 삽입 (역순 생성)
  • reconnect: 특정 값을 찾아 맨 앞으로 이동
  • 연결 리스트 재구성 알고리즘

19. C언어 비트 연산 문제

문제

다음은 C언어에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

#include <stdio.h>

typedef struct student {
    char* name;
    int score[3];
} Student;

int dec(int enc) {
    return enc & 0xA5;
}

int sum(Student* p) {
    return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}

int main() {
    Student s[2] = { "Kim", {0xA0, 0xA5, 0xDB}, "Lee", {0xA0, 0xED, 0x81} };
    Student* p = s;
    int result = 0;

    for (int i = 0; i < 2; i++) {
        result += sum(&s[i]);
    }
    printf("%d", result);
    return 0;
}

정답

908

해설

비트 연산 분석:

16진수 2진수 0xA5 (2진수) AND 결과 10진수
0xA0 A0 10100000 10100101 10100000 160
0xA5 A5 10100101 10100101 10100101 165
0xDB DB 11011011 10100101 10000001 129
0xED ED 11101101 10100101 10100101 165
0x81 81 10000001 10100101 10000001 129

0xA5 비트 마스크:

0xA5 = 10100101 (2진수)
      = 128 + 32 + 4 + 1
      = 165 (10진수)

dec 함수 동작:

int dec(int enc) {
    return enc & 0xA5;  // 비트 AND 연산
}

각 학생 계산:

Kim 학생:

score[0] = 0xA0
dec(0xA0) = 0xA0 & 0xA5 = 10100000 & 10100101 = 10100000 = 160

score[1] = 0xA5
dec(0xA5) = 0xA5 & 0xA5 = 10100101 & 10100101 = 10100101 = 165

score[2] = 0xDB
dec(0xDB) = 0xDB & 0xA5 = 11011011 & 10100101 = 10000001 = 129

sum(Kim) = 160 + 165 + 129 = 454

Lee 학생:

score[0] = 0xA0
dec(0xA0) = 0xA0 & 0xA5 = 10100000 & 10100101 = 10100000 = 160

score[1] = 0xED
dec(0xED) = 0xED & 0xA5 = 11101101 & 10100101 = 10100101 = 165

score[2] = 0x81
dec(0x81) = 0x81 & 0xA5 = 10000001 & 10100101 = 10000001 = 129

sum(Lee) = 160 + 165 + 129 = 454

최종 결과:

result = sum(Kim) + sum(Lee)
       = 454 + 454
       = 908

비트 AND 연산 규칙:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

비트 마스크 사용:

  • 0xA5는 마스크로 사용
  • 특정 비트만 추출하는 용도
  • 암호화/복호화에서 사용 가능

20. Java 메서드 오버로딩 문제

문제

다음은 Java 코드에 대한 문제이다. 아래 코드를 확인하여 알맞는 출력값을 작성하시오.

public class Main {
  public static void main(String[] args) {
    System.out.println(calc("5"));
  }

  static int calc(int value) {
    if (value <= 1) return value;
    return calc(value - 1) + calc(value - 2);
  }

  static int calc(String str) {
    int value = Integer.valueOf(str);
    if (value <= 1) return value;
    return calc(value - 1) + calc(value - 3);
  }
}

정답

4

해설

메서드 오버로딩:

  • calc(int): 피보나치 수열 (n-1, n-2)
  • calc(String): 다른 수열 (n-1, n-3)

실행 흐름:

단계 호출 매개변수 조건 계산 반환
1 calc("5") "5" value=5 > 1 calc(4) + calc(2) -
2 calc(4) 4 4 > 1 calc(3) + calc(1) -
3 calc(3) 3 3 > 1 calc(2) + calc(0) -
4 calc(2) 2 2 > 1 calc(1) + calc(-1) -
5 calc(1) 1 1 ≤ 1 - 1
6 calc(-1) -1 -1 ≤ 1 - -1
7 calc(2) - - 1 + (-1) = 0 0
8 calc(0) 0 0 ≤ 1 - 0
9 calc(3) - - 0 + 0 = 0 0
10 calc(1) 1 1 ≤ 1 - 1
11 calc(4) - - 0 + 1 = 1 1
12 calc(2) 2 2 > 1 calc(1) + calc(-1) -
13 calc(1) 1 1 ≤ 1 - 1
14 calc(-1) -1 -1 ≤ 1 - -1
15 calc(2) - - 1 + (-1) = 0 0
16 calc("5") - - 1 + 0 = 1 1

재귀 호출 트리:

calc("5")
├─ value = 5
├─ calc(4)  [calc(int)]
│  ├─ calc(3)
│  │  ├─ calc(2)
│  │  │  ├─ calc(1) → 1
│  │  │  └─ calc(-1) → -1
│  │  │  └─ return 1 + (-1) = 0
│  │  └─ calc(0) → 0
│  │  └─ return 0 + 0 = 0
│  └─ calc(1) → 1
│  └─ return 0 + 1 = 1
└─ calc(2)  [calc(int)]
   ├─ calc(1) → 1
   └─ calc(-1) → -1
   └─ return 1 + (-1) = 0

최종: 1 + 0 = 1

상세 계산:

calc(2) - calc(int):

calc(2)
├─ 2 > 1 → 재귀 호출
├─ calc(1) = 1
└─ calc(2-2) = calc(0) = 0
└─ return 1 + 0 = 1

다시 계산 (정정):

calc("5") 실행:

calc("5")
├─ value = Integer.valueOf("5") = 5
├─ 5 > 1 → 재귀 호출
├─ calc(5-1) = calc(4)
│  └─ calc(int) 호출
│  └─ 피보나치: calc(3) + calc(2)
│     ├─ calc(3) = calc(2) + calc(1) = 1 + 1 = 2
│     └─ calc(2) = calc(1) + calc(0) = 1 + 0 = 1
│  └─ return 2 + 1 = 3
└─ calc(5-3) = calc(2)
   └─ calc(int) 호출
   └─ 피보나치: calc(1) + calc(0) = 1 + 0 = 1
└─ return 3 + 1 = 4

최종 정답: 4

핵심 포인트:

  • calc("5")calc(String) 호출
  • calc(value-1)calc(value-3)calc(int) 호출 (오버로딩)
  • calc(int)는 피보나치 수열 계산
  • calc(String)은 다른 수열 계산

전체 문제 요약

문제 주제 난이도 핵심 개념
1 네트워크 보안 세션 하이재킹
2 제약조건 도메인, 개체, 참조
3 CRC 순환 중복 검사
4 악성코드 스캐어웨어
5 Java 예외 예외 처리, finally
6 ARP/RARP 주소 변환 프로토콜
7 SQL 조인 내부 조인
8 DB 용어 차수, 기수, 외래키, 도메인
9 서브넷 서브넷 마스크, 브로드캐스트
10 C 배열 배열 삽입 알고리즘
11 C 2차원 배열 2차원 배열, 인덱스 계산
12 결합도 모듈 결합도 종류
13 Java 상속 상속, 오버라이드, 정적 변수
14 디자인 패턴 어댑터 패턴
15 테스트 커버리지 문장 커버리지
16 Java 재귀 분할 정복, 재귀
17 파이썬 트리 트리 구조, 재귀
18 C 연결 리스트 연결 리스트 조작
19 C 비트 연산 비트 AND 연산
20 Java 오버로딩 메서드 오버로딩, 재귀

작성일: 2026-01-30
시험: 2025년 정보처리기사 실기 1회 복원 문제
용도: 정보처리기사 실기 시험 대비 자료