연습17(주의)-마지막도 유의

류한선·2025년 7월 1일

실기연습-2

목록 보기
65/95

좋아! 정보처리기사 실기 시험에서는 기본 문법을 알고 있다고 착각하면 틀리기 쉬운 문제, 즉 "기초 개념 + 트릭(함정)" 문제들이 자주 출제돼. 그래서 다음과 같은 문제를 준비했어:


🔍 문제 1. 자바 변수와 참조의 이해 (난이도: 중)

다음 Java 코드를 실행했을 때 출력 결과를 구하시오.

public class Main {
    public static void main(String[] args) {
        int[] a = {1, 2, 3};
        int[] b = a;
        
        b[0] = 100;

        changeArray(a);

        System.out.println(a[0]);
    }

    public static void changeArray(int[] arr) {
        arr = new int[]{9, 9, 9};
        arr[0] = 500;
    }
}

✅ 보기 (출력 결과는?)

A. 1
B. 100
C. 500
D. 9


🧠 풀이 및 해설

  1. int[] a = {1, 2, 3};
    a[1, 2, 3]을 가리킴
    → 그림: a --> [1, 2, 3]

  2. int[] b = a;
    b도 같은 배열을 참조함
    → 그림: b --> [1, 2, 3] (a와 동일한 객체를 참조)

  3. b[0] = 100;
    ba와 같은 배열을 참조하므로 a[0] = 100이 됨
    → 그림: a --> [100, 2, 3]

  4. changeArray(a); 호출 시:

    • arr = a 이므로 arra를 참조하게 됨
    • 하지만 그 다음 줄 arr = new int[]{9, 9, 9};에서 새로운 배열을 생성하고 참조를 arr이 그것으로 바꿈
      → 이건 arr 변수만 새로운 배열을 가리키게 되지, a는 여전히 [100, 2, 3]을 가리킴
    • arr[0] = 500; → 이건 새로 만들어진 [9, 9, 9] → [500, 9, 9]이 되는 것이고, a에는 영향 없음
  5. 최종적으로 System.out.println(a[0]);a[0] = 100 이므로 100 출력


✅ 정답: B. 100


💡 핵심 포인트 (시험에 자주 나오는 함정!)

  • 자바에서 배열이나 객체는 참조 타입이다.
  • 메서드에서 참조를 새로 바꾸는 것(arr = new ...) 은 원본에 영향을 주지 않음!
  • arr[0] = ... 과 같이 내용을 수정하는 것만 원본 영향을 줌

🤔 연습용 비슷한 함정 포인트 (자주 출제)

  1. String 은 불변이라 s = "hello"; s.toUpperCase(); 만 하면 변화 없음
  2. ArrayList<Integer> a = b;a.add() 하면 b도 영향을 받음
  3. call-by-value / call-by-reference 개념을 헷갈리게 만드는 문제
  4. int[] arrint arr[] 의 차이는 없음 → 오답 유도 가능성 있음

좋아! 그럼 정보처리기사 실기에서 기본 문법과 로직에 숨어 있는 트릭을 노린 문제를 3개 출제하고, 각 문제에 대해 왜 틀리기 쉬운지, 정답은 왜 그게 되는지, 관련 개념은 무엇인지까지 모두 해설해줄게.


✅ 문제 1. 조건문과 비교 연산자 함정 (Java)

다음 코드의 출력 결과는?

public class Main {
    public static void main(String[] args) {
        int x = 10;
        int y = 20;

        if (x + y == 10)
            System.out.println("A");
        if (x + y == 30);
            System.out.println("B");
    }
}

❓ 보기

A. A만 출력
B. B만 출력
C. A, B 둘 다 출력
D. 아무것도 출력 안 됨


✅ 정답: B. B만 출력


🔍 해설

  1. if (x + y == 10)

    • x=10, y=20 → x+y=30 → 30==10 → ❌ 조건 불만족
    • → A는 출력 안 됨
  2. if (x + y == 30); ← 여기 주의!

    • 조건이 참이어도 세미콜론 ; 때문에 if문이 "끝나버림"
    • 즉, if (조건); 이거는 아무 코드도 실행 안 한다는 뜻임
    • 그리고 나서 System.out.println("B"); 이건 무조건 실행

🧠 핵심 포인트

  • if (조건); → 세미콜론 때문에 조건과 상관없이 if문 종료됨
  • 이 문제는 들여쓰기와 오해를 유도해서 시험에 자주 등장

✅ 문제 2. 파이썬 mutable default argument 트랩

다음 코드 실행 결과는?

def append_val(val, lst=[]):
    lst.append(val)
    return lst

print(append_val(1))
print(append_val(2))
print(append_val(3))

❓ 보기

A.

