이전 자료의 예상 모의를 실전 꼴로 옮겼다. 기출과 같은 분포(프로그래밍 9 · SQL·DB 4 · 네트워크 2 · 보안 2 · SW공학 3)로 짰다
왜 이걸 하나 — 세트는 시험장과 같은 조건에서만 숫자가 된다. 조건은 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분 안에 푸는 것 자체가 연습이다. 분야 장의 문제와 같은 문항이어도 조건이 다르다.
시작을 누르면 시계가 돌고 화면을 닫아도 이어진다. 다 적은 뒤 문항마다 정답 보기 → 맞았다 · 틀렸다를 누르면 위 막대에 점수와 분야별 결과가 모인다. 이 세트에서 채점한 기록은 분야 장의 같은 문항에도 그대로 보인다.
다음 코드의 출력을 쓰시오.
답 — DAnimalAnimal. 메서드는 자식 것이 불리지만(D), 필드는 참조 타입인 Animal 것이 읽힌다(Animal · Animal).
원리 — 자바에서 메서드 호출은 "실제 객체"를 보고 결정된다(동적 바인딩). a 는 Animal 타입 변수지만 안에 든 것은 Dog 이므로 cry() 는 Dog 의 것이 불려 D 가 찍힌다. 그런데 필드는 다르다 — 필드는 오버라이딩되지 않고 "가려질(hiding)" 뿐이며, 어느 필드를 읽을지는 컴파일 시점의 타입으로 정해진다. sound() 는 Animal 클래스 안에 적힌 코드라 거기서 name 은 Animal 의 name 이고, a.name 은 a 의 타입이 Animal 이라 역시 Animal 의 name 이다. Dog 의 name = "Dog" 는 Dog 타입 변수로 봐야만 보인다.
따라가기
헷갈리는 자리 — 필드도 오버라이딩된다고 생각해 DDogDog 로 적는 것. "메서드는 객체를 보고, 필드는 타입을 본다" 한 줄로 잡는다. 필드에 자식 값을 쓰게 하려면 getName() 같은 메서드로 감싸야 한다 — 그것이 캡슐화가 권장되는 이유 중 하나다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — ATION / F / K (세 줄). 포인터에 더하는 것과 글자에 더하는 것이 다르다는 것을 한 문제에 넣었다.
원리 — s 는 문자열 "INFORMATION" 의 첫 글자 주소를 담은 포인터다. s + 6 은 "여섯 글자 뒤의 주소"이고 %s 는 그 주소부터 널 문자까지 찍으니 7번째 글자부터 끝까지 나온다. *(s + 2) 는 "두 글자 뒤 주소의 내용" = 세 번째 글자 하나다. *s + 2 는 우선순위가 다르다 — * 가 + 보다 먼저라 "첫 글자의 내용"에 2 를 더한 것이고, 문자는 정수(아스키 코드)라 'I' 의 코드 73 + 2 = 75 = 'K' 가 된다. 괄호 위치 하나가 "주소를 옮기나, 글자를 바꾸나"를 가른다.
따라가기
헷갈리는 자리 — *s + 2 를 *(s + 2) 로 읽어 F 라고 적는 것. 괄호가 없으면 * 가 먼저 붙는다. 그리고 %c 로 찍으니 숫자 75 가 아니라 글자 K 다 — %d 였다면 75 가 찍힌다. 번호는 0 부터 세는 것도 늘 확인한다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 10. 1234 의 각 자리 4 + 3 + 2 + 1 을 재귀로 더한 것이다.
원리 — n % 10 은 마지막 자리, n / 10 은 마지막 자리를 뗀 나머지 수다(정수 나눗셈이라 소수점이 버려진다). f(n) 은 "마지막 자리 + 나머지 수의 자릿수 합"으로 자기 자신을 부르고, n 이 0 이 되면 더할 것이 없으니 0 을 돌려준다. 재귀는 "지금 한 자리만 처리하고 나머지는 같은 함수에 맡긴다"는 발상이다. 호출은 f(1234) → f(123) → f(12) → f(1) → f(0) 순으로 쌓였다가 f(0) = 0 부터 거꾸로 값이 돌아오며 더해진다.
따라가기
헷갈리는 자리 — 종료 조건을 n == 1 로 착각해 마지막 1 을 빠뜨리는 것. 이 코드는 n == 0 에서 멈추므로 1 의 자리도 더해진다. 그리고 순서 — 자릿수 합은 순서가 상관없지만, 자리를 "출력"하는 재귀라면 호출 순서(4 3 2 1)인지 반환 순서(1 2 3 4)인지가 답을 가른다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — b 3. 값 순으로 키를 정렬하면 b · c · a 이고, 첫 키는 b, 마지막 키 a 의 값은 3 이다.
원리 — sorted(d) 는 딕셔너리의 "키"를 정렬한 리스트를 돌려준다. key=d.get 을 주면 각 키를 d.get(키) 곧 그 키의 값으로 바꿔 비교한다 — 키가 아니라 값 순으로 키가 줄 서는 것이다. 값이 1 · 2 · 3 인 b · c · a 순서다. s[0] 은 'b', s[-1] 은 마지막 'a' 이고 d['a'] = 3 이다. "값으로 정렬한 키 목록"은 최댓값 키 찾기(max(d, key=d.get))와 같은 발상이라 함께 나온다.
따라가기
헷갈리는 자리 — sorted(d) 가 값을 정렬한다고 보는 것. 딕셔너리를 순회하면 키가 나오므로 정렬 대상도 키다. key=d.get 이 없으면 알파벳 순 a · b · c 라 답이 "a 2" 로 바뀐다. sorted(d.values()) 였다면 [1, 2, 3] 이다 — 무엇을 정렬하는지 먼저 본다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 Python 3.12 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 1EFG. arr[3] 에서 예외가 나 그 뒤 줄은 건너뛰고 catch → finally → 다음 문장 순으로 간다.
원리 — try 블록은 예외가 나는 순간 거기서 멈추고 나머지 줄은 실행하지 않는다. arr 은 3칸(0 · 1 · 2)이라 arr[3] 은 범위 밖이고 ArrayIndexOutOfBoundsException 이 던져진다. 그래서 arr[0] 의 1 은 찍혔지만 arr[1] 의 2 는 영영 찍히지 않는다. 예외는 타입이 맞는 catch 로 잡혀 E 를 찍고, finally 는 예외가 났든 안 났든 반드시 실행돼 F 를 찍는다. 예외가 처리됐으니 프로그램은 계속 진행해 G 를 찍는다.
따라가기
헷갈리는 자리 — 예외 뒤의 arr[1] 도 찍혀 12EFG 로 적는 것. 예외가 난 줄부터 try 의 나머지는 실행되지 않는다. 그리고 catch 가 없거나 타입이 안 맞았다면 finally 는 F 를 찍고 예외가 밖으로 나가 G 는 안 찍힌다 — "잡혔는가"가 뒤 문장의 운명을 정한다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 8 14 6. 12 = 1100, 10 = 1010 을 비트 단위로 AND · OR · XOR 한 값이다.
원리 — 비트 연산은 두 수를 2진수로 놓고 같은 자리끼리 계산한다. AND(&)는 둘 다 1 일 때만 1, OR(|)는 하나라도 1 이면 1, XOR(^)는 서로 다를 때만 1 이다. 12 는 8+4 = 1100, 10 은 8+2 = 1010 이다. 자리별로 보면 8의 자리는 둘 다 1, 4의 자리는 12 만, 2의 자리는 10 만, 1의 자리는 둘 다 0 이다. AND 는 8의 자리만 남아 8, OR 는 8+4+2 = 14, XOR 는 4+2 = 6 이다. 2진수로 바꿔 세로로 놓고 푸는 것이 가장 안 틀린다.
따라가기
헷갈리는 자리 — & 와 && 를 섞는 것. && 는 논리 AND 라 12 && 10 은 1 이다. 한 글자면 비트, 두 글자면 논리다. 그리고 XOR 는 "같은 수를 두 번 XOR 하면 원래대로" 라는 성질(a ^ b ^ b = a)이 있어 값 교환 · 암호 문제에 나온다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 3 4 18. a 는 [3, 6, 9] 로 3개, 집합 b 는 중복이 사라져 {3, 6, 9, 12} 4개, a 의 합은 18 이다.
원리 — 리스트 컴프리헨션 [x for x in range(1, 10) if x % 3 == 0] 은 1~9 중 3 의 배수만 모은다 → [3, 6, 9]. a + [3, 9, 12] 는 리스트 이어 붙이기라 [3, 6, 9, 3, 9, 12] 인데, set() 에 넣으면 중복이 제거되어 {3, 6, 9, 12} 가 된다. 집합은 "중복 없음 · 순서 없음"이 성질이다. len(a) = 3, len(b) = 4, sum(a) = 3 + 6 + 9 = 18. range 의 끝 10 은 포함되지 않는다는 것도 확인 지점이다.
따라가기
헷갈리는 자리 — set 이 중복을 지운다는 것을 놓쳐 len(b) 를 6 으로 적는 것. 그리고 sum 의 대상이 a 인지 b 인지 — b 였다면 30 이다. 집합 문제는 "중복 제거 후 몇 개"가 늘 핵심이다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 Python 3.12 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 8결과53. + 는 왼쪽부터 계산되어 문자열을 만나기 전까지는 덧셈, 만난 뒤로는 이어 붙이기다.
원리 — 자바의 + 는 두 피연산자 중 하나라도 String 이면 문자열 연결이고, 둘 다 숫자면 덧셈이다. 그리고 같은 우선순위라 왼쪽에서 오른쪽으로 하나씩 계산한다. a + b 는 5 + 3 = 8(숫자). 8 + "결과" 는 "8결과"(문자열). "8결과" + a 는 "8결과5", 거기에 + b 는 "8결과53". 한 번 문자열이 되면 그 뒤의 숫자는 전부 붙는다. 같은 식이라도 괄호를 (a + b) 로 뒤에 두면 "8결과8" 이 된다.
따라가기
헷갈리는 자리 — 뒤의 a + b 도 더해 "8결과8" 로 적는 것. 문자열 뒤에서는 더하기가 없다. println 이라 줄바꿈이 붙지만 답에는 안 적는다. 이 유형은 문자열 위치만 바꿔 여러 번 나온다 — 왼쪽부터 한 칸씩 계산하면 된다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 JDK 17 실행 결과와 대조했다.
다음 코드의 출력을 쓰시오.
답 — 5 4. 2차원 배열도 메모리에는 한 줄로 놓이므로, 첫 칸 주소에서 4칸 뒤는 두 번째 행의 두 번째 원소다.
원리 — int a[2][3] 은 "3칸짜리 행이 2개"이고 메모리에는 1 2 3 4 5 6 이 이어서 놓인다(행 우선). a[0] 은 첫 행의 시작 주소이므로 p = a[0] 은 1 이 있는 칸을 가리킨다. p + 4 는 int 4개 뒤, 곧 통째로 세었을 때 5번째(0부터 4번) 칸이라 값은 5 다. a[1][0] 은 두 번째 행의 첫 원소 4 다. 2차원 첨자 [i][j] 를 1차원 번호로 바꾸면 i × 열 수 + j 이고, 거꾸로 번호 4 는 4 ÷ 3 = 1 행, 4 % 3 = 1 열 → a[1][1] = 5 다.
따라가기
헷갈리는 자리 — p 가 int * 이므로 p + 4 는 4바이트가 아니라 int 4개(16바이트)만큼 간다는 것. 그리고 a + 1 은 "행 하나(int 3개)" 를 건너뛰지만 a[0] + 1 은 "원소 하나"를 건너뛴다 — 같은 + 1 인데 타입에 따라 보폭이 다르다.
이전 자료의 예상 문제다. 코드를 손으로 따라가고 docker gcc(alpine 13.2) 실행 결과와 대조했다.
성적 테이블이 다음과 같을 때 쿼리 결과를 쓰시오.
답 — 열 이름 · 평균, 한 행 박C · 95. 이름별 평균이 85 를 넘는 사람은 박C 뿐이다.
원리 — GROUP BY 이름 은 같은 이름의 행을 묶고, AVG(점수) 는 묶음마다 평균을 낸다. HAVING AVG(점수) > 85 는 묶은 뒤 평균에 거는 조건이라 85 는 안 들어간다(초과). 김A 는 (90 + 80) / 2 = 85, 이B 는 (70 + 100) / 2 = 85 라 둘 다 탈락이고 박C 는 95 하나뿐이라 평균 95 다.
따라가기
헷갈리는 자리 — > 를 >= 로 읽어 세 사람을 다 남기는 것. "초과"와 "이상"은 다르다. 평균 열 이름을 AVG(점수)로 적는 것 — AS 평균 이 있으니 평균이다.
이전 자료의 예상 문제다. sqlite 3.49 에서 실행해 정답을 확인했다.
사용자 '김기사'에게 학생 테이블의 SELECT 권한을 부여하되, 김기사가 그 권한을 다른 사용자에게도 부여할 수 있도록 하는 SQL문을 작성하시오.
GRANT SELECT ON 학생 TO 김기사 WITH GRANT OPTION;답 — GRANT SELECT ON 학생 TO 김기사 WITH GRANT OPTION;
원리 — 권한을 주는 명령은 GRANT 권한 ON 대상 TO 사용자 다(DCL). 여기에 WITH GRANT OPTION 을 붙이면 받은 사람이 그 권한을 남에게 다시 줄 수 있다. 거두는 명령은 REVOKE 권한 ON 대상 FROM 사용자 이고, 남에게 넘겨준 권한까지 같이 거두려면 CASCADE 를 붙인다. GRANT 는 TO, REVOKE 는 FROM 이라는 짝을 기억한다.
따라가기
헷갈리는 자리 — TO 를 FOR 나 FROM 으로 적는 것. WITH GRANT OPTION 을 빼면 "권한 부여"까지만 맞고 문제의 둘째 조건이 빠진다. 낱말 순서(권한 → ON → TO → WITH)가 곧 채점 기준이다.
이전 자료의 예상 문제다. sqlite 3.49 에서 실행해 정답을 확인했다.
릴레이션 R(학번, 과목코드, 성적, 학생이름)에서 기본키는 (학번, 과목코드)이고 함수 종속이 다음과 같다: (학번, 과목코드) → 성적, 학번 → 학생이름. 이 릴레이션에 존재하는 함수 종속의 문제점과, 이를 제거하면 도달하는 정규형은?
답 — 부분 함수 종속(학번 → 학생이름이 복합키의 일부에만 매달림), 제거하면 제2정규형.
원리 — 기본키가 (학번, 과목코드) 두 속성인데 학생이름은 학번만으로 정해진다. 키의 일부에만 매달린 이런 종속을 부분 함수 종속이라 하고, 이것이 있으면 같은 학생이 여러 과목을 들을 때 이름이 여러 행에 중복돼 갱신 이상이 난다. 부분 종속을 떼어 학생(학번, 학생이름) 표를 따로 만들면 제2정규형이 된다. 1NF → 2NF 의 조건이 바로 "부분 함수 종속 제거"다.
따라가기
헷갈리는 자리 — 이행 함수 종속이라 적는 것. 이행은 키 아닌 속성끼리(A → B → C)이고, 여기는 키의 일부가 결정자다. 정규형 사다리: 부분 종속 제거 = 2NF, 이행 종속 제거 = 3NF, 결정자가 후보키 = BCNF.
이전 자료의 예상 문제다. 교재 정의와 대조했다.
트랜잭션의 특성: ① 연산이 전부 반영되거나 전혀 반영되지 않아야 한다 ② 성공적으로 완료된 트랜잭션의 결과는 시스템 장애가 발생해도 영구적으로 반영되어야 한다. 각각의 명칭은?
답 — ① 원자성(Atomicity) ② 영속성 · 지속성(Durability). 트랜잭션 네 특성(ACID) 중 둘이다.
원리 — 트랜잭션은 "전부 되거나 전부 안 되거나"여야 하는 일 묶음이다. 원자성 — 더 쪼갤 수 없는 하나처럼 전부 반영되거나 하나도 반영되지 않는다(송금에서 출금만 되고 입금이 안 되면 안 된다). 일관성 — 끝난 뒤 데이터베이스가 모순 없는 상태. 고립성 — 동시에 돌아도 서로 끼어들지 않은 것처럼. 영속성 — 완료(COMMIT)된 결과는 장애가 나도 남는다. 앞 글자 A · C · I · D 로 외운다.
따라가기
헷갈리는 자리 — 영속성을 "일관성"으로 적는 것. "장애 · 영구"는 영속성, "모순 없음"은 일관성이다. 원자성의 표지는 "전부 아니면 전무(all or nothing)"다.
이전 자료의 예상 문제다. 교재 정의와 대조했다.
200.1.1.0/24 네트워크를 4개의 동일한 서브넷으로 분할했다. ① 두 번째 서브넷의 브로드캐스트 주소 ② 각 서브넷에서 실제 호스트에 할당 가능한 IP 개수는?
답 — ① 200.1.1.127 ② 62개. /24 를 4개로 나누면 /26, 묶음 64 이라 둘째 묶음은 64~127 이고 호스트는 62 개다.
원리 — 4 = 2² 이니 네트워크 비트가 2 늘어 /26, 호스트 비트 6 → 묶음 64. 묶음은 0~63, 64~127, 128~191, 192~255. 둘째 서브넷의 브로드캐스트는 묶음의 마지막 주소 127 이고, 각 서브넷의 호스트 수는 64 − 2 = 62 다. "몇 개로 나누나"가 주어지면 2ⁿ 을 찾아 프리픽스에 n 을 더한다.
따라가기
헷갈리는 자리 — 둘째 서브넷을 128~191 로 세는 것(첫째가 0~63 이다). 호스트 수 64 로 적는 것. 두 값이 짝이라 하나만 맞으면 부분 점수다.
이전 자료의 예상 문제다. ipaddress · 표준 정의로 확인했다.
네트워크에 접속하는 호스트에게 IP 주소, 서브넷 마스크, 게이트웨이 주소 등을 자동으로 할당해 주는 프로토콜은? (영문 약자)
답 — DHCP. 네트워크에 들어온 장비에게 IP · 서브넷 마스크 · 게이트웨이 · DNS 를 자동으로 빌려주는 프로토콜이다.
원리 — 장비마다 IP 를 손으로 적으면 중복과 실수가 난다. DHCP(Dynamic Host Configuration Protocol) 서버는 IP 주소 풀을 갖고, 새 장비가 브로드캐스트로 "주소 주세요"(Discover)를 외치면 서버가 제안(Offer) → 장비가 요청(Request) → 서버가 확인(Ack)하는 네 단계로 정해진 기간 동안 빌려준다(임대). RARP 가 하던 일을 넓힌 것이다. UDP 67 · 68 포트를 쓴다.
따라가기
헷갈리는 자리 — DNS(이름 → IP)와 섞는 것. DNS 는 이름을 풀고 DHCP 는 주소를 준다. "자동 할당 · 임대"가 DHCP 의 표지다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
사용자가 올바른 도메인 주소를 입력해도 DNS 정보를 조작하여 가짜 사이트로 연결되게 하는 공격은?
답 — 파밍(Pharming). 사용자가 주소를 맞게 쳐도 DNS 가 가짜 IP 를 돌려줘 가짜 사이트로 가게 하는 공격이다.
원리 — 피싱은 가짜 링크를 누르게 속이지만, 파밍은 이름을 IP 로 바꾸는 DNS 자체(서버나 PC 의 hosts 파일)를 조작해 올바른 주소로도 가짜로 간다. 사용자 잘못이 없어 더 위험하다. 이름은 farming(농사 짓듯 대량으로 거둔다)의 f 를 ph 로 바꾼 것이다. 막으려면 HTTPS 인증서를 확인하고 DNSSEC 을 쓴다.
따라가기
헷갈리는 자리 — 피싱(Phishing)과 바꾸는 것. "DNS 조작"이면 파밍, "속이는 메일 · 링크"면 피싱이다. 스미싱은 문자(SMS)로 하는 피싱이고, 보이스 피싱은 전화다 — 수단으로 이름이 갈린다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
① 소인수분해의 어려움에 기반한 공개키(비대칭키) 암호 알고리즘 ② 타원 곡선 이론에 기반해 짧은 키로 동등한 보안 강도를 제공하는 공개키 알고리즘
답 — ① RSA ② ECC. 큰 수의 소인수분해가 어렵다는 것에 기댄 것이 RSA, 타원 곡선 위의 계산이 어렵다는 것에 기댄 것이 ECC 다.
원리 — 공개키 암호는 "한 방향은 쉽고 거꾸로는 어려운" 수학 문제 위에 세운다. RSA 는 두 큰 소수를 곱하기는 쉽지만 곱을 다시 소인수분해하기는 어렵다는 것을 쓴다 — 키가 2048비트 이상으로 길다. ECC(타원 곡선 암호)는 타원 곡선 위의 점 연산에서 거꾸로 푸는 것이 어렵다는 것을 써서, 256비트 키로 RSA 3072비트와 비슷한 강도를 낸다 — 짧은 키라 모바일 · 인증서에 널리 쓴다.
따라가기
헷갈리는 자리 — DH(디피-헬만)는 이산대수 문제 위의 키 교환 방식이라 셋을 섞지 않는다. "소인수분해"는 RSA 하나뿐이다.
이전 자료의 예상 문제다. 표준 정의와 대조했다.
① 복잡한 서브시스템들을 하나의 단순한 통합 인터페이스로 제공하여 사용을 쉽게 하는 구조 패턴 ② 객체의 상태를 저장해 두었다가 필요할 때 이전 상태로 복원(Undo)할 수 있게 하는 행위 패턴
답 — ① 퍼사드(Facade) ② 메멘토(Memento). "통합 창구"와 "상태 저장 · 복원"이 각각의 표지다.
원리 — 퍼사드는 구조 패턴이다. 서브시스템 안에 클래스 열 개가 얽혀 있어도, 앞에 "간단한 메서드 몇 개"만 가진 퍼사드 클래스를 세우면 클라이언트는 그것만 부른다 — 건물 정면(facade)만 보고 안의 배관을 모르듯. 결합도가 내려가고 쓰기 쉬워진다. 메멘토는 행위 패턴이다. 객체의 내부 상태를 캡슐화를 깨지 않고 메멘토 객체에 저장해 두었다가, 나중에 그 메멘토로 되돌린다 — 편집기의 실행 취소(Undo), 게임 저장이 이것이다. 원본(Originator)이 메멘토를 만들고, 관리자(Caretaker)가 보관한다.
따라가기
헷갈리는 자리 — 퍼사드를 어댑터로 적는 것. 어댑터는 인터페이스를 "변환"하고, 퍼사드는 여러 개를 "단순화"한다. 메멘토를 커맨드로 적는 것 — 커맨드도 Undo 를 하지만 "요청을 객체로" 만드는 것이 본질이고, 메멘토는 "상태 스냅샷"이 본질이다.
이전 자료의 예상 문제다. GoF 패턴 정의와 대조했다.
입력 유효 범위가 0~100인 프로그램을 테스트하기 위해 -1, 0, 100, 101을 테스트 데이터로 선정했다. 오류가 경계 부근에 집중된다는 점을 이용한 이 블랙박스 테스트 기법은?
답 — 경계값 분석(Boundary Value Analysis). 유효 범위 0~100 의 양 끝과 바로 바깥(−1 · 0 · 100 · 101)을 고른 것이 표지다.
원리 — 프로그래머의 실수는 경계에서 몰린다 — if (x < 100) 을 <= 로 써야 했다거나, 배열 크기를 하나 작게 잡았다거나. 그래서 동치 분할로 묶음을 나눈 뒤, 묶음의 가운데가 아니라 "경계와 그 바로 옆"을 검사하면 오류를 훨씬 잘 잡는다. 유효 범위가 0~100 이면 경계는 0 과 100 이고, 안쪽 값 0 · 100 과 바깥쪽 값 −1 · 101 을 고른다(2값 방식). 3값 방식이면 1 · 99 까지 더한다. 동치 분할이 "어디를 나눌까"라면 경계값 분석은 "나눈 선 위에서 검사하자"다.
따라가기
헷갈리는 자리 — 동치 분할로 적는 것. 동치 분할은 50 같은 대표값을 고르고, 경계값은 0 · 100 · −1 · 101 을 고른다. 입력 데이터가 "경계 양옆"이면 경계값 분석이다. 두 기법은 보통 같이 쓴다 — 동치 분할로 묶음을 나누고, 각 묶음의 경계에서 경계값을 뽑는다. 그래서 문제가 둘 중 무엇을 묻는지는 "제시된 입력값이 대표값인가 경계값인가"로만 갈린다.
이전 자료의 예상 문제다. 표준 정의(ISTQB · V 모델)와 대조했다.
교착상태(Deadlock) 발생 4가지 필요조건 중 빈칸 2개: 상호 배제, 점유와 대기, ( ① ), ( ② )
답 — ① 비선점 ② 환형 대기(순환 대기). 교착상태 4조건은 상호 배제 · 점유와 대기 · 비선점 · 환형 대기다.
원리 — 교착상태(deadlock)는 여러 프로세스가 서로가 가진 자원을 기다리며 영원히 멈추는 것이다. 네 조건이 "동시에" 성립해야 생긴다. 상호 배제 — 자원을 한 번에 하나만 쓸 수 있다(프린터). 점유와 대기 — 이미 가진 것을 쥔 채로 다른 것을 기다린다. 비선점 — 남이 가진 자원을 강제로 뺏을 수 없다. 환형 대기 — A 는 B 것을, B 는 A 것을 기다리는 식으로 대기가 원을 이룬다. 넷 중 하나라도 깨면 교착이 안 생기므로 "예방"은 조건 하나를 없애는 것이고, "회피"는 은행원 알고리즘으로 안전 상태만 허용하는 것이다.
따라가기
헷갈리는 자리 — 비선점을 "선점"으로 적는 것. 자원을 뺏을 수 있으면(선점) 교착이 풀리므로 교착 조건은 "비선점"이다. 환형 대기는 "순환 대기 · 원형 대기"로도 쓴다.
이전 자료의 예상 문제다. 표준 정의 · 손 계산으로 확인했다.
왜 이걸 하나 — 점수보다 어느 장으로 돌아가느냐가 결과다. 문항마다 가는 장이 정해져 있다.
코드 9문항 중 C 4 · Java 3 · Python 2 다. 1번은 오버라이딩된 cry 는 자식 것(D)이고 필드 name 은 참조형 것(Animal)이라 DAnimalAnimal, 8번은 5 + 3 이 먼저 8 이 되고 그 뒤로는 문자열 결합이라 8결과53 이다. 9번은 2차원 배열의 첫 행 주소에 4 를 더하면 두 번째 행 둘째 원소(5)다.
5번은 arr[3] 에서 예외가 나 그 줄 뒤의 print(arr[1]) 은 안 돌고 catch E · finally F · 그 뒤 G 다. 예외가 난 줄 다음부터 catch 까지가 건너뛰는 구간이라는 것을 표로 확인한다.
용어 11문항은 SQL·DB 4(HAVING 결과 · GRANT 작성 · 부분 함수 종속 · 원자성/영속성) · SW공학 3(퍼사드/메멘토 · 경계값 분석 · 교착상태 4조건) · 네트워크 2(/26 서브넷 · DHCP) · 보안 2(파밍 · RSA/ECC)다. 11번 GRANT 문은 WITH GRANT OPTION 까지 적어야 5점이다.
틀린 문항의 「가는 장」을 열면 그 문항이 04절에 그대로 있고, 앞뒤로 같은 꼴의 문항이 붙어 있다. 몰라서 틀렸으면 그 장 03절부터, 알았는데 틀렸으면 05절만 읽는다. 판정 기준은 E01 의 03절 표와 같다.
| 문항 | 분야 | 가는 장 | 무엇을 묻나 |
|---|---|---|---|
| 1 | Java | E05 | 오버라이딩 cry 와 가려진 필드 name |
| 2 | C | E02 | 문자열 포인터 s + 6 · *(s + 2) · *s + 2 |
| 3 | C | E03 | 자릿수 합 재귀 |
| 4 | Python | E07 | sorted key=d.get 값 기준 정렬 |
| 5 | Java | E06 | 배열 첨자 예외 뒤 finally 흐름 |
| 6 | C | E04 | 비트 & | ^ 계산 |
| 7 | Python | E07 | 컴프리헨션과 집합 중복 제거 |
| 8 | Java | E06 | int + int + 문자열 결합 순서 |
| 9 | C | E02 | 2차원 배열을 1차원 포인터로 *(p + 4) |
| 10 | SQL | E08 | GROUP BY + HAVING AVG 결과 |
| 11 | SQL | E09 | GRANT … WITH GRANT OPTION 작성 |
| 12 | DB | E10 | 부분 함수 종속 제거 → 2NF |
| 13 | DB | E10 | 원자성 · 영속성 |
| 14 | 네트워크 | E12 | /26 두 번째 서브넷 브로드캐스트와 호스트 수 |
| 15 | 네트워크 | E11 | IP 자동 할당 DHCP |
| 16 | 보안 | E14 | DNS 조작 파밍 |
| 17 | 보안 | E13 | RSA 와 ECC |
| 18 | 디자인패턴 | E17 | 퍼사드와 메멘토 |
| 19 | 테스트 | E18 | 경계값 분석 |
| 20 | OS | E16 | 교착상태 4조건 빈칸 |
| 문항 | 왜 갈리나 |
|---|---|
| 1번 | a.sound() → cry() 는 Dog 것 D, name 은 Animal 의 것. a.name 도 참조형 Animal 의 것 |
| 9번 | a[0] 은 첫 행의 시작. p + 4 는 1 2 3 4 5 6 중 다섯째 → 5. a[1][0] 은 4 |
| 12번 | (학번, 과목코드) 가 키인데 학번 → 학생이름 이 있으면 부분 함수 종속이다. 떼어내면 2NF |
| 14번 | /24 를 4개로 나누면 /26, 블록 64. 두 번째 서브넷은 64~127 이라 브로드캐스트 .127, 호스트 62 |
채점 결과는 오답노트에 회차별 점수와 틀린 문항 목록으로 모인다. 세트를 하나 끝낼 때마다 거기서 같은 장에서 반복해서 틀리는지를 본다. 두 세트에서 같은 장이 나오면 그 장의 06절 훈련을 그날 5문항 푼다.
왜 이걸 하나 — 세트의 결과는 다음에 열 장의 이름이어야 한다.