[TIL/정처기] 2025/03/24
23년 1회 기출 코드 정리 ✍️ 23-1-1-JAVA ⚙️ 23-1-2-C ⚙️ 23-1-3-C ⚙️ 23-1-9-C ⚙️ 23-1-14-C ⚙️ 23-1-15-Python ⚙️ 23-1-17-JAVA ⚙️ 23-1-20-JAVA ⚙️ > 이론 문제
23년 1회 기출 코드 정리 ✍️
23-1-1-JAVA ⚙️
class Static {
public int a = 20;
static int b = 0;
}
public class Test {
public static void main(String[] args) {
int a = 10;
Static.b = a;
Static st = new Static();
System.out.println(Static.b++);
System.out.println(st.b);
System.out.println(a);
System.out.print(st.a);
}
}static 변수는, 객체 변수 선언 없이 사용할 수 있다. 즉 b에 대해서는 객체 변수 선언 없이 ``Static.b``와 같은 방식으로 접근할 수 있다. a는 인스턴스 변수다. 따라서 객체를 생성해야만 접근할 수 있고, 각 객체마다 독립적인 값을 갖게 된다. 따라서 최초에는 10, 이후에는 후위 연산자에 의해 증가된 값인 11이 출력된다. 추가적으로, a는 지역변수 10을 출력하고 st.a는 객체 변수 선언에 대한 a이기 때문에 인스턴스 변수 값에 해당하는 20을 출력하게 된다.
JAVA에서 사용되는 변수들의 성격에 대해 잘 이해하고 있는지 묻는 코드라고 요약할 수 있다.
23-1-2-C ⚙️
#include <stdio.h>
main(){
char a[] = "Art";
char* p = NULL;
p = a;
printf("%s\n", a);
printf("%c\n", *p);
printf("%c\n", *a);
printf("%s\n", p);
for(int i = 0; a[i] != '\0'; i++)
printf("%c", a[i]);
}포인터와 배열은 주소를 기반으로 데이터를 참조한다는 점에서 유사하다. 다만, 배열 이름 a는 주소가 고정되어 변경할 수 없지만, 포인터 p는 다른 주소를 가리킬 수 있다는 점에 차이가 있다. 코드 자체는 매우 쉽다.
23-1-3-C ⚙️
#include <stdio.h>
main(){
char* a = "qwer";
char* b = "qwtety";
for(int i = 0; a[i] != '\0'; i++)
for(int j = 0; b[j] != '\0'; j++)
if(a[i] == b[j])
printf("%c", a[i]);
}중첩 루프에 대한 간단한 이해를 확인하는 코드다. 코드 자체는 매우 쉽다. 중첩 루프를 다룰 때에는 조건을 먼저 확인하는 것이 좋다. a[i] == b[j] 부분만 봐도, 두 문자열에서 같은 글자를 순서대로 출력하는 코드임을 직관적으로 파악할 수 있다. 표를 그려서 차근차근 풀어내자.
23-1-9-C ⚙️
#include <stdio.h>
main(){
int input = 101110;
int di = 1;
int sum = 0;
while (1)
{
if(input == 0) break;
sum = sum + (input % 10) * di;
di = di * 2;
input = input / 10;
}
printf("%d", sum);
}101110을 이진수 값으로 변경하는 간단한 코드다. 처음에 주어진 101110이 십진수가 아니라 이진수인 줄 알고, 불필요한 고민을 많이 했던 코드다. 최종 결과는 46이다.
23-1-14-C ⚙️
#include <stdio.h>
void swap(int* a, int idx1, int idx2){
int t = a[idx1];
a[idx1] = a[idx2];
a[idx2] = t;
}
void Usort(int* a, int len){
for(int i = 0; i < len - 1; i++)
for(int j = 0; j < len - 1 - i; j++)
if(a[j] > a[j+1])
swap(a, j, j + 1);
}
main(){
int a[] = {85, 75, 50, 100, 95};
int nx = 5;
Usort(a, nx);
}swap() 함수를 통해, 버블 정렬로 배열에 저장된 수를 오름차순으로 정렬하는 코드다. 개정 이후 정처기 코드 문제를 40% 정도 학습하니, 이 정도 코드에 대한 답은 툭 치면 탁 나온다.
중첩 루프 구조일 때 세부적인 함수의 로직을 먼저 고려하기보다는, 인덱스의 변화를 표의 형태로 먼저 그려놓는 것이 훨씬 유리하다는 노하우가 생겼다.
23-1-15-Python ⚙️
asia = {'한국', '중국', '일본'}
asia.add('베트남')
asia.remove('일본')
asia.update({'한국', '홍콩', '태국'})
print(asia)파이썬의 set 자료는 중복을 허용하지 않는다는 사실을 알고 있는지 묻는 코드다. '한국'이 중복되는 상황이므로 update를 수행할 때 무시된다. 따라서 최종 출력 결과는 {'한국', '중국', '베트남', '홍콩', '태국'}이다.
23-1-17-JAVA ⚙️
abstract class Vehicle{
String name;
abstract public String getName(String val);
public String getName(){
return "Vehicle name : " + name;
}
}
class Car extends Vehicle{
private String name;
public Car(String val){
name = super.name = val;
}
public String getName(String val){
return "Car name : " + val;
}
public String getName(byte[] val){
return "Car name : " + val;
}
}
public class Test{
public static void main(String[] args) {
Vehicle obj = new Car("Spark");
System.out.print(obj.getName());
}
}다형성에 의해 오버라이딩된 자식의 메소드를 먼저 활용해야 하는데, 파라미터에 아무것도 전달하지 않는 getName() 함수는 자식에게 정의되어 있지 않다. 따라서 부모의 getName(String val)를 실행하게 되고, 최종적으로 Vehicle name : Spark가 출력된다.
메소드의 이름이 동일해도 인수의 자료형과 개수가 다르면 서로 다른 메소드임을 알고 있는지 묻는 코드라고 정리할 수 있다.
23-1-20-JAVA ⚙️
class Parent{
int x = 1000;
Parent(){
this(3000);
}
Parent(int x){
this.x = x;
}
}
class Child extends Parent{
int x = 4000;
Child(){
this(5000);
}
Child(int x){
this.x = x;
}
int getX(){
return this.x;
}
}
public class Test{
public static void main(String[] args) {
Child c = new Child();
System.out.println(c.getX());
}
}자바의 상속과 생성자 체이닝(constructor chaining)을 보여주는 코드다. 최초에 c를 생성하면 파라미터가 없는 Child(){this(5000);}가 먼저 실행되는데, this(5000);으로 넘어가기에 앞서 Parent의 기본 생성자가 먼저 실행된다. 자식 클래스의 생성자에는 super()와 같이 부모 클래스 생성자를 호출하는 코드가 묵시적으로 포함되어 있기 때문이다.
하지만 Parent에서 this.x에 3000을 저장하더라도, 이후 Child(int x){} 함수가 실행되며 this.x는 5000이 된다. 따라서 최종적인 출력 결과는 5000이 된다.
이론 문제 포인트 ✍️
1. 하향식 통합 테스트 ✅ - 상위 모듈에서 하위 모듈 방향으로 통합하면서 테스트하는 기법 1. 주요 제어 모듈은 작성된 프로그램을 사용하고, 주요 제어 모듈의 종속 모듈들은 스텁(Stub)으로 대체함 2. 깊이 우선 또는 넓이 우선 등의 통합 방식에 따라 하위 모듈인 스텁들이 한 번에 하나씩 실제 모듈로 교체됨 3. 모듈이 통합될 때마다 테스트를 실시 4. 새로운 오류가 발생하지 않음을 보증하기 위해 회귀 테스트를 실시
스텁(Stub): 제어 모듈이 호출하는 타 모듈의 기능을 단순히 수행하는 도구, 일시적으로 필요한 조건만을 가지고 있는 시험용 모듈
2. 상향식 통합 테스트 ✅ - 하위 모듈에서 상위 모듈 방향으로 통합하면서 테스트하는 기법 1. 하위 모듈들을 클러스터(Cluster)로 결합 2. 상위 모듈에서 데이터의 입출력을 확인하기 위해 더미 모듈인 드라이버(Driver)를 작성 3. 통합된 클러스터 단위로 테스트 4. 테스트가 완료되면 클러스터는 프로그램 구조의 상위로 이동하여 결합하고 드라이버는 실제 모듈로 대체
테스트 드라이버(Test Driver): 테스트 대상의 하위 모듈을 호출하고, 파라미터를 전달하고, 모듈 테스트 수행 후의 결과를 도출하는 도구
3. 회귀 테스트 ✅ - 통합 테스트로 인해 변경된 모듈이나 컴포넌트에 새로운 오류가 있는지 확인하는 테스트 - 이미 테스트된 프로그램의 테스팅을 반복하는 것 - 회귀 테스트는 수정한 모듈이나 컴포넌트가 다른 부분에 영향을 미치는지, 오류가 생기지 않았는지 테스트하여, 새로운 오류가 발생하지 않음을 보증하기 위해 반복 테스트함
4. 테스트 오라클의 종류 ✅ - ``참(True) 오라클``: 모든 테스트 케이스의 입력 값에 대해 기대하는 결과를 제공하는 오라클로, 발생된 모든 오류를 검출할 수 있음
- ``샘플링(Sampling) 오라클``: 특정한 몇몇 테스트 케이스의 입력 값들에 대해서만 기대하는 결과를 제공하는 오라클로, 전수 테스트가 불가능한 경우 사용하는 오라클
- ``추정(Heuristic) 오라클``: 특정 테스트 케이스의 입력 값에 대해 기대하는 결과를 제공하고, 나머지 입력 값들에 대해서는 추정으로 처리하는 오라클
- ``일관성 검사(Consistent) 오라클``: 애플리케이션에 변경이 있을 때, 테스트 케이스의 수행 전과 후의 결과 값이 동일한지를 확인하는 오라클
5. 애플리케이션 성능 측정 지표 ✅ - ``처리량(Troughput)``: 일정 시간 내에 애플리케이션이 처리하는 일의 양
- ``응답 시간(Response Time)``: 애플리케이션에 요청을 전달한 시간부터 응답이 도착할 때까지 걸린 시간
- ``경과 시간(Turn Around Time)``: 애플리케이션에 작업을 의뢰한 시간부터 처리가 완료될 때까지 걸린 시간
- ``자원 사용률(Resource Usage)``: 애플리케이션이 의뢰한 작업을 처리하는 동안의 CPU, 메모리, 네트워크 사용량 등 자원 사용률
6. 소스 코드 품질 분석 도구 ✅
- ``정적 분석(Static Analysis) 도구`` - 작성한 소스 코드를 실행하지 않고 코딩 표준이나 코딩 스타일, 결함 등을 확인하는 코드 분석 도구 - pmd, cppcheck, SonarQube, checkstyle, ccm, cobertura 등
- ``동적 분석(Dynamic Analysis) 도구`` - 작성한 소스 코드를 실행하여 코드에 존재하는 메모리 누수, 스레드 결함 등을 분석하는 도구 - Avalanche, Valgrind 등
7. CREATE INDEX ✅
- 인덱스를 정의하는 명령문
CREATE [UNIQUE] INDEX 인덱스명
ON 테이블명(속성명[ASC|DESC][,속성명[ASC|DESC]])
[CLUSTER];예) <고객> 테이블에서 UNIQUE한 특성을 갖는 '고객번호' 속성에 대해 내림차순으로 정렬하여 '고객번호_idx'라는 이름으로 인덱스를 정의하시오
CREATE UNIQUE INDEX 고객번호_idx
ON 고객(고객번호 DESC);8. ALTER TABLE ✅
- 테이블에 대한 정의를 변경하는 명령문
ALTER TABLE 테이블명 ADD 속성명 데이터_타입 [DEFAULT '기본값'];
ALTER TABLE 테이블명 ALTER 속성명 [SET DEFAULT '기본값'];
ALTER TABLE 테이블명 DROP COLUMN 속성명 [CASCADE];예) <학생> 테이블에 최대 3문자로 구성되는 '학년' 속성을 추가하시오
ALTER TABLE 학생 ADD 학년 VARCHAR(3);예) <학생> 테이블의 '학번' 필드의 데이터 타입과 크기를 VARCHAR(10)으로 하고 NULL 값이 입력되지 않도록 변경하시오
ALTER TABLE 학생 ALTER 학번 VARCHAR(10) NOT NULL;9. GRANT / REVOKE ✅
- 권한을 부여하거나 회수하기 위한 명령어
GRANT 권한_리스트 ON 개체 TO 사용자 [WITH GRANT OPTION];
REVOKE [GRANT OPTION FOR] 권한_리스트 ON 개체 FROM 사용자 [CASCADE];예) 사용자 ID가 "NABI"인 사람에게 <고객> 테이블에 대한 모든 권한과 다른 사람에게 권한을 부여할 수 있는 권한까지 부여하는 SQL문을 작성하시오
GRANT ALL ON 고객 TO NABI WITH GRANT OPTION;예) 사용자 ID가 "STAR"인 사람에게 부여한 <고객> 테이블에 대한 권한 중 UPDATE 권한을 다른 사람에게 부여할 수 있는 권한만 취소하는 SQL문을 작성하시오
REVOKE GRANT OPTION FOR UPDATE ON 고객 FROM STAR;10. ROLLBACK ✅
- 변경되었으나 아직 COMMIT되지 않은 모든 내용들을 취소하고 데이터베이스를 이전 상태로 되돌리는 명령어 - 트랜잭션 전체가 성공적으로 끝나지 못하면 일부 변경된 내용만 데이터베이스에 반영되는 비일관성 상태가 될 수 있기에, 일부분만 완료된 트랜잭션은 롤백(ROLLBACK)되어야 함
More to read
Amazon VPC Architecture 이해하기
새로운 프로젝트를 기획하며, 개발에서 무엇을 가장 먼저 고민해야 하는지 다시 돌아보게 되었습니다.한때는 프론트엔드가 모든 설계의 출발점이라고 믿었습니다. 유저가 무엇을 보고, 어떤 흐름에서 머무르고 이탈하는지에 대한 이해 없이 서비스를 만든다는 건 불가능하다고 생각했기
'원사이트'프론트엔드 관점으로 알고리즘 이해하기
오랜만에 방법론에 관한 글을 쓰게 되었습니다. 최근 상황은 이렇습니다. SSAFY에서는 하루에 엄청난 양의 알고리즘 문제들을 과제로 수행하게 됩니다. 그 과정에서, '구현력'이 매우 떨어진다는 생각이 들었습니다. 완전히 어려운 문제라면 '아쉬움'이라는 감정조차 느끼지
SubnetVPC 설계의 시작: IP와 Subnet
반복되는 루틴 속에서 얻은 안정감을 발판 삼아, 이제는 기술적 스펙트럼을 넓히기 위한 개인 프로젝트에 착수하고자 합니다.이번 프로젝트의 목표는 단순한 포트폴리오 구축을 넘어, 실제 서비스 수준의 블로그 시스템 구현과 다국어 처리 적용 등 실무에 가까운 역량을 한 단계