[1]  
[2]  
[3]

B.

[1]  
[1, 2]  
[1, 2, 3]

C.

[1]  
[1, 2]  
[3]

D.

[1]  
[1]  
[1]

✅ 정답: B. [1], [1, 2], [1, 2, 3]


🔍 해설

  • lst=[]기본값이 한 번만 만들어짐
  • 함수가 여러 번 호출되어도, 기존 리스트 객체가 재사용

실제로는 이런 식으로 동작함:

  1. append_val(1) → lst: [] → append(1) → [1]
  2. append_val(2) → lst: [1] → append(2) → [1, 2]
  3. append_val(3) → lst: [1, 2] → append(3) → [1, 2, 3]

🧠 핵심 포인트

  • 파이썬 함수에서 기본 인자값에 mutable 객체를 쓰면 재사용됨!
  • 리스트, 딕셔너리 등을 기본값으로 쓰지 말 것

✅ 문제 3. C 언어 포인터 헷갈리게 하는 구조체 문제

다음 C 코드의 출력 결과는?

#include <stdio.h>

typedef struct {
    int x;
} Point;

void change(Point p) {
    p.x = 999;
}

int main() {
    Point a = {100};
    change(a);
    printf("%d\n", a.x);
    return 0;
}

❓ 보기

A. 999
B. 0
C. 쓰레기값
D. 100


✅ 정답: D. 100


🔍 해설

  • change(a)값 복사(Call by value) 이기 때문에
    구조체 전체가 복사본으로 함수에 전달됨
  • 즉, pa의 복사 → p.x = 999 해도 a.x영향 없음

🧠 핵심 포인트

  • 구조체는 함수에 넘기면 기본적으로 복사됨 (포인터가 아님)
  • 원본을 수정하려면 change(Point *p) 로 포인터 전달해야 함

✍️ 요약

개념함정기억할 점
Java 조건문세미콜론(;)if (조건); 은 실행 안 됨
Python 함수mutable default리스트/딕트는 디폴트값으로 쓰면 안 됨
C 구조체복사 전달원본 수정하려면 포인터 사용해야 함

좋아, 그럼 정보처리기사 실기 대비용으로
Java + C + Python
기초 문법 + 자료구조 + 함수 호출 + 포인터 + 반복문 + 참조 + 예외처리 + 트랩
모든 걸 싹 다 엮은 트랩 문제들을 6문제 출제할게.
각 문제는 반드시 틀리게 유도하는 트릭을 포함하고,
풀이+해설+핵심 개념 정리까지 해준다.


🔥 [문제 1] Java - ArrayList 참조 트릭

import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Integer> a = new ArrayList<>();
        a.add(1);
        a.add(2);

        List<Integer> b = a;
        b.add(3);

        a = new ArrayList<>();
        a.add(100);

        System.out.println(b);
    }
}

보기

A. [1, 2]
B. [1, 2, 3]
C. [100]
D. [3]


✅ 정답: B. [1, 2, 3]

✅ 해설:

  • b = a → b는 a와 같은 ArrayList 참조
  • b.add(3)a도 바뀜: [1, 2, 3]
  • a = new ArrayList<>() → 이제 a는 다른 리스트를 참조함. b는 여전히 예전 리스트
  • 따라서 System.out.println(b)[1, 2, 3]

🔥 [문제 2] Python - 리스트 복사 vs 얕은 복사(체크)

a = [[1, 2], [3, 4]]
b = a[:]
b[0][0] = 100
print(a[0][0])

보기

A. 1
B. 100
C. 오류 발생
D. None


✅ 정답: B. 100

✅ 해설:

  • b = a[:]얕은 복사임. 리스트 객체는 새로 복사하지만, 내부 객체(리스트)는 같은 참조
  • 그래서 b[0][0] = 100a[0][0] = 100도 같이 바뀜

🔥 [문제 3] C - 포인터와 배열 혼동 트랩

#include <stdio.h>

void change(int arr[]) {
    arr[0] = 999;
}

int main() {
    int a[3] = {1, 2, 3};
    change(a);
    printf("%d\n", a[0]);
    return 0;
}

보기

A. 1
B. 999
C. 쓰레기값
D. 컴파일 오류


✅ 정답: B. 999

✅ 해설:

  • 배열은 함수에 넘기면 포인터처럼 작동함
  • arra의 시작 주소 → arr[0] = 999a[0]에 바로 반영됨

🔥 [문제 4] Java - 문자열 불변성 트릭

public class Main {
    public static void main(String[] args) {
        String s = "hello";
        s.toUpperCase();
        System.out.println(s);
    }
}

보기

A. HELLO
B. hello
C. null
D. 컴파일 오류


✅ 정답: B. hello

