마지막 세트. clone 과 참조 대입, super.g() 안의 f(), 로킹 단위, HRN 우선순위, V모델 4단계. 12세트의 점수 추이를 오답노트에서 본다
왜 이걸 하나 — 세트는 시험장과 같은 조건에서만 숫자가 된다. 조건은 E01 과 같다.
규칙은 E01 진단의 01절 그대로다. 시작을 누르면 150분이 돌고, 1회독 100분 · 2회독 40분 · 검토 10분으로 나눈다. 한 문항에 5분이 넘으면 답 칸을 비우고 넘어가며, 정답은 20문항을 다 적은 뒤에 연다.
이 회차의 배점은 프로그래밍 9문항(45점) · SQL·DB 4문항(20점) · SW공학 3문항(15점) · 네트워크 2문항(10점) · 보안 2문항(10점)이다. 코드 문항 수만큼 5분씩을 1회독에서 먼저 떼어 두고, 남는 시간을 용어에 쓴다. 용어는 아는 것을 바로 적고 모르는 것은 비운다 — 용어에서 고민하는 시간이 코드 한 문항의 값이다.
왜 이걸 하나 — 20문항을 한 번에 150분 안에 푸는 것 자체가 연습이다. 분야 장의 문제와 같은 문항이어도 조건이 다르다.
시작을 누르면 시계가 돌고 화면을 닫아도 이어진다. 다 적은 뒤 문항마다 정답 보기 → 맞았다 · 틀렸다를 누르면 위 막대에 점수와 분야별 결과가 모인다. 이 세트에서 채점한 기록은 분야 장의 같은 문항에도 그대로 보인다.
다음 코드의 출력을 쓰시오.
답 — 3123. static 변수 total 은 클래스에 하나뿐이라 객체를 만들 때마다 1 씩 올라 3 이고, 각 객체의 num 은 만들어질 때의 total 값 1 · 2 · 3 을 갖는다.
원리 — static 필드는 객체마다 있는 것이 아니라 클래스 전체에 하나만 있다. 생성자가 total++ 를 하면 그 하나가 커진다. 반면 num 은 인스턴스 필드라 객체마다 따로 있고, 생성자에서 num = total 로 그 순간의 값을 복사해 둔다. a 는 total 이 1 일 때, b 는 2, c 는 3 일 때 만들어졌다. Counter.total + "" 은 숫자를 문자열로 바꾸는 관용구라 그 뒤의 + 는 전부 이어 붙이기가 되어 "3" + "1" + "2" + "3" 이다.
따라가기
헷갈리는 자리 — num 도 static 처럼 보고 3333 으로 적는 것. num 은 객체별 값이다. 그리고 + "" 가 없었다면 3 + 1 + 2 + 3 = 9 로 숫자 덧셈이 되었을 것이다 — 빈 문자열의 자리가 결과를 바꾼다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 10,15. 짝수 8 + 2 = 10, 홀수 3 + 5 + 7 = 15 다.
원리 — % 는 나머지 연산이고, a[i] % 2 가 0 이면 짝수다. 반복문이 배열 5칸을 차례로 보며 짝수는 s1 에, 홀수는 s2 에 더한다. if 에 중괄호가 없으면 바로 다음 문장 하나만 if 에 속하고, else 는 그 if 의 짝이다 — 한 줄에 적혀 있어도 구조는 if { s1 += } else { s2 += } 다. printf 서식이 "%d,%d" 라 두 수 사이에 쉼표가 공백 없이 붙는다 — 서식 문자열의 글자는 그대로 찍힌다.
따라가기
헷갈리는 자리 — 서식의 쉼표를 빼고 "10 15" 로 적는 것. 시험은 출력을 글자 그대로 채점하니 서식 문자열의 구두점 · 공백을 그대로 옮긴다. 음수가 섞였다면 C 의 % 는 부호가 피제수를 따라 -3 % 2 = -1 이라 "== 0" 판정은 그대로 되지만 "== 1" 판정은 깨진다는 것도 알아 둔다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 9. 36 의 약수 1 · 2 · 3 · 4 · 6 · 9 · 12 · 18 · 36 이 아홉 개다.
원리 — n % i == 0 은 "n 을 i 로 나눈 나머지가 0" 곧 i 가 n 의 약수라는 뜻이다. 1 부터 n 까지 전부 나눠 보며 약수를 세는 가장 단순한 방법이다. 36 = 2² × 3² 이라 약수 개수는 (2+1)(2+1) = 9 로 공식으로도 확인된다. 반복 범위가 i <= n 이라 36 자신도 포함된다 — 범위를 i < n 으로 바꾸면 8 이 된다. 시험은 이런 경계 하나를 바꿔서 낸다.
따라가기
헷갈리는 자리 — 약수를 세다가 6 을 두 번 세거나(6 × 6 = 36 이라 짝이 자기 자신) 1 · 36 을 빼먹는 것. 코드는 i 를 하나씩 올리니 그런 실수가 없다 — 손으로 셀 때는 짝(1·36, 2·18, 3·12, 4·9, 6)으로 세면 9 가 바로 나온다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 3 dlrow. 대문자로 바꾼 "HELLO WORLD" 에 L 이 3개, 둘째 단어 "World" 를 뒤집어 소문자로 만들면 dlrow 다.
원리 — 문자열 메서드는 원본을 바꾸지 않고 새 문자열을 돌려주므로 점으로 이어 부른다. s.upper() 는 "HELLO WORLD", .count('L') 은 L 의 개수 — HELLO 에 2개, WORLD 에 1개로 3. s.split() 은 공백 기준으로 ["Hello", "World"], [1] 은 "World", [::-1] 은 뒤집기 "dlroW", .lower() 는 "dlrow". 각 단계의 결과를 다음 단계가 받는 파이프라인이다.
따라가기
헷갈리는 자리 — count 를 대문자로 바꾸기 전 원본 "Hello World" 에서 세어 'L' 이 0 개(소문자 l 만 있음)라고 하는 것. upper() 가 먼저다. 그리고 lower() 를 뒤집기 전에 적용해도 결과는 같지만, [::-1] 이 문자열 전체가 아니라 split 한 한 단어에 걸린다는 것을 본다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 Python 3.12 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 923. b 는 a 와 같은 배열을 가리켜 b[0] = 9 가 a 에 반영되고, c 는 복사본이라 c[1] = 8 은 a 에 영향이 없다.
원리 — 배열 변수는 배열 객체의 "주소"를 담는다. int[] b = a 는 주소를 복사한 것이라 a 와 b 는 같은 배열이다 — b[0] 을 바꾸면 a[0] 도 바뀐다. a.clone() 은 배열을 새로 만들어 값을 복사한 것이라 c 는 다른 배열이다 — c[1] 을 바꿔도 a 는 그대로다. 출력은 a[0] + "" 로 문자열을 만든 뒤 붙이므로 9 · 2 · 3 이 이어진다. 참조 복사와 값 복사의 차이가 이 문제 전부다.
따라가기
헷갈리는 자리 — clone 도 같은 배열이라 보고 983 으로 적거나, = 도 복사라 보고 123 으로 적는 것. "= 는 같은 것을 가리키고, clone 은 새로 만든다". 2차원 배열의 clone 은 바깥 배열만 복사(얕은 복사)라 안쪽 행은 공유된다는 것이 다음 단계 함정이다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 10 20. 0 + 2 + 4 + 6 + 8 = 20 을 더하고 i 는 10 에서 멈춘다.
원리 — do-while 은 본문을 먼저 한 번 실행하고 그다음에 조건을 검사한다. 조건이 처음부터 거짓이어도 본문이 한 번은 돈다는 것이 while 과의 차이다. 여기서는 sum += i 를 한 뒤 i 를 2 올리고 i < 10 인지 본다. i 가 8 일 때 sum 에 8 을 더하고 i 가 10 이 되어 조건이 거짓이라 끝난다. 그래서 마지막으로 더해진 값은 8 이고 i 의 최종값은 10 이다 — "더한 값"과 "멈춘 i" 가 다르다.
따라가기
헷갈리는 자리 — 10 도 더해서 30 으로 적는 것. 10 은 조건 검사에서 걸러져 본문에 들어오지 못한다. 그리고 출력 순서 — printf 가 i 를 먼저, sum 을 나중에 찍는다. 변수 순서를 바꿔 읽으면 20 10 이 된다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 34. 제곱 리스트 [1, 4, 9, 16, 25] 에서 b[2] = 9 와 b[-1] = 25 를 더했다.
원리 — map(함수, 리스트) 는 리스트의 각 원소에 함수를 적용한 결과를 만든다. lambda x: x * x 는 이름 없는 제곱 함수다. map 이 돌려주는 것은 게으른 반복자라 list() 로 감싸야 리스트가 된다 → [1, 4, 9, 16, 25]. b[2] 는 세 번째 원소 9, b[-1] 은 마지막 25. 합 34. 음수 첨자는 뒤에서부터 센다 — −1 이 마지막, −2 가 그 앞이다.
따라가기
헷갈리는 자리 — b[2] 를 "2번째"로 읽어 4 로 잡는 것. 첨자는 0 부터라 b[2] 는 세 번째다. lambda x: x * 2 로 잘못 읽으면 [2, 4, 6, 8, 10] 이라 6 + 10 = 16 이 된다 — x * x 와 x * 2 를 구분한다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 Python 3.12 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 11. super.g() 안에서 불리는 f() 도 B 의 f 라서 5 + 1 = 6 이고, 거기에 B 의 f() 5 를 더해 11 이다.
원리 — super.g() 는 "부모 클래스의 g 코드를 실행하라"이지 "부모 객체로 바꿔라"가 아니다. 실행되는 객체는 여전히 B 인스턴스다. 그래서 A 의 g 안에 있는 f() 호출은 동적 바인딩으로 B 의 f 를 부른다 — A 의 f 가 아니다. 결과 super.g() = 5 + 1 = 6. B 의 g 는 거기에 자기 f() = 5 를 더해 11 을 돌려준다. super 는 "코드 선택"만 바꾸고 "객체"는 못 바꾼다는 것이 핵심이다.
따라가기
헷갈리는 자리 — super.g() 안의 f() 를 A 의 f 로 보고 3 + 1 + 5 = 9 로 적는 것. super 로 부른 메서드 안에서도 this 는 B 다. 부모의 f 를 명시적으로 부르려면 A 의 g 코드가 아니라 B 안에서 super.f() 라고 써야 한다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 2O. 대문자 K · A 두 개를 세고, s[1] 인 'o' 에서 32 를 빼 'O' 로 만든다.
원리 — 아스키 코드에서 대문자 A~Z 는 65~90, 소문자 a~z 는 97~122 로 정확히 32 차이다. 그래서 소문자 − 32 = 대문자, 대문자 + 32 = 소문자다. 반복문은 널 문자까지 돌며 'A' 이상 'Z' 이하인 글자만 센다 — "KoreA" 에서 K 와 A 다. s[1] 은 'o'(111) 이고 111 − 32 = 79 = 'O' 를 %c 가 글자로 찍는다. 서식이 "%d%c" 라 숫자와 글자가 붙어서 나온다.
따라가기
헷갈리는 자리 — 2 뒤의 글자를 숫자 0 으로 적는 것. 알파벳 O 다. 그리고 s[1] 을 "첫 글자"로 읽어 K 로 계산하는 것 — 첨자는 0 부터다. 대소문자 변환은 ±32 또는 toupper() · tolower() 함수로도 나온다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
사원(사번, 이름, 부서코드): (1,김,A) (2,이,B) (3,박,NULL) / 부서(부서코드, 부서명): (A,영업) (B,개발)
① SELECT COUNT(*) FROM 사원 s INNER JOIN 부서 d ON s.부서코드 = d.부서코드;
② SELECT COUNT(*) FROM 사원 s LEFT JOIN 부서 d ON s.부서코드 = d.부서코드; 각각의 결과는?
답 — ① 2 ② 3. INNER JOIN 은 짝이 있는 행만, LEFT JOIN 은 왼쪽(사원) 행 전부를 남긴다.
원리 — 조인은 두 테이블의 행을 조건(부서코드가 같음)으로 짝짓는다. INNER JOIN 은 짝이 맞는 행만 결과에 넣는다 — 박의 부서코드가 NULL 이라 어느 부서와도 못 맞아 빠진다. LEFT JOIN 은 왼쪽 테이블의 모든 행을 남기고 짝이 없으면 오른쪽 열을 NULL 로 채운다 — 박도 남는다. NULL 은 어떤 값과도 같지 않으므로 NULL 끼리도 짝이 안 된다.
따라가기
헷갈리는 자리 — 부서 테이블에 없는 코드가 아니라 NULL 이라도 결과는 같다 — 짝이 없으면 INNER 에서 빠진다. RIGHT JOIN 이었다면 부서 쪽 전부가 남아 2 다.
이전 자료의 예상 문제다. sqlite 3.49 에서 실행해 정답을 확인했다.
학생 테이블에서 이름이 '홍길동'인 학생의 학년을 4로 변경하는 SQL문을 작성하시오.
UPDATE 학생 SET 학년 = 4 WHERE 이름 = '홍길동';답 — UPDATE 학생 SET 학년 = 4 WHERE 이름 = '홍길동';
원리 — 값을 고치는 명령은 UPDATE 테이블 SET 열 = 새값 WHERE 조건 이다. SET 뒤에 고칠 열과 값을 적고, WHERE 로 고칠 행을 고른다. WHERE 를 빼면 모든 행의 학년이 4 가 되므로 조건이 반드시 있어야 한다. 여러 열을 한 번에 고치려면 SET 학년 = 4, 학과 = '…' 처럼 쉼표로 잇는다.
따라가기
헷갈리는 자리 — INSERT 처럼 VALUES 를 쓰거나, SET 대신 = 만 적는 것. 4 는 숫자라 따옴표가 없고 홍길동은 문자열이라 있다. 이 셋(SET · WHERE · 따옴표)이 UPDATE 작성 문제의 감점 자리다.
이전 자료의 예상 문제다. sqlite 3.49 에서 실행해 정답을 확인했다.
정규화하지 않은 테이블에서 데이터 중복 때문에 발생하는 이상(Anomaly) 현상 3가지를 쓰시오.
답 — 삽입 이상 · 삭제 이상 · 갱신 이상. 중복이 있는 표에서 넣고 · 지우고 · 고칠 때 각각 생기는 세 가지 사고다.
원리 — 학생과 강좌를 한 표에 넣어 두면 세 가지가 꼬인다. 삽입 이상 — 아직 강좌를 안 듣는 학생은 강좌 칸을 채울 수 없어 넣지 못하거나 NULL 을 넣어야 한다. 삭제 이상 — 어떤 학생의 유일한 강좌 행을 지우면 학생 정보까지 함께 사라진다. 갱신 이상 — 같은 학생 이름이 여러 행에 있어 하나만 고치면 서로 달라진다. 정규화는 이 셋을 없애려고 표를 쪼개는 일이다.
따라가기
헷갈리는 자리 — "조회 이상" 같은 없는 이름을 만드는 것. 셋은 삽입 · 삭제 · 갱신이고, 갱신을 수정으로 써도 같은 말이다. 원인이 "중복"이라는 것까지 함께 적어야 다음 문제(정규화 이유)로 이어진다.
이전 자료의 예상 문제다. 교재 정의와 대조했다.
로킹(Locking) 단위가 커질수록: 로크의 수는 ( ① ), 병행성(동시성) 수준은 ( ② ), 관리 오버헤드는 ( ③ ). 괄호에 증가/감소(높아짐/낮아짐)를 쓰시오.
답 — ① 감소 ② 낮아짐 ③ 감소. 로킹 단위가 커지면 잠글 덩어리 수가 줄고, 동시에 일할 여지도 줄고, 관리할 것도 준다.
원리 — 로킹 단위는 "한 번에 잠그는 덩어리 크기"다 — 필드 · 레코드 · 테이블 · 데이터베이스 순으로 커진다. 덩어리가 크면 몇 개만 잠가도 전체를 덮으니 로크 수가 줄고 관리도 쉽지만, 한 사람이 잠근 동안 다른 사람은 그 큰 덩어리 전체를 못 써 동시에 일할 수 있는 정도(병행성)가 떨어진다. 반대로 단위가 작으면 병행성은 오르지만 로크가 많아져 오버헤드가 늘어난다. 세 값이 "크면 줄고 작으면 는다"는 한 방향으로 움직인다.
따라가기
헷갈리는 자리 — 병행성을 "높아짐"으로 적는 것. 크게 잠글수록 남이 기다린다. 오버헤드와 병행성이 반대 방향이라고 생각하기 쉽지만 여기서는 둘 다 "줄어든다"로 같은 편이다 — 오버헤드는 로크 수를 따라간다.
이전 자료의 예상 문제다. 교재 정의와 대조했다.
OSI 계층 매칭: ① 세그먼트 단위로 종단 간 신뢰성 있는 전송을 담당(TCP/UDP) ② 패킷 단위로 경로 설정을 담당하며 라우터가 동작 ③ 프레임 단위로 인접 노드 간 오류·흐름 제어를 담당하며 스위치가 동작
답 — ① 전송 계층 ② 네트워크 계층 ③ 데이터링크 계층. 데이터 단위와 장비 이름이 계층을 가리킨다.
원리 — OSI 7계층은 아래부터 물리(비트) · 데이터링크(프레임) · 네트워크(패킷) · 전송(세그먼트) · 세션 · 표현 · 응용이다. 계층마다 데이터 이름과 대표 장비가 다르다 — 데이터링크는 프레임 · 스위치 · 브리지, 네트워크는 패킷 · 라우터, 전송은 세그먼트 · TCP/UDP. 문제 문장의 "세그먼트 · TCP", "패킷 · 라우터", "프레임 · 스위치" 낱말을 그 표에 대면 된다.
따라가기
헷갈리는 자리 — 흐름 제어가 데이터링크와 전송 양쪽에 있어 헷갈리는 것 — "인접 노드"면 데이터링크, "종단 간"이면 전송이다. 계층 번호(2 · 3 · 4)로 적어도 되는지는 문제의 요구를 따른다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
IPv6는 ( ① )비트 주소 체계를 사용하며, 주소 유형은 유니캐스트·멀티캐스트·( ② ) 3가지이다(IPv4의 브로드캐스트가 사라짐). 괄호를 채우시오.
답 — ① 128 ② 애니캐스트(Anycast). IPv6 는 128비트 주소이고 브로드캐스트 대신 애니캐스트가 있다.
원리 — IPv4 는 32비트(약 43억 개)라 모자라 128비트인 IPv6 가 나왔다(16진수 8 묶음, 콜론 구분). 주소 유형은 셋 — 유니캐스트(하나에게), 멀티캐스트(그룹 전부에게), 애니캐스트(그룹 중 가장 가까운 하나에게). IPv4 의 브로드캐스트는 없어지고 멀티캐스트가 대신한다. 헤더 단순화 · 자동 설정 · IPSec 기본 지원도 IPv6 의 특징이다.
따라가기
헷갈리는 자리 — ② 에 브로드캐스트를 적는 것. IPv6 엔 없다. 128 을 64 로 적는 것 — 64비트는 IPv6 의 인터페이스 식별자 길이라 헷갈리기 쉽다.
이전 자료의 예상 문제다. ipaddress · 표준 정의로 확인했다.
① 규정 크기보다 큰 ICMP 패킷을 보내 시스템을 마비시키는 공격 ② 출발지 IP와 목적지 IP를 모두 피해자 주소로 동일하게 위조해 전송하는 공격
답 — ① Ping of Death ② LAND Attack. 너무 큰 ICMP 패킷 하나로 죽이는 것과, 출발지 = 목적지로 만들어 자기 자신과 통신하게 하는 것이다.
원리 — Ping of Death 는 규정(65,535바이트)보다 큰 ICMP 패킷을 조각내 보내면 받는 쪽이 재조립하다 버퍼가 넘쳐 멈추는 것이다. LAND 는 SYN 패킷의 출발지 IP · 포트를 목적지와 똑같이 위조해, 서버가 자기에게 응답을 보내고 다시 받는 일을 반복하다 지치게 만든다. 둘 다 옛 취약점이라 지금 시스템은 막지만 시험에는 이름으로 나온다. "규정보다 큰 ICMP = Ping of Death", "출발지 = 목적지 = LAND" 다.
따라가기
헷갈리는 자리 — 티어드롭(조각 오프셋 겹침)과 Ping of Death(조각 크기 초과)를 섞는 것. 둘 다 조각화를 쓰지만 겹침이면 티어드롭, 크기면 Ping of Death 다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
① 네트워크 침입을 실시간 탐지하여 관리자에게 알리는 시스템 ② 탐지에 그치지 않고 침입을 자동으로 차단까지 수행하는 시스템 (영문 약자)
답 — ① IDS ② IPS. 탐지해서 알리기만 하면 IDS, 탐지한 뒤 스스로 막기까지 하면 IPS 다.
원리 — 침입 탐지 시스템(IDS, Intrusion Detection)은 트래픽을 지켜보다 공격 무늬(시그니처)나 이상 행동을 찾으면 경보를 울린다 — 경비 카메라. 침입 방지 시스템(IPS, Prevention)은 트래픽이 지나가는 길목에 서서 공격이면 그 자리에서 끊는다 — 경비원. IDS 는 옆에서 복사본을 보고(패시브), IPS 는 인라인이라 오탐이 나면 정상 트래픽도 막는 부담이 있다. D 는 Detection(탐지), P 는 Prevention(방지)이다.
따라가기
헷갈리는 자리 — 방화벽과 섞는 것. 방화벽은 규칙(포트 · 주소)으로 문을 여닫고, IDS/IPS 는 내용(패턴)을 본다. 셋을 층으로 두면 방화벽 → IPS → IDS 순으로 깊이 본다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
① 알고리즘군을 각각 캡슐화하여 실행 중에 동적으로 교체할 수 있게 하는 행위 패턴 ② 요청 자체를 객체로 캡슐화하여 요청의 저장·취소(Undo)·큐잉이 가능하게 하는 행위 패턴
답 — ① 스트래티지(Strategy) ② 커맨드(Command). "알고리즘 교체"와 "요청을 객체로"가 각각의 표지다.
원리 — 둘 다 행위 패턴이다. 스트래티지는 같은 일을 하는 여러 알고리즘(정렬 방식 · 할인 정책 · 경로 계산)을 각각 클래스로 캡슐화하고 같은 인터페이스를 갖게 해서, 실행 중에 갈아끼운다 — if-else 로 알고리즘을 고르던 코드가 없어진다. 커맨드는 "무엇을 해 달라"는 요청 자체를 객체로 만든다. execute() 를 가진 명령 객체를 만들어 두면 큐에 넣어 나중에 실행하거나, 로그로 남기거나, undo() 를 구현해 취소할 수 있다 — 메뉴 항목 · 버튼 클릭 · 트랜잭션이 이것이다.
따라가기
헷갈리는 자리 — 스트래티지를 스테이트(State)로 적는 것. 구조가 같지만 스테이트는 "객체 상태에 따라" 자동으로 행동이 바뀌고, 스트래티지는 "클라이언트가 골라서" 알고리즘을 바꾼다. 커맨드를 메멘토로 적는 것 — 메멘토는 상태 저장, 커맨드는 요청 저장이다.
이전 자료의 예상 문제다. GoF 패턴 정의와 대조했다.
V모델의 테스트 수준 4단계를 실행 순서대로 나열하시오: (시스템 테스트 / 단위 테스트 / 인수 테스트 / 통합 테스트)
답 — 단위 테스트 → 통합 테스트 → 시스템 테스트 → 인수 테스트. 작은 것에서 큰 것으로, 개발자에서 사용자로 간다.
원리 — V 모델은 왼쪽 팔에 개발 단계(요구 분석 → 설계 → 상세 설계 → 구현)를, 오른쪽 팔에 그 단계와 짝인 테스트를 둔다. 구현 ↔ 단위 테스트(모듈 하나가 맞나), 상세 설계 ↔ 통합 테스트(모듈을 붙였을 때 인터페이스가 맞나), 설계 ↔ 시스템 테스트(전체가 요구 명세대로 도나, 성능 · 보안 포함), 요구 분석 ↔ 인수 테스트(사용자가 받아들일 만한가, 알파 · 베타). 테스트는 오른쪽 팔을 아래에서 위로 올라가니 단위 → 통합 → 시스템 → 인수 순서다.
따라가기
헷갈리는 자리 — 시스템과 인수를 바꾸는 것. 시스템 테스트는 개발 조직이 "명세대로인가"를 보고, 인수 테스트는 사용자 · 고객이 "받을 만한가"를 본다. 인수가 마지막이다.
이전 자료의 예상 문제다. 표준 정의(ISTQB · V 모델)와 대조했다.
HRN 스케줄링에서 우선순위 = (대기시간 + 서비스시간) ÷ 서비스시간이다. 다음 프로세스의 실행 우선순위를 높은 순서로 나열하시오.
답 — C → B → A. 우선순위는 A 2 · B 4 · C 5 로 C 가 가장 높다.
원리 — HRN(Highest Response-ratio Next)은 SJF 의 기아 문제를 고친 비선점 스케줄링이다. 우선순위 = (대기 시간 + 서비스 시간) ÷ 서비스 시간이다. 서비스 시간이 짧으면 분모가 작아 값이 커지고(SJF 처럼 짧은 것 우대), 오래 기다리면 분자가 커져 값이 올라간다(긴 작업도 언젠가 차례가 온다). 값이 큰 것부터 실행한다. 계산은 분수 하나씩이니 세 개를 구해 크기 순으로 세우면 끝이다.
따라가기
헷갈리는 자리 — 값이 작은 것부터 세우는 것. HRN 은 응답 비율이 "높은(Highest)" 것이 먼저다. 그리고 대기 시간만 보고 C 를 고르는 것은 우연히 맞지만, B 와 A 는 대기만 보면 순서가 같아도 근거가 다르다 — 반드시 비율로 계산한다.
이전 자료의 예상 문제다. 표준 정의 · 손 계산으로 확인했다.
왜 이걸 하나 — 점수보다 어느 장으로 돌아가느냐가 결과다. 문항마다 가는 장이 정해져 있다.
코드 9문항 중 C 4 · Java 3 · Python 2 다. 1번은 static total 이 셋을 세고 num 은 생성 순서라 3123, 5번은 b 가 a 와 같은 배열이라 a[0] 이 9 로 바뀌고 c 는 clone 이라 a 에 영향이 없어 923 이다. 8번은 super.g() 가 A 의 g 를 돌지만 그 안의 f() 는 B 것(5)이라 6 + 5 = 11.
6번 do-while 은 i 가 0 2 4 6 8 을 더한 뒤 10 이 되어 멈추므로 끝값 10 과 합 20 둘을 적는다. 9번은 대문자 K · A 두 개와 s[1] − 32 = O 라 2O 다. 4번 Python 은 upper · count · split · 역순 · lower 가 한 줄에 다 있어 중간 값을 줄마다 적는다.
용어 11문항은 SQL·DB 4(INNER/LEFT JOIN 건수 · UPDATE 작성 · 이상 3종 · 로킹 단위) · SW공학 3(스트래티지/커맨드 · V모델 순서 · HRN) · 네트워크 2(OSI 3계층 · IPv6) · 보안 2(Ping of Death/LAND · IDS/IPS)다. 10번은 NULL 부서코드가 INNER 에서는 빠지고 LEFT 에서는 남아 2 와 3 이다.
틀린 문항의 「가는 장」을 열면 그 문항이 04절에 그대로 있고, 앞뒤로 같은 꼴의 문항이 붙어 있다. 몰라서 틀렸으면 그 장 03절부터, 알았는데 틀렸으면 05절만 읽는다. 판정 기준은 E01 의 03절 표와 같다.
| 문항 | 분야 | 가는 장 | 무엇을 묻나 |
|---|---|---|---|
| 1 | Java | E06 | static total 과 생성 순서 num |
| 2 | C | E02 | 짝수 합 · 홀수 합 배열 반복 |
| 3 | C | E04 | 36 의 약수 개수 |
| 4 | Python | E07 | upper · count · split · 역순 |
| 5 | Java | E06 | 배열 참조 대입과 clone 의 차이 |
| 6 | C | E04 | do-while 2씩 증가 — 끝값과 합 |
| 7 | Python | E07 | map lambda 제곱 리스트 |
| 8 | Java | E05 | super.g() 안의 f() 는 자식 것 |
| 9 | C | E03 | 대문자 개수와 s[1] - 32 |
| 10 | SQL | E08 | INNER JOIN 과 LEFT JOIN 건수 |
| 11 | SQL | E09 | UPDATE 문 작성 |
| 12 | DB | E10 | 삽입 · 삭제 · 갱신 이상 |
| 13 | DB | E10 | 로킹 단위와 로크 수 · 병행성 · 오버헤드 |
| 14 | 네트워크 | E11 | 전송 · 네트워크 · 데이터링크 계층 |
| 15 | 네트워크 | E12 | IPv6 128비트와 애니캐스트 |
| 16 | 보안 | E14 | Ping of Death 와 LAND |
| 17 | 보안 | E14 | IDS 와 IPS |
| 18 | 디자인패턴 | E17 | 스트래티지와 커맨드 |
| 19 | 테스트 | E18 | V모델 테스트 4단계 순서 |
| 20 | OS | E16 | HRN 우선순위 계산 |
| 문항 | 왜 갈리나 |
|---|---|
| 5번 | b = a 는 같은 배열, c = a.clone() 은 새 배열. a 는 9 2 3 |
| 8번 | super.g() 는 A.g 를 돌지만 그 안의 f() 는 동적으로 B.f(5). 6 + f() 5 = 11 |
| 13번 | 로킹 단위가 커지면 로크 수 감소 · 병행성 낮아짐 · 오버헤드 감소. 셋 다 같은 방향이다 |
| 20번 | A (5 + 5) ÷ 5 = 2, B (6 + 2) ÷ 2 = 4, C (12 + 3) ÷ 3 = 5. C → B → A |
채점 결과는 오답노트에 회차별 점수와 틀린 문항 목록으로 모인다. 세트를 하나 끝낼 때마다 거기서 같은 장에서 반복해서 틀리는지를 본다. 두 세트에서 같은 장이 나오면 그 장의 06절 훈련을 그날 5문항 푼다.
왜 이걸 하나 — 세트의 결과는 다음에 열 장의 이름이어야 한다.