✅ 해설:

  • String불변(immutable). s.toUpperCase()새 문자열을 리턴하지만 저장 안 했음
  • 원래 s는 그대로 "hello"

🔥 [문제 5] Python - 함수 내 전역 변수 트랩

x = 10

def func():
    x = x + 1
    return x

print(func())

보기

A. 11
B. 10
C. 오류
D. None


✅ 정답: C. 오류

✅ 해설:

  • x = x + 1 → 함수 내부에서 x를 로컬 변수로 판단
  • 하지만 x에 값이 없기 때문에 UnboundLocalError 발생
  • 해결하려면 global x 선언 필요

🔥 [문제 6] C - 구조체 포인터 접근 혼동

#include <stdio.h>

typedef struct {
    int value;
} Data;

void change(Data *p) {
    p->value = 123;
}

int main() {
    Data d = {5};
    change(&d);
    printf("%d\n", d.value);
}

보기

A. 5
B. 123
C. 컴파일 오류
D. 쓰레기값


✅ 정답: B. 123

✅ 해설:

  • &d를 넘기므로 pd의 주소
  • p->value = 123 → 원본 구조체 d의 값 변경됨

🧠 총정리표

문제핵심 트릭요점 정리
1 (Java)참조 재할당a = new는 b에 영향 없음
2 (Python)얕은 복사내부 리스트는 같은 객체
3 (C)배열 포인터배열은 주소 전달됨
4 (Java)불변 객체toUpperCase() 결과 저장 안 함
5 (Python)전역 vs 지역x = x + 1은 UnboundLocalError
6 (C)구조체 포인터p->value는 원본 수정 가능

좋아! 그럼 이번엔 정보처리기사 실기 스타일로
💣 기본기 부족하면 틀리는 트랩 문제 10개
➡ Java / C / Python / SQL 등 다양한 언어 + 자료형 + 흐름 제어 + 예외 상황 + 참조 트릭 + 로직 꼬기
객관식 + 틀리게 유도하는 오답 보기 포함
➡ 각 문제에 정답 + 왜 틀리는지 해설 + 핵심 개념 정리 포함


🔥 [문제 1] Java - 조건문 중괄호 생략 트릭

int x = 10;
if (x > 5)
    System.out.println("크다");
    System.out.println("정말?");

출력 결과는?

A.

크다  
정말?

B.

정말?

C.

크다

D. 아무것도 출력되지 않음


정답: A

🧠 해설:
중괄호 {} 가 없을 경우, if문은 한 줄만 실행됨.
두 번째 System.out.println("정말?");은 조건문 바깥 코드라 항상 실행됨.


🔥 [문제 2] Python - 리스트 기본값 트랩

def f(x, lst=[]):
    lst.append(x)
    return lst

print(f(1))
print(f(2))

A. [1], [2]
B. [1], [1, 2]
C. [1, 2], [2]
D. 오류 발생


정답: B

🧠 해설:
함수 인자 lst=[]처음 한 번만 생성됨.
그래서 lst가 함수 호출 간에 공유되어 누적됨.
mutable default argument 트랩


🔥 [문제 3] C - 함수 인자 포인터 복사

void update(int *p) {
    p = NULL;
}

int main() {
    int x = 100;
    int *ptr = &x;
    update(ptr);
    printf("%d\n", *ptr);
}

A. 0
B. 오류
C. 100
D. 쓰레기값


정답: C

🧠 해설:
p = NULL; 은 복사된 포인터 p만 변경.
ptr 자체는 영향 없음. 여전히 x를 가리킴.


🔥 [문제 4] Java - equals와 == 비교

String a = new String("hi");
String b = new String("hi");
System.out.println(a == b);

A. true
B. false
C. 컴파일 오류
D. null


정답: B

🧠 해설:
new String() 으로 만든 객체는 서로 다른 참조 주소
== 은 주소 비교 → false
내용 비교는 .equals() 를 써야 함


🔥 [문제 5] Python - 변수 범위 트랩

x = 10

def g():
    print(x)
    x = 20

g()

A. 10
B. 20
C. 오류 발생
D. None


정답: C (UnboundLocalError)

🧠 해설:
x = 20 이 있기 때문에 x는 지역변수로 간주됨
그런데 print(x)가 그 전에 있어 초기화 안 된 변수 사용 → 오류


🔥 [문제 6] SQL - WHERE vs HAVING

다음 중 집계함수를 필터링할 때 사용하는 절은?

A. WHERE
B. GROUP BY
C. HAVING
D. ORDER BY


정답: C

🧠 해설:
WHERE집계되기 전에 필터링
HAVING집계 이후 조건 처리


🔥 [문제 7] Java - 배열 전달과 재할당

public static void change(int[] arr) {
    arr = new int[]{9, 9, 9};
    arr[0] = 999;
}

public static void main(String[] args) {
    int[] nums = {1, 2, 3};
    change(nums);
    System.out.println(nums[0]);
}

A. 1
B. 9
C. 999
D. 컴파일 오류


정답: A

🧠 해설:
arr = new int[]{...}arr 변수만 재할당됨
nums 는 영향 없음 → 원래 값 유지


🔥 [문제 8] C - 배열 포인터 vs 값 복사

void set(int arr[]) {
    arr[0] = 100;
}

int main() {
    int a[3] = {1, 2, 3};
    set(a);
    printf("%d", a[0]);
}

A. 1
B. 100
C. 오류
D. 0


정답: B

🧠 해설:
배열은 함수로 넘기면 주소가 전달됨
→ 원본 변경 가능


🔥 [문제 9] Python - 리스트 깊은 복사 문제

import copy

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0][0] = 999
print(a[0][0])

A. 999
B. 1
C. None
D. 오류


정답: B

🧠 해설:
deepcopy()는 내부 리스트까지 완전히 복사
→ 원본 a는 영향 없음


🔥 [문제 10] SQL - NULL 비교 트릭

SELECT * FROM users WHERE name = NULL;

이 쿼리의 동작 결과는?

A. name이 NULL인 레코드를 찾는다
B. 오류
C. 아무 것도 반환하지 않는다
D. 모든 레코드를 반환한다


정답: C

🧠 해설:
NULL은 =, != 비교가 안 됨.
IS NULL 써야 찾을 수 있음
name = NULL 은 항상 false


📚 마무리 요약표

#핵심 트랩기억할 점
1Java 조건문 줄바꿈{} 안 쓰면 한 줄만
2Python 리스트 기본값한 번만 생성됨
3C 포인터 인자 복사원본 안 바뀜
4Java 문자열 비교== 말고 .equals()
5Python 변수 범위할당하면 지역변수로 판단
6SQL HAVING집계 이후 필터링
7Java 배열 재할당참조 변수만 바뀜
8C 배열 함수 전달포인터처럼 전달
9Python deepcopy완전 복사
10SQL NULL 비교IS NULL 사용해야 함

좋은 질문이야!
문제 3번은 이 코드였지:

void update(int *p) {
    p = NULL;
}

int main() {
    int x = 100;
    int *ptr = &x;
    update(ptr);
    printf("%d\n", *ptr);
}

너의 질문은 이거야:

"포인터는 깊은 복사여서 p = NULL; 하면 ptr도 바뀌는 거 아냐?"

🤯 하지만 실제로는 반대야!
C에서는 함수 인자로 포인터를 넘겨도 포인터 자체는 값 복사다.
"포인터가 가리키는 대상"은 바꿀 수 있지만,
"포인터 변수 자체"는 함수 안에서 바꿔도 원본 포인터에 영향이 없어.


🔬 정확한 개념 정리

1. int *ptr = &x;

  • ptr은 x의 주소를 가짐 → 예를 들어 ptr = 0x1000, x = 100

2. update(ptr);

  • ptr의 값(=주소 0x1000)을 update() 함수의 p복사해서 넘김
  • 즉, pptr의 복사본일 뿐

그래서 함수 내에서 p = NULL;을 해도,

  • 이건 p 변수의 값을 NULL로 바꾸는 것 (복사본을 변경)
  • 원래 ptr에는 아무 영향 없음

🔍 시각적으로 설명

메인 함수 (main)update 함수 내부
ptrx (100)p → 복사본 (same address initially)
p = NULLp는 이제 NULL
ptr는 그대로 x 가리킴

🔥 결론

  • 🔴 포인터를 넘기면 얕은 복사처럼 보이지만, 사실은 포인터 변수 자체가 값 복사
  • 함수 내에서 p = NULL; 해도 원본 ptr에는 영향이 없다
  • "포인터가 가리키는 값은 변경 가능", 하지만
    "포인터 변수 자체를 바꾸면 원본에 영향 없음"

💡 헷갈리는 부분 보강 예시

void update(int *p) {
    *p = 999;  // 이건 원본 값을 바꾼다!
}

void reassign(int *p) {
    int y = 777;
    p = &y;    // 이건 원본 포인터 ptr은 안 바뀐다!
}
  • *p = 999; → 원본 변수 x가 999로 바뀜 ✅
  • p = &y; → 원본 포인터는 그대로고, 함수 안에서만 바뀜 ❌

📌 요약

  • *p = ... → 가리키는 대상 변경 → 원본에 영향
  • p = ... → 포인터 변수 자체 변경 → 원본에는 영향 없음

0개의 댓글