인프런 널널한 개발자 강사님의 기초 탄탄! 독하게 시작하는 Java - Part2 : OOP와 JVM의 강의 중 JVM내용 정리


 

Class Loader는 우리가 직접 만들수도 있다고 합니다. C/C++로 구현하지 않고 JAVA로도 직접 구현해서 사용할 수 있다고 하네요.

Class Loader에 대해 이해하기 위해 .class 파일과 바이트 코드에 대해 짚고 넘어갑니다.

 

.class 파일은 .java파일을 컴파일 했을때 생성되는 자바 바이트 코드입니다.

 이것을 Class Loader가 Loading하는 것입니다. 윈도우로 치면 .exe, .dll 같은 확장자를 가진 실행파일(PE)이 JVM에서는 .class파일인 겁니다.

class 파일의 구조는 아래와 같다고 합니다.

ClassFile {
    u4 				magic;
    u2 				minor_version;
    u2 				major_version;
    u2 				constant_pool_count;
    cp_info 			constant_pool[constant_pool_count-1];
    u2 				access_flags;
    u2 				this_class;
    u2 				super_class;
    u2 				interfaces_count;
    u2 				interfaces[interfaces_count];
    u2 				fields_count;
    field_info 			fields[fields_count];
    u2 				methods_count;
    method_info 		methods[methods_count];
    u2 				attributes_count;
    attribute_info 		attributes[attributes_count];
}

 

위에서 부터

u4는 unsigned 캐릭터 아마 4바이트

밑으로 minor_version, major_version 정보가 나와있고

그 밑에 중요한 constant_pool_count 얘기가 나옵니다. 아무튼 이것저것 this class, super class, field, method, 이런정보가 담겨져 있구나 라는걸 알 수 있씁니다.

 

 

 

사진은 대표적인 Hello World! 코드를 컴파일한 .class 을 16진수 편집기로 열어본 것입니다.

 

맨 앞의 CA FE BA BE 이 4바이트가 위에서 u4에 해당하는 거고, 그 뒤로 major/minor 버전, constant pool 등등 정보가 담겨져 있는 것입니다. 근데 뭐 저거만 보고 리버스 엔지니어링을 하는 것은 힘들기 때문에 보통 도구를 이용해서

.class 파일을 분석하기도 한다고 합니다.

 

IntelliJ에서도 바이트코드를 볼 수가 있는데

바이트 코드 보는법은 생략하고 저런식으로 더 쉬운 형태로 변환하여 .class 파일을 분석할 수 잇다고 합니다.

저런 거로 디컴파일도 할 수 있다고 하네요.

 

아무튼

 

Hello World를 출력하는 .java 파일이 java byte code로 바뀌고 그걸 JVM이라는 프로세스가 실행시켜주는데,

근데 실질적으로 실행은 CPU가 하는 것입니다.

자바로 프로그램을 개발하게 되면 결국은 자바 소스코드 말고,

.class 파일에 들어있는 형태인 자바 바이트 코드의 스트림 형태로 변환이 되어서 로딩되고 적재된 다음에 어쩌구저쩌구 쭈욱 가는겁니다.

 

 

 

자바 바이트코드의 실행의 근거가 되어주는 것들은 JVM에서의 명령들입니다. 근데 JVM 자체가 가상 머신이지 진짜 머신(CPU)는 아닙니다. 그래서 결과적으로 그것들(바이트코드들)을 CPU가 인식할 수 있는 Native코드로 바꾸어 주어야 합니다. 그래서 그 과정에서 사용되는 컴파일러가 등장합니다. 그래서 컴파일러가 두 번 등장하는데

첫 번째로, .java파일을 .class 파일로 바꾸는 컴파일러.

두 번째로, .class파일을 CPU가 이해할 수 잇는 Native 코드로 바꾸는 컴파일러

네이티브로 바꿔주는 컴파일러는 두 놈이 있습니다.

 

출처: https://medium.com/webeveloper/jvm-java-virtual-machine-architecture-94b914e93d86

JVM의 3가지 영역 중 Execution Engine에 해당되는 부분에서 Interpreter와 JIT Compiler 입니다.

 

JIT컴파일러(Just-In-Time) 는 JVM이 바이트코드 레벨에서 분석을 해서 예를들어 반복문을 돈다고 하면 반복문 안의 코드는 특정 횟수 만큼 반복이 될 것입니다 이런 반복되는 부분에대해 JIT가 미리 컴파일을 해놓습니다.

평상시에는 Interpreter가  바이트코드를 일정 단위 뜯어와서 CPU에 번역해서 연산시키고 합니다. 근데 이걸 매번 변환하는 과정을 거친다는 것은 성능을 떨어뜨리는 원인이 됩니다.

그래서? JIT가 자주 사용되는 부분을 미리 번역해놓고 재사용하기 때문에 JIT로 인해 JVM의 성능이 극단적으로 상승했다고 합니다.

 


 

Class Loader

클래스로더의 역할을 생각해보면 하는 일도 많고 중요하기도 하지만 생각보다 이걸 건드리거나 할 일은 많이 없다고 합니다. 따라서 클래스로더가 무슨일을 하는지 이론적으로만 알아도 된다고 합니다.

 

우리가 작성한 JAVA파일을 class 파일로 컴파일이 되고, class파일 안에 있는 자바 바이트코드를 JVM이 뜯어와서 실행을 하게 됩니다.

중요한 점은 바이트 코드의 본질은 결국에는 Method라는 것입니다.

 

클래스 로더가 하는 일은 아래와 같습니다.

 

1. 이름을 알고 있는 특정 클래스에 대한 정의(Byte Stream)를 가져오는 역할을 수행

  -> 가져온다라는 의미를 생각해 보면 어디 다른곳에서 가져올 수 있다는 의미입니다. 네트워크를 통해 퍼온다거나 할 수 있습니다.

2. 부트스트랩 클래스 로더

  - JVM에서 라이브러리로 취급(rt.jar, tools.jar)되는 것들을 로드 (핫스팟에서는 C++로 구현)

3. 플랫폼 클래스 로더 (기존 확장 클래스 로더)

  - 클래스 라이브러리 로드

4. 애플리케이션 클래스 로더

  - sun.misc.Launcher$AppClassLoader를 의미

 

 

클래스가 로딩되는 과정

 

개발자에게는 3가지 시점이 있습니다.

1. 컴파일타임

2. 링크타임

3. 런타임

그런데 자바에서는 이렇게 구분하는 개념이 없습니다. build를 하면 컴파일타임을 말하고 실행을 하면 링크 + 런타임을 묶는다고 합니다.

 

출처 : 강의자료 일부

그래서 클래스를 로딩하겠다 하면 JVM이 인식할 수 있게 하는 자바 바이트코드 스트림 덩어리로 바꾸는 과정을 로딩 단계라고 합니다. 위 그림에서는 Loading -> Linking 까지 입니다.

그리고 사용단계는 그 아래쪽인데 사용단계 수준에서 인스턴스화를 진행합니다. 즉, new 연산이 등장하는거죠 그래서 Using 박스 안에 Initializaion(초기화) 가 있는 것입니다.

그리고 Unloading은 GC를 통해 메모리가 해제되는 것입니다.

 

Java 클래스 로딩

- 클래스 로딩 및 링킹 과정이 모두 런타임에 이루어짐

- 실행 성능이 일부 저하될 수 있으나 높은 확장성과 유연성을 제공하는 근간

  - 인터페이스만 맞으면 Runtime에 구현 클래스를 결정하지 않을 수 잇음

  - 클래스 로더는 실행할 프로그램 코드를 네트워크로 수신하는 것도 가능

- 해석(Resolution) 단계는 동적 바인등(혹은 늦은 바인딩)을 지원할 목적으로 초기화 후로 지연될 수 있음

 

 

로딩 단계에서 가장 먼저 하는일, 검증.(Verification)

- JVM 명세가 정하는 규칙과 제약을 만족하는지 확인합니다.

  - 파일 형식(.class)

  - 메타데이터

  - 바이트코드

  - 심벌 참조

- 보안위협에 대한 검증 포함

  - 바이트코드 검증 시 함께 확인

 

준비 및 해석단계(Preparation, Resolution)

- java.lang.Class 인스턴스(메타 데이터)가 힙 영역에 생성되고 클래스 변수(정적 멤버) 메모리를 0으로 초기화

  -> 로드되는 클래스의 인스턴스는 Using 단계에서 힙 사용

  -> final 선언된 변수는 코드에서 정의한 초깃값으로 정의(0이 아닐수 있다)

- 생성자 호출 전 상태(new 연산 전 단계)

  -> 필드(인스턴스 변수) 초깃값은 생성자 호출 시 정의됨

  -> 정적 필드에 초깃값 할당

- 해석은 상수 풀의 심벌 참조를 직접 참조로 대체하는 과정

 

 

사용단계

Heap 영역에 객체 생성 (new 연산 실행) 

- JVM은 객체 저장을 위한 메모리 공간을 확보 후 0으로 초기화 (단, 객체 헤더 제외)

- 객체 초기화를 위한 구성설정 실시

  -> 클래스 이름 및 메타 정보 확인 방법

  -> 객체에 대한 해시코드

  -> GC 세대 나이

- 생성자 호출

 

'CS > JAVA' 카테고리의 다른 글

JVM 이해하기 (1) - 도입  (3) 2025.01.28
옵저버 패턴 정리  (0) 2024.07.21

인프런 널널한 개발자 강사님의 기초 탄탄! 독하게 시작하는 Java - Part2 : OOP와 JVM의 강의 중 JVM내용 정리


 

 

개발을 하고 서비스를 하면서 장애가 났을때에 다양한 원인이 있겠지만, 해결을 하려할 때 JVM에 대한 깊은 이해가 없을경우 해결을 못하는 경우가 있습니다. 

 

JVM에 대한 이해를 쌓고자 강의를 들으면서 알게 된 것들과 중요한 내용을 지금부터 정리해보겠습니다


 

 

JVM은 결과적으로 보면 프로세스이다.  java.exe 실행 파일을 실행시켜서 그 위에서 내가 만든 어플리케이션을 돌리는 것이다.

JVM은 기본적으로 Virtual Machine이다.

여담

널널한 개발자님 강의를 보다 보면 설명을 하시면서 물리적/논리적 개념으로 나누는데 

물리적인 부분 == H/W
논리적인 부분 == S/W
으로 봐도 된다.

또한 논리적이다 라는 말은 가상이라는 개념으로 봐도 된다고 종종 말씀하신다.
logical 을 IT쪽에서는 Virtual이라고 한다.
그리고 컴퓨터에서 CPU를 machine이라고도 한다고 하는데 그렇다면
Vircual Machine이다 라고 하면 CPU를 논리적으로 구현한것이다 라고 해석할 수 있다.

 

 

 

강사님께서 정말 많이 자주 그리시는 컴퓨터의 형태이다.

 

하드웨어 영역과 소프트웨어 영역으로 나누어져 있고, 소프트웨어영역은 Application영역과 System영역이 있다. System 영역의 가장 대표적인게 운영체제인데, 운영체제의 핵심적인 알맹이를 커널이라고 한다. 

커널은 그림에서 Kernel 영역에서 돌아가는 것이고

User Mode Application 영역이 있는데, 이것은 이제 위 그림에서 User 영역에서 돌아가는것이다.

 

우리가 소위 Native라고 부르는 영역은 H/W부터 Kernel까지 포함하는 구간이다.

그래서 그 부분을 개발하는것은 C/C++과 같이 Native언어로 개발을 하는데, C/C++코드가 CPU가 이해할 수 있는 언어로 직접 번역이 되어 실행합니다.

그렇기떄문에 H/W나 OS에 의존성이 있고, 의존성이 있다는 말은 Window에서 개발한 C/C++코드가 있으면 그 코드는 리눅스에서 제대로 동작하지 않을 수 있다는 것입니다.

 

처음에 말했듯 VM이라는 것은 컴퓨터를 소프트웨어적으로 구현한 것이다. 머신은 머신인데 이 머신이 인식할 수 있는 코드가 자바 바이트 코드라면 그걸 JVM 이라고 한다는 것이다.

 

결과적으로 JVM이라는것을 말하면 소프트웨어로 CPU도 구현돼있고, RAM도 구현돼있고, SSD도 구현돼있는 것이다. 따라서 JVM은 User Mode Applicatio 프로세스 임과 동시에 가상 메모리 공간을 RAM이나 보조기억장치처럼 활용 하면서 동시에 머신으로 연산도 해주는기능을 모두 포함하고 추가로 운영체제가 제공하는 기능 일부까지 다 들어있습니다.

 

따라서 JVM은 CS론에서 "OS/컴퓨터구조 를 전부 섞어서 C나 C++로 구현" 한게 JVM이 된다는 것이다.

그래서 위에서 잠깐 설명한 네이티브영역을 개발하는 언어들과 다르게 JVM만 있다면 내가 만든 자바코드는 JVM이 돌려주기 때문에 OS에 영향이 없이 JVM만 있다면 돌릴 수 있는 것이다.

 

C++ 과 Java의 메모리 관리 차이

C++ Java
- 객체에 대한 모든 관리 책임은 개발자에 있다.(소유권, 메모리 할당 및 해제)

- 객체의 생명주기에 모두 개입하는 구조
- 객체 메모리 해제는 전적으로 JVM몫이다.(개발자에게는 소유권도 책임도 없음)

- 문제 발생 시 구조를 알아야 대응이 가능함

 

C++은 자유도가 극상에 가깝다. 근데 자유도가 극상인 만큼 책임도 많이 져야한다.

자바는 GC가 메모리관리를 해준다. 

 


 

JVM 구성요소

출처 : https://medium.com/webeveloper/jvm-java-virtual-machine-architecture-94b914e93d86

 

1. Class Loader,  2. Runtime Data Area, 3.  Execution Engine으로 크게 3가지 영역으로 나뉜다.

아무 영역에 속하지 않은 Native Method이쪽은 User Mode가 아닌 Kernel모드 수준에서의 API를 호출하게 해주는걸 가능하게 해준다.

나는 3가지 영역에 대해서만 알아볼거고, 2번 Runtime Data Area영역이 가장 중요하다고 한다.

 

 

'CS > JAVA' 카테고리의 다른 글

JVM 이해하기 (2) - Class Loader  (2) 2025.01.29
옵저버 패턴 정리  (0) 2024.07.21

질문

더보기
  1. HTTP 프로토콜이란?
  2. HTTP와 HTTPS의 차이점은?
  3. 대칭 암호화와 비대칭 암호화란?
  4. HTTPS의 최초 연결에 대해
  5. HTTP1과 HTTP2의 차이점은?
  6. HTTP 메소드들과 각각이 쓰이는 
  7. GET과 POST의 차이
  8. POST PUT PATCH의 차이
  9. REST란?
  10. API란?
  11. REST의 특징은?
  12. REST API의 장단점은?
  13. www.naver.com에 접속할 때 생기는 과정 (네트워크 관점에서)
  14. TCP와 UDP의 차이
  15. TCP 접속과 종료
  16. OSI 7계층이란?
  17. OSI 7계층과 TCP/IP 4계층 매핑
  18. OSI 7계층과 TCP/IP의 차이점
  19. 공인 IP와 사설 IP의 차이점
  20. 로드 밸런싱이란?

답변

Q) HTTP 프로토콜이란?

더보기

HTTP 프로토콜이란 서버와 클라이언트가 데이터를 주고 받기 위한 프로토콜입니다. HTTP는 애플리케이션 레벨의 프로토콜로 TCP/IP 위에서 작동합니다. HTTP는 상태 정보를 저장하지 않는 stateless 특성과 클라이언트의 요청에 대한 응답을하면 연결을 끊는 connectionless 특성을 가지고있습니다. 하지만 그렇기 때문에 request가 도착할때마다 다시 인증을 해주어야한다는 단점이 있기에 이를 해결하기 위해 쿠키/세션 등을 활용합니다.

Q) HTTP와 HTTPS의 차이점은?

더보기

HTTP는 plaintext 데이터를 전송하는 프로토콜이기 때문에 제3자에 의해 조회될 수 있습니다. 이 문제를 해결하기 위해 HTTPS를 사용하는 것으로, HTTPS는 HTTP와 같이 바로 TCP와 통신하지 않고 대신, SSL을 통하여 TCP와 통신하는 방식입니다. HTTPS는 대칭키 암호화와 비대칭키 암호화를 동시에 이용하며 서버와 클라이언트가 최초로 연결할 때 대칭키를 주고받기 위해 비대칭키 암호화를 사용하고 그 이후로는 대칭키 암호화를 사용합니다.

Q) 대칭키 암호화와 비대칭키 암호화란?

더보기

대칭키 암호화는 하나의 키로 데이터의 암호화/복호화를 할 수 있는 암호화입니다. 클라이언트와 서버가 동일한 키를 가지고 있고 그 키로 주고 받은 데이터의 암호화/복호화를 진행하는 것을 의미합니다.

비대칭키 암호화란 한쌍의 키로 데이터의 암호화/복호화를 하는 암호화입니다. 비대칭키 암호화의 키는 공개키와 개인키로 이루어져있으며, 공개키로 암호화하여 데이터를 받는 사람을 보장할 수 있고 개인키로 암호화하여 데이터를 보내는 사람을 보장할 수 있습니다. 

Q) HTTPS의 최초 연결에 대해

더보기

HTTPS에서는 최초로 연결을 할때 세션키, 즉 대칭키,를 주고받기 위해 비대칭키 암호화를 사용합니다. 서버는 클라이언트에게 공개키, 즉 인증서,를 전송하고, 클라이언트는 인증서가 유효한지 검사 후 세션키를 생성고 서버에게서 받은 공개키로 암호화하여, 서버에게 이를 전송합니다. 공개키로 암호화된 데이터는 서버만이 가지고있는 개인키로만 복호화가 가능하기 때문에 이를 통해 서버와 클라이언트는 안전하게 세션키를 주고받을 수 있게됩니다.

Q) HTTP1과 HTTP2의 차이점은?

더보기

HTTP1은 연결당 하나의 요청과 응답을 처리하고 이로인해 엔드 유저는 latency와 같은 성능 저하를 경험할 수 있습니다. 이를 개선하기 위해 HTTP2가 개발되었고 HTTP2는 하나의 연결로 다수의 요청과 응답을 처리할 수 있습니다.


Q) HTTP 메소드들과 각각이 쓰이는 곳

더보기

HTTP 메소드는 클라이언트가 서버에게 요청의 목적을 알리는 수단으로 GET, POST, PUT, PATCH, DELETE등이 있습니다. GET은 데이터 조회, POST는 데이터 추가 또는 수정, PUT은 데이터 변경, PATCH는 데이터 일부 변경, DELETE는 데이터 삭제를 의미합니다.

Q) GET과 POST의 차이

더보기

GET은 데이터를 조회하기 위해 사용되는 메소드로 데이터가 URL에 노출되기 때문에 보안적으로 중요한 데이터는 GET을 사용해서는 안됩니다. POST는 데이터를 추가 또는 수장하기 위해 사용되는 메소드로 데이터를 바디에 추가하여 전송하기 때문에 GET보다는 안전합니다.

Q) POST PUT PATCH의 차이

더보기

POST와 PUT 모두 메소드와 생성과 수정을 담당할 수 있으나 RESTful한 API는 자원에 대한 4가지 행위인 CRUD를 구현하기 위해 POST는 Create와, PUT은 Update와 매칭한 것입니다. 이 외에 POST는 멱등하지 않으나 PUT은 멱등하다는 차이점도 존재합니다.

PUT은 리소스의 모든 속성을 수정하기 위해, PATCH는 리소스의 일부만 수정하기 위해 사용됩니다.

 

멱등: 어떤 조작을 몇 번을 반복해도 결과가 동일한 것 

Q) REST란?

더보기

HTTP URI로 자원을 표현하고 HTTP Method로 그 자원에 대한 CRUD 연산을 진행하는 것을 의미합니다.

Q) API란?

더보기

클라이언트와 웹 리소스 사이의 게이트웨이로, 데이터와 기능의 집합을 제공하여 서로 정보를 교환가능 하도록 합니다.

Q) REST의 특징은?

더보기

HTTP 인프라를 그대로 사용하기 때문에 HTTP와 비슷한 특징을 가지고 있습니다. REST는 상태 저장을 하지 않기에 stateless하고 캐시 처리가 가능합니다. 또한 REST는 서버와 클라이언트의 역할을 완전히 분리시키고 다중 계층 구조를 만들 수 있습니다.

Q) REST API의 장단점은?

더보기

REST API는 HTTP 인프라를 그대로 사용하기 때문에 추가 인프라를 구축하지 않아도 되며 메세지가 의도하는 바를 정확히 나타내 사용하기 쉽다는 장점이 있습니다. 그러나 행위가 네개밖에 존재하지 않고 표준이 존재하지 않다는 단점을 가지고있습니다.

Q) www.naver.com에 접속할 때 생기는 과정 (네트워크 관점에서)

더보기
  1. 사용자가 브라우저에 URL을 입력합니다.
  2. 브라우저는 local DNS → 루트 DNS 서버 → .com DNS 서버 → naver.com DNS 서버 순서대로 www.naver.com에 해당하는 IP주소를 찾습니다.
  3. 찾아낸 IP 주소로 웹 서버에 TCP 3 handshake로 연결을 수립합니다.
  4. 브라우저는 HTTP를 사용하여 HTTP 요청 메세지를 생성함니다.
  5. TCP/IP 연결을 통해 HTTP요청이 서버로 전송됩니다.
  6. 서버는 HTTP를 활용해 HTTP 응답 메세지를 생성합니다.
  7. TCP/IP 연결을 통해 요청한 컴퓨터로 전송합니다.
  8. 도착한 HTTP 응답 메세지는 웹페이지 데이터로 변환되고, 웹 브라우저에 의해 출력되어 사용자가 볼 수 있게 됩니다.

Q) TCP와 UDP의 차이

더보기

TCP는 연결형 서비스로 3-way-handshaking 과정을 통해 연결을 설정하기에 높은 신뢰성을 보이지만 속도는 느립니다. UDP는 비연결형 서비스로 신뢰성은 떨어지나 데이터 수신여부를 확인하지 않기 때문에 속도는 빠릅니다. TCP는 신뢰성이 중요한 파일 교환과 같은 경우에서 쓰이고 UDP는 속도가 중요한 실시간 스트리밍과 같은 경우에 쓰입니다.

Q) TCP 접속과 종료

더보기

TCP의 연결을 위해서는 3-way-handshaking이라는 과정을 사용합니다. 클라이언트가 연결을 원한다는 SYN 패킷을 보내고, 서버가 요청을 수락한다는 SYNACK 패킷을 보내고, 클라이언트는 이를 받았다는 ACK 패킷을 보내며 연결을 설정합니다.

TCP의 연결 해제를 위해서는 4-way-handshaking이라는 과정을 통합니다. 클라이언트가 접속 해제를 원한다는 FIN 패킷을 보내고, 서버가 이를 받았다는 ACK 패킷을 보낸 후, 남아있는 나머지 응답들을 모두 보낸 후 해제할 준비가 되었다는 FIN 패킷을 보낸 후, 클라이언트가 이를 받았다는 ACK 패킷을 보냅니다.

Q) OSI 7계층이란?

더보기
  • 7 계층(응용 계층): 사용자와 직접 상호작용하는 응용 프로그램들이 포함된 계층
  • 6 계층(표현 계층): 데이터의 형식(Format)을 정의하는 계층
  • 5 계층(세션 계층): 컴퓨터끼리 통신을 하기 위해 세션을 만드는 계층
  • 4 계층(전송 계층): 최종 수신 프로세스로 데이터의 전송을 담당하는 계층
  • 3 계층(네트워크 계층): 패킷을 목적지까지 가장 빠른 길로 전송하기 위한 계층
  • 2 계층(데이터링크 계층): 데이터의 물리적인 전송과 에러 검출, 흐름 제어를 담당하는 계층
  • 1 계층(물리 계층): 데이터를 전기 신호로 바꾸어주는 계층

Q) OSI 7계층과 TCP/IP 4계층 매핑

더보기
OSI TCP/IP 기술
5,6,7 (세션, 표현, 응용) 4 (응용) HTTP, DNS
4 (전송) 3 (전송) TCP, UDP
3 (네트워크) 2 (인터넷) ARP, RARP, IP, ICMP
1,2 (물리, 데이터링크) 1 (네트워크 접근) MAC

Q) OSI 7계층과 TCP/IP의 차이점

더보기

OSI는 네트워크 연결 표준이 되는 개방 시스템 상호 연결 모델이고 TCP/IP는 컴퓨터간의 통신에서 사용되는 통신 규약의 모음입니다. TCP/IP는 인터넷 개발 이후 계속 표준화 되어 신뢰성이 높은 반면 OSI는 실구현 예가 거의 없어 신뢰성이 낮아 표준을 설정할 때는 사용되나 실질적 통신 자체는 TCP/IP를 사용하는 경우가 많습니다.

Q) 공인 IP와 사설 IP의 차이점

더보기

공인 IP는 ISP가 제공하는 전 세계 유일한 IP 주소이며 외부에 공개되어 있는 IP 주소입니다. 사설 IP는 특정 네트워크 안에서 사용하는 IP주소로 IPv4의 주소 부족으로 인해 생겨났으며 라우터에게서 제공 받는 가상의 주소입니다. 

Q) 로드 밸런싱이란?

더보기

여러개의 서버가 존재할 경우 이 여러대의 서버에 트래픽을 균등하게 배분해주는 것입니다. 특히 scale out한 서버에는 꼭 필요한 절차로 round robin, least connection과 같은 다양한 알고리즘 중 하나를 선택해 진행하게 됩니다. Round robin은 서버에 요청을 돌아가며 순서대로 배정하는 방식이고, least connection 트래픽이 들어온 시점에 가장 적은 연결 상태를 보이는 서버에 배정하는 방식입니다.

'CS > 면접준비' 카테고리의 다른 글

데이터베이스  (0) 2024.08.17
운영체제  (0) 2024.08.17
JAVA  (0) 2024.08.17

질문

더보기
DBMS란?
  1. RDBMS와 NoSQL의 차이점은?
  2. RDBMS와 NoSQL은 언제 사용하는가?
  3. 파티셔닝이란?
  4. 데이터베이스 샤딩이란?
  5. 분할 기법들에는 어떤것이 있는지?
  6. Scale up과 Scale out의 차이점은?
  7. RDBMS에서 scale out이 어려운 이유는?
  8. 클러스터링이란?
  9. 리플리케이션이란?
  10. 데이터베이스 트랜잭션이란?
  11. 데이터베이스 트랜잭션의 성질 ACID에 대해 설명해보시오
  12. DB Lock이란? 그 종류는?
  13. OLTP와 OLAP란?
  14. 인덱스란? 그 종류는?
  15. 인덱스를 사용할 시 단점
  16. 인덱스는 언제 사용해야하는가?
  17. DB 정규화란?
  18. DB 정규형의 종류는?
  19. Key의 종류와 각 특징은?
  20. 정규화를 하는 이유는?
  21. 이상현상의 종류는?
  22. 역정규화를 하는 이유는?
  23. DB 튜닝이란?
  24. DB 튜닝의 종류는?
  25. SQL 문장 종류는?
  26. Select 쿼리의 수행 순서는?
  27. 높은 트래픽을 어떻게 대비할 것인가?

답변

Q) DBMS란?

더보기

DBMS는 데이터베이스 관리 시스템의 약자로 데이터의 집합인 데이터베이스를 관리하고 운용하는 응용 프로그램의 집합니다.

Q) RDBMS와 NoSQL의 차이점은?

더보기

RDBMS는 관계형 데이터베이스 관리 시스템을 의미하며 모든 데이터는 중복이 없고 정확한 스키마를 따르는 2차원 테이블 형태로 저장, 관리됩니다. 그렇기 때문에 데이터의 구조와 정합성을 보장할 수 있으나 scale out이 어렵습니다.

그에비해 NoSQL은 각 데이터의 관계, 스키마와 관련 없이 key-value 값으로 데이터를 관리합니다. 그 덕분에 자유로운 데이터 관리와 scale out이 가능하지만 데이터 중복이 생길 수 있으며 중복된 데이터가 변경될 경우 모든 컬렉션에서 수정을 진행하여야합니다.

 

*정합성: 데이터가 서로 모순 없이 일관되게 일치

Q) RDBMS와 NoSQL은 언제 사용하는가?

더보기

RDBMS는 데이터 무결성을 만족하기 때문에 관계를 맺고있는 데이터가 자주 변경이 이루어지는 시스템에 적합합니다.

NoSQL은 그와 반대로 데이터의 update는 자주이루어지지 않는 데이터에 사용하는게 좋으며, scale out이 가능하다는 장점을 이용하여 빅데이터와 같은 분야에서 사용됩니다.

Q) 파티셔닝이란?

더보기

데이터베이스의 크기가 너무 커지게되면 용량의 한계와 성능의 저하를 초래할 수 있습니다. 이러한 문제점을 해결하기위해 데이터베이스를 파티션이라는 작은 단위로 나누는 것을 파티셔닝이라고합니다. 파티셔닝을 통해 물리적인 데이터 분할이 있더라도 application은 그 것을 알아차리지 못한다는 것이 특징입니다. 파티셔닝을 통해 성능과 가용성, 그리고 관리 용이성이 향상되지만 table간의 JOIN 연산이 많아지고 table과 index를 같이 파티셔닝 해야하기에 연산 오버헤드가 발생할 수 있습니다. 파티셔닝의 종류로는 세로로 데이터베이스를 나누는 vertical partitioning과 가로로 나누는 horizontal paritioning이 있습니다.

Q) 데이터베이스 샤딩이란?

더보기

데이터베이스 샤딩은 horizontal paritioning과 동일한 개념으로 테이블을 가로로 나누는 것을 의미합니다. 샤딩을 적용한다면 scale out 가능, 특정 query 성능 향상, 장애 전파 억제와 같은 장점이 있지만, 프로그래밍, 운영적인 복잡도는 더 높아지는 단점이 있습니다. 그렇기 때문에 서버 확장을 위해서는 scale up, read 부하 저하를 위해서는 cache 활용, table의 일부 칼럼만 자주 활용한다면 vertical partitioning 등 sharding을 피하거나 지연시켜야합니다. 또한 샤딩을할 때 고려해야할 것은 데이터가 한 쪽 샤드로 몰릴 경우(Hotspot), 샤딩이 무의미 해지기 때문에 균일하게 데이터베이스를 분산하는 것이 중요합니다.

Q) 분할 기법들에는 어떤것이 있는지?

더보기
  • 범위 분할: 분할 키 값이 범위 내에 존재하는지 확인하는 방법입니다.
  • 목록 분할: 값 목록에 파티션을 할당하고, 분할 키 값을 그 목록에 비추어 파티션을 선택하는 방법입니다.
  • 해시 분할: 해시 함수의 값에 따라 파티션에 포함할지 여부를 결정하는 방법입니다.
    • 예) 4개의 파티션으로 나뉘는 경우 해시 함수는 0-3의 정수를 돌려줍니다
  • 합성 분할: 위의 분할 방법들 중 하나를 선택합니다.

Q) Scale up과 Scale out의 차이점은?

더보기

두 방식 모두 서버의 한계에 도달했을 때 서버를 확장시키는 방식을 뜻합니다.

Scale up은 기존의 서버보다 더 높은 사양의 서버로 서버를 교체하는 방식이며 scale out은 비슷한 사양의 서버를 추가하여 인프라를 확장시키는 방식입니다. Scale up은 추가적 연결이 필요 없기 때문에 더 쉬운 방식이나 비용이 많이 발생하고 성능 확장에 한계가 있습니다. Scale out은 비용이 비교적 저렴하고 지속적 성능 확장이 가능하지만 관리가 어렵습니다.

Q) RDBMS에서 scale out이 어려운 이유는?

더보기

Scale out을 한다는 의미는 한 데이터베이스에 있는 데이터들을 특정한 기준으로 쪼갠다는 의미를 가집니다. RDBMS는 관계형 데이터베이스 관리 시스템으로 테이블들간의 관계가 중요한 역할을 하기에 데이터를 쪼개는 기준을 설정하기가 복잡해집니다. 그러나 NoSQL은 한 key에 대한 데이터를 모두 value에 담고있기 때문에 다른 데이터를 참조할 필요가 없어 그저 key 기준으로 나누면 됩니다.

Q) 클러스터링이란?

더보기

클러스터링이란 여러 개의 DB를 수평적인 구조로 구축하는 방식입니다. 클러스터링은 분산 환경을 구성하여 Single point of failure와 같은 문제를 해결할 수 있는 Fail Over 시스템을 구축하기 위해서 사용됩니다. 클러스터링은 동기 방식으로 노드들 간의 데이터를 동기화하며 그 종류로는 모든 서버를 active로 두는 active-active와 서버를 하나만 운용하고 나머지는 standby로 두는 active-standby가 있습니다. Active-active는 서버 하나가 다운될 시 서비스 중단이 없으나 비용이 많이 들고 active-standby는 비용은 적으나 active 서버가 다운될 시 standby 서버를 전환하는 시간이 듭니다.

Q) 리플리케이션이란?

더보기

리플리케이션이란 여러개의 DB를 수직적인 구조로 구축하는 방식입니다. 리플리케이션에서 master node에는 쓰기만, slave node에는 읽기만을 처리합니다. 통계적으로 DB 요청의 60%~80%는 읽기 요청이기 때문에 읽기 요청만을 처리하는 slave node를 둠으로써 부하를 분산시킬 수 있습니다. 그러나 slave node는 비동기 방식으로 master node와 동기화하기 때문에 일관성에 문제가 생길 수 있습니다.


Q) 데이터베이스 트랜잭션이란?

더보기

트랜잭션은 작업의 완전성을 보장해주는 작업 방식입니다. 작업들을 모두 처리하여 commit하거나 처리하지 못할 경우 이전 상태로 rollback하여 작업의 일부만이 적용되지 않도록 합니다.

Q) 데이터베이스 트랜잭션의 성질 ACID에 대해 설명해보시오

더보기
  • 원자성 (atomicity): 작업이 모두 반영되던지 전혀 반영되지 않던지 둘 중 하나의 경우여야합니다.
  • 일관성 (consistency): 실행이 완료된 후에는 일관성 있는 DB상태가 되어야합니다.
  • 독립성 (isolation): 트랜잭션들은 서로 수행 중인 연산에 끼어들거나 값을 참조할 수 없습니다.
  • 영속성 (durability): 완료된 결과는 영구적으로 반영되어야합니다.

Q) DB Lock이란? 그 종류는?

더보기

DB Lock이란 여러개의 트랜잭션이 하나의 데이터에 동시에 접근을 시도할 때 이를 제어해주는 도구입니다. 그 종류로는 읽기만을 허용하는 공유락, 읽기와 쓰기를 모두 허용하는 베타락이 있습니다.

Q) OLTP와 OLAP란?

더보기

OLTP란 OnLine Transaction Processing으로, 동시에 발생하는 다수의 트랜잭션을 서버가 처리하는 것을 의미합니다. OLTP는 현재의 데이터 처리가 얼마나 정확하고, 무결한지가 중요합니다. 그렇기 때문에 주로 데이터의 저장, 삭제, 수정 등의 실질적인 데이터를 수정하는 작업을 의미하는 용어입니다.

OLAP란 OnLine Analytical Processing으로, OLTP가 데이터 자체의 처리에 중점이 된 용어라면, OLAP는 이미 저장된 데이터를 기반하여 분석하는데 중점이 된 용어입니다. OLAP는 이미 저장된 데이터를 바탕으로 어떤 정보를 제공하는지가 중요합니다. 따라서 OLAP는 데이터가 무결하고, 정확하다는 전재를 바탕으로 고객 또는 사용자가 원하는 정보를 어떤식으로 표현하고 제공하는지를 의미하는 용어입니다. 


Q) 인덱스란? 그 종류는?

더보기

인덱스란 검색속도를 향상을 위해 생성할 수 있는 자료구조입니다. 테이블 전체를 탐색하는 FTS가 아닌 인덱스에서 해당 값의 위치를 찾아서 접근한다는 점에서 책의 색인과 비슷한 기능을한다고 볼 수 있습니다. 종류로는 Hash Table과 B+ Tree가 있습니다. Hash table은 탐색 시간 속도가 O(1)으로 매우 빠르나 순차적 탐색이 불가능하다는 단점이 있고 B+ Tree는 hash table보다 탐색 속도는 느리지만 B tree의 리프노드들을 LinkedList로 연결시켜 순차적 탐색을 할 수 있습니다. 

 

*B tree: 이진 트리를 확장해 자식 노드의 최대 숫자가 2보다 큰 트리 구조로 자식 노드의 최대 숫자 K를 지정하여 관리

Q) 인덱스를 사용할 시 단점

더보기

인덱스를 저장할 공간이 따로 필요하기 때문에 인덱스를 사용한다는 것은 검색 성능 향상을 위해 저장 성능을 어느정도 포기하는 것을 의미합니다. 또한 데이터 변경이 일어날 시 인덱스 또한 업데이트해야하기 때문에 변경이 빈번하다면 성능 처하를 초래할 수 있습니다.

Q) 인덱스는 언제 사용해야하는가?

더보기

데이터 양이 많고 데이터 변경보다 검색이 더 자주 발생할 때 사용해야합니다.


Q) DB 정규화란?

더보기

정규화 는 데이터 무결성을 유지하기 위해 잘 정의 된 방식으로 테이블을 분할하여 데이터베이스에서 중복 데이터를 제거하는 프로세스입니다.

Q) DB 정규형의 종류는?

더보기
  • 제1정규형: 테이블의 칼럼이 원자값을 갖도록 분해하는 것입니다.
  • 제2정규형: 제1정규형을 만족하고, 기본키가 아닌 속성이 기본키에 완전 함수 종속이도록 분해하는 것입니다.
    • 완전 함수 종속이란 기본키의 부분집합이 다른 값을 결정하지 않는 것을 의미합니다.
  • 제3정규형: 제2정규형을 만족하고, 기본키가 아닌 속성이 기본키에 이행적 종속을 갖지 않도록 분해하는 것입니다.
    • 이행적 종속이란 B가 A에 종속적이고 C가 B에 종속적일 때 C가 A에 종속적이 되는 것을 의미합니다.
  • BCNF (Boyce Codd Normal Form): 제3정규형을 만족하고, 모든 결정자가 후보키가 되도록 하는 것을 의미합니다.

Q) Key의 종류와 각 특징은?

더보기
  • 슈퍼키: 유일성을 만족하는 키입니다. 즉, 이 슈퍼키를 이용하면 중복 값 없이 각 데이터가 구별이 될 수 있게 되는 키입니다.
  • 복합키: 두개 이상의 속성을 사용한 키입니다.
  • 후보키: 유일성과 최소성을 만족하는 키입니다. 즉, 슈퍼키들 중 최소한의 갯수의 속성을 가진 키들의 집합이며 이들은 모두 기본키가 될 수 있는 후보입니다.
  • 기본키: 후보키들 중 선택된 하나의 키로 오직 테이블에서 오직 하나만 지정할 수 있으며 중복값, NULL값들을 허용하지 않습니다.
  • 대체키: 후보키들 중 기본키로 선택되지 못한 키들입니다.
  • 외래키: 두 테이블을 서로 연결해주는 key로 NULL이거나 부모 테이블의 기본키값이여야합니다.

Q) 정규화를 하는 이유는?

더보기

데이터 변경 시 발생하는 이상 현상을 줄일 수 있고 데이터베이스 구조 확장시에 재디자인을 최소화합니다. 또한 중복 값을 제거하기 때문에 저장 공간을 절약할 수 있습니다.

Q) 이상 현상의 종류는?

더보기
  • 삽입 이상: 데이터를 삽입할 때 특정 속성에 값이 없어 NULL을 입력하게되는 경우입니다.
  • 갱신 이상: 중복된 데이터 중 일부만 변경하여 데이터 모순이 일어나는 경우입니다.
  • 삭제 이상: 어떤 정보를 삭제할 때 의도하지 않은 다른 정보까지 삭제하게되는 경우입니다.

Q) 역정규화를 하는 이유는?

더보기

정규화로 인한 릴레이션 분해로 인하여 릴레이션 간의 join연산이 많아지며 이로인해 응답시간이 느려질 수 있습니다.


Q) DB 튜닝이란?

더보기

DB 튜닝이란 DB 구조, DB 자체, 운영체제등을 조정하여 DB 시스템의 전체적인 성능을 개선하는 작업을 의미합니다.

Q) DB 튜닝의 종류는?

더보기
  • 1단계 DB 설계 튜닝: DB 설계 단계에서 성능을 고려하여 설계하는 것입니다. 데이터 모델링, 인덱스 설계, 테이블 스페이스 설계 등이 포함됩니다.
  • 2단계 DBMS 튜닝: 성능을 고려햐여 메모리 혹은 블록 크기를 지정하는 것입니다. CPU, 메모리, I/O 관점에서의 튜닝으로 예시로는 Buffer, Cache 크기 등을 지정하는 것이 있습니다.
  • 3단계 SQL 튜닝: SQL 작성시 성능을 고려하는 것이며 hash, join등을 사용합니다.

Q) SQL 문장 종류는?

더보기
  • DML (Data Manipulation Langague, 데이터 조작어): SELECT, INSERT, DELETE > 데이터 자체의 변형
  • DDL (Data Definition Language, 데이터 정의어): CREATE, ALTER, DROP, RENAME > 데이터 구조의 정의
  • DCL (Data Control Language, 데이터 제어어): GRANT, REVOKE > 데이터베이스 접근에 관한 권한
  • TCL (Transaction Control Language, 트랜젝션 제어어): COMMIT, ROLLBACK, ACK > 논리적인 작업의 단위를 묶어서 DML에 의해 조작된 결과를 트랜잭션별로 제어 

Q) Select 쿼리의 수행 순서는?

더보기

FROM, ON, JOIN > WHERE, GROUP BY, HAVING > SELECT > DISTINCT >  ORDER BY > LIMIT

 

우선 FROM, ON, JOIN을 사용하여 사용할 릴레이션들을 파악합니다.

그 후 WHERE, GROUP BY, HAVING등을 사용하여 각 열에 대한 쿼리를 진행합니다.

이 모든 것이 수행 된 후 SELECT가 수행되며, SELECT 수행 이후에 DISTINCT, ORDER BY, LIMIT 순으로 선택 된 데이터 중 중복 값, 정렬, 제외할 값들에 대한 처리를 진행합니다.

'CS > 면접준비' 카테고리의 다른 글

네트워크  (0) 2024.08.17
운영체제  (0) 2024.08.17
JAVA  (0) 2024.08.17

질문

더보기
  1. 프로세스와 쓰레드의 차이점은?
  2. 메모리 영역 중 힙영역과 스택영역의 차의점은?
  3. 쓰레드에서 stack을 분리한 이유는?
  4. 멀티 프로세싱과 멀티 쓰레딩의 장단점 및 차이점은?
  5. 멀티 쓰레드 환경에서의 주의점
  6. CPU 스케쥴링이 발생하는 시점은?
  7. 선점형 스케쥴링과 비선점형 스케쥴링이란?
  8. 동시성이란?
  9. 병렬성이란?
  10. 데드락이란?
  11. 데드락의 4가지 조건은?
  12. 데드락의 해결방법은?
  13. 임계 영역이란?
  14. 운영체제에서의 기아란?
  15. 세마포어와 뮤텍스의 차이점은?
  16. 페이징과 세그먼트의 차이점은?
  17. 내부 단편화와 외부 단편화란?
  18. 페이지 교체 알고리즘이란?
  19. 컨텍스트 스위칭이란?
  20. 동기와 비동기의 차이점은?

 


 

답변

Q) 프로세스와 쓰레드의 차이점은?

더보기

프로세스는 자원을 할당받아 메모리 위에서 실행되고 있는 작업의 단위이고, 쓰레드는 프로세스가 할당한 자원에서 동작하고 있는 실행 단위입니다.

프로세스의 메모리 영역의 code, data, heap, stack 중 쓰레드는 stack만을 각자 할당받고 나머지는 공유합니다. 

따라서 쓰레드는 즉시 다른 쓰레드들의 결과를 확인할 수 있는데 반해, 프로세스는 다른 프로세스와 독립적인 구조로, 서로 통신하기 위해서는 IPC (프로세스 간 통신, Inter-Process Communication) 사용해야합니다.


 

Q) 메모리 영역 중 힙영역과 스택영역의 차의점은?

더보기

메모리 영역에는 code, data, heap, stack이 있습니다. 코드는 실행할 코드가 저장되는 텍스트 영역, 데이터는 전역변수와 정적변수가 저장되는 영역, 스택은 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역, 힙 영역은 사용자가 직접 관리할 수 있는 동적 메모리 영역입니다.

이 중 힙 영역은 런타임에 크기가 결정되고 스택영역은 컴파일타임에 크기가 결정됩니다.


 

Q) 쓰레드에서 stack을 분리한 이유는?

더보기
Stack은 함수의 호출 정보가 저장되는데, stack의 LIFO 구조로 인해 이를 공유하게되면 실행 순서가 꼬일 수 있기 때문입니다.

 

Q) 멀티 프로세싱과 멀티 쓰레딩의 장단점 및 차이점은?

더보기

멀티 프로세싱은 하나의 프로그램을 여러개의 프로세스로 구성하는 것을 의미합니다. 하나의 프로세스가 죽더라도 다른 프로세서에게는 영향을 끼치지 않는다는 장점이 있으며 컨텍스트 스위칭을 위한 오버헤드가 발생한다는 단점이 있습니다.

멀티 쓰레딩은 하나의 프로그램을 여러개의 쓰레드로 구성하는 것을 의미합니다. 컨텍스트 스위칭을 위한 오버헤드가 작다는 장점이 있고, 하나의 쓰레드에 문제가 생기면 다른 쓰레드에도 문제가 생긴다는 점과 자원 공유, 즉 동기화에 문제가 생길 수 있다는 점이 단점입니다.


 

Q) 멀티 쓰레드 환경에서의 주의점

더보기
다수의 쓰레드가 하나의 공유 자원에 접근할 때 상호 배제를 제거해 데드락을 예방하고 동기화 기법을 이용해 동시성 문제가 생기지 않도록 주의해야합니다.

 

Q) CPU 스케쥴링이 발생하는 시점은?

더보기
  • 실행상태에서 대기상태로 전환될 때 (예, 입출력 요청) - Non preemptive(비선점)
  • 실행상태에서 준비상태로 전환될 때 (예, 인터럽트 발생) - preemptive(선점)
  • 대기상태에서 준비상태로 전환될 때(예, 입출력이 종료될 때)
  • 종료될 때(Terminated)

 

Q) 선점형 스케쥴링과 비선점형 스케쥴링이란?

더보기
선점형 스케쥴링은 하나의 프로세스가 실행중인 다른 프로세스에게서 CPU를 뺏어올 수 있음을 의미하고 비선점형은 하나의 프로세스가 끝나지 않으면 CPU를 사용할 수 없음을 의미합니다.

 

Q) 동시성이란?

더보기
싱글 코어에서 멀티 스레드를 동작 시키기 위한 방법으로 멀티 태스킹을 위해 스레드들이 코어를 번갈아가며 사용하는 것을 의미합니다.

 

Q) 병렬성이란?

더보기
멀티 작업을 위해 멀티 코어에서 한 개 이상의 쓰레드를 포함하는 각 코어들을 동시에 실행하는 것을 의미합니다. 

Q) 데드락이란?

더보기
데드락, 또는 교착 상태란, 둘 이상의 프로세스들이 자원을 점유한 상태에서 서로 다른 프로세스가 점유하고 있는 자원을 요구하며 무한정 기다리는 상황을 말합니다. 예를 들면 A프로세스가 1번 자원을, B프로세스가 2번 자원을 점유하고 있는 상황에서 A는 2번 자원이, B는 1번 자원이 필요할 때 생길 수 있습니다.

 

Q) 데드락의 4가지 조건은?

더보기
  • 비선점 (Nonpreemptive) : 다른 프로세스의 자원을 뺏을 수 없음.
  • 순환 대기 (Circular wait) : 두 개 이상의 프로세스가 자원 접근을 기다릴 때, 관계가 순환적 구조.
  • 점유 대기 (Hold & Wait) : 공유 자원에 대한 접근 권한을 가진 채로 다른 자원에 대한 접근 권한을 요구.
  • 상호 배제(Mutual Exclusion) : 한 번에 한 프로세스만 공유 자원에 접근 가능하며, 접근 권한이 제한적일 경우.

 

Q) 데드락의 해결방법은?

더보기
데드락을 해결하기 위해서는 데드락의 4가지 조건 중 하나라도 없애면 됩니다. 공유 자원 중 많은 경우가 한 프로세스만 사용할 수 있는 경우가 많기 때문에 상호 배제는 없애기 힘들기에 많은 경우 순환 대기를 막는데 초점이 맞추어져있습니다. 해결 방법은 예방, 회피, 탐지와 복구 등이 있습니다.

 

Q) 임계 영역이란?

더보기
임계 영역이란 프로세스간의 공유 자원을 접근함에 있어 문제가 생기지 않도록 한번에 한 프로세스만이 접근하도록 해야하는 영역을 의미합니다. 임계 영역을 만들기 위해서는 세가지 조건이 필요합니다. 하나의 프로세스만이 들어갈 수 있어야 한다는 상호 배제, 임계 영역에 들어간 프로세스가 없는 상태에서 여러 프로세스가 동시에 임계 영역에 진입하려 할 때 어느 것이 들어갈지 결정해준다는 진행, 그리고 기아를 방지하기위한 한정 대기입니다.

 

Q) 운영체제에서의 기아란?

더보기
운영체제에서 기아란 우선 순위가 낮은 프로세스가 계속해서 자원을 할당 받지 못하는 것을 의미합니다.

 

Q) 세마포어와 뮤텍스의 차이점은?

더보기
뮤텍스는 lock을 사용해 공유 자원에 하나의 프로세스 또는 스레드만이 접근할 수 있도록 하는 것입니다. 그에 반해 세마포어는 세마포어의 카운트 갯수만큼의 프로세스 또는 스레드가 공유 자원에 접근할 수 있도록 하는 것입니다. 따라서 세마포어의 카운트를 1로 설정하면 뮤텍스로 사용이 가능합니다.

 


Q) 페이징과 세그먼트의 차이점은?

더보기

페이징은 프로세스를 물리적 고정 크기로 나누어 메모리에 불연속적으로 적재하는 방식을 뜻합니다. 페이징을 사용하면 외부 단편화 문제를 해결할 수 있으나 내부 단편화가 존재할 수 있습니다.

세그먼트는 프로세스를 논리적 내용으로 프로세스를 나누어 메모리를 할당하는 방식을 뜻합니다. 각 세그먼트는 크기가 다르며 내부 단편화가 존재하지 않으나 외부 단편화가 생길 수 있습니다.


 

Q) 내부 단편화와 외부 단편화란?

더보기
내부 단편화란 할당된 메모리 공간보다 프로세스가 작아서 사용하지 않는 메모리가 생기는 것을 의미합니다. 외부 단편화란 전체적으로 남아있는 메모리 공간은 프로세스를 올릴 수 있을 정도이지만 그 공간이 연속적이지 않아서 프로세스를 올릴 수 없는 상황을 의미합니다.

 

Q) 페이지 교체 알고리즘이란?

더보기
페이징 기법으로 관리되는 운영체제에서 주기억 장치에 필요한 페이지가 적재되어있지 않았을 때 어떤 페이지 프레임을 선택해 교체할지 선택하기 위해 사용하는 알고리즘입니다. FIFO, optimal 페이지 교체, LRU (Least Recently Used), LFU (Least Frequently Used), MFU (Most Frequently Used) 등이 있습니다. Optimal 페이지 교체는 실제로 활용할 수 있는 방법은 아니기에 연구 목적으로만 사용되며 LFU와 MFU는 구현 비용이 높기 때문에 실제로 쓰이지 않습니다.

 

Q) 컨텍스트 스위칭이란?

더보기
컨텍스트 스위칭이란 어떤 프로세스를 실행하고 있는 중에 발생한 인터럽트로 인해 현재 실행 중인 프로세스를 중지하고 다음 우선 순위 프로세스를 실행하기 위한 과정입니다. 현재 실행중인 프로세스의 상태, 즉 PCB를 저장하고 다음 프로세스를 동작시켜 작업을 처리한 후에 이전에 저장했던 컨텍스트를 복구시킵니다.

 

Q) 동기와 비동기의 차이점은?

더보기

동기는 요청과 결과가 동시에 일어난다는 의미로, 메소드를 실행시킴과 동시에 값이 반환되기 전까지는 blocking되어 있다는 것을 의미합니다. 비동기의 경우, blocking 되지 않고 이벤트 큐에 넣거나 백그라운드 스레드에게 해당 task를 위임하고 바로 다음 코드를 실행합니다.

동기 방식은 설계가 간편하고 직관적이라는 장점이 있으나 결과가 주어질때가지 대기해야한다는 단점이 있습니다. 비동기 방식은 동기보다 복잡하지만 결과가 주어질 때까지 다른 작업을 수행할 수 있기 때문에 자원을 효율적으로 사용할 수 있습니다.


 

'CS > 면접준비' 카테고리의 다른 글

네트워크  (0) 2024.08.17
데이터베이스  (0) 2024.08.17
JAVA  (0) 2024.08.17

질문모음

더보기
  1. 객체지향(OOP)이란?
  2. 객체지향 설계 원칙인 SOLID란?
  3. 관점지향(AOP)이란?
  4. 추상화란?
  5. 추상 클래스와 인터페이스의 특징과 차이를 설명하시오
  6. 캡슐화란?
  7. Spring Boot의 어노테이션 중 @Getter와 @Setter의 무분별한 사용을 지양해야하는 이유는 무엇인가?
  8. 상속이란?
  9. IS-A 관계와 HAS-A 관계의 차이점이란 무엇인가?
  10. 다형성이란?
  11. 자바의 컴파일 과정을 설명하시오
  12. JVM (Java Virtual Machine) 의 역할은 무엇인가?
  13. JVM의 내부 구조는?
  14. 자바의 메모리 영역의 종류와 그 특성은?
  15. 가비지 컬렉션을 위해 만들어진 heap 영역의 구조와 가비지 컬렉션의 동작방식은?
  16. Java 7의 특징은?
  17. Java 8의 특징은?
  18. Java 11의 특징은?
  19. 제네릭이란?
  20. String, StringBuilder, StringBuffer의 차이점은?
  21. String을 선언할 때 따옴표를 사용하는 것과 new를 사용하는 것의 차이점은?

 

답변

1) 객체지향(OOP)이란?

더보기

프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.


2) 객체지향 설계 원칙인 SOLID란?

더보기
  • SRP (Single Responsibility Principle): 단일 책임 원칙, 하나의 클래스는 하나의 책임만을 가져야합니다
  • OCP (Open/Closed Principle): 개방 폐쇄 원칙, 확장에는 열려있고 수정에는 닫혀있어야합니다
  • LSP (Liskov Substitution Principle): 리스코브 치환 원칙, 상위 타입은 하위 타입으로 치환이 가능해야합니다
  • ISP (Interface Segregation Priciple): 인터페이스 분리 원칙, 하나의 범용 인터페이스보다 다수의 특정 인터페이스가 낫습니다
  • DIP (Dependency Inversion Principle): 의존 역전 원칙, 추상화에 의존해야지 구체화에 의존해선 안됩니다. 즉, 인터페이스, 추상 클래스와 같이 자주 변하지 않는 클래스와 관계를 맺어야합니다.

3) 관점지향(AOP)이란?

더보기

OOP를 더 발전시킨 개념으로 OOP에서 비즈니스 로직을 모듈화했다면 거기서 관점을 다르게해 인프라/부가 기능 측면에서 공통된 요소를 추출하는 것입니다. 예를들면 OOP가 프로그램을 계좌이체/입출금/이자계산으로 모듈화 했다면 AOP는 그 중에서 공통적으로 발생하는 부가 기능인 인증, 권한 체크, 트랜잭션 등을 분리시켜 필요한 시점에 자동으로 삽입되게 하는 것입니다.

이를 통해 코드 재활용성을 높이고 유지보수를 더 쉽게할 수 있습니다.

 


 

4) 추상화란?

더보기

추상화란 서로 다른 객체들의 특성 중 공통적인 속성, 동작들을 추출하여 하나의 묶음으로 정의하는 것을 의미합니다. 추상화를 이용한 설계는 코드의 재사용성을 높이고 그로 인해 간결해진 코드로 생산성, 가독성, 유지 보수 시간에 긍정적인 영향을 미칩니다

5) 추상 클래스와 인터페이스의 특징과 차이를 설명하시오

더보기

추상클래스는 일반 클래스와 별 다를 것이 없습니다. 단지, 추상 메서드를 선언하여 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스입니다. 그래서 미완성 설계도라고도 표현합니다. 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없습니다.

추상클래스가 미완성 설계도라면 인터페이스는 기본 설계도라고 할 수 있습니다. 인터페이스도 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 작성하고 인터페이스는 추상메서드만을 가지고있습니다. 클래스와 다르게 다중상속이 가능합니다.

추상 클래스와 인터페이스를 나눠서 사용하는 이유는 사용 의도와 공통 기능 재사용이라는 두가지가 있습니다. 추상 클래스는 '상속', 즉 is-a 의 관계가 되기 때문에 클래스의 구분을 추상 클래스로 해결하고, 다중 상속이 가능한 인터페이스는 has-a 관계로 생각해 클래스가 가지고있는 기능들에 대한 부분을 해결하는 용도로 쓰입니다. 또한 만약 모든 클래스가 인터페이스를 사용해서 기본 틀을 구성한다면 공통으로 필요한 기능들도 모든 클래스에서 오버라이딩 하여 재정의 해야하는 번거로움이 있습니다.

6) 캡슐화란?

더보기

캡슐화란 객체 내부의 구조 및 데이터를 하나의 캡슐로 감싸 외부로부터 은닉하여 보호하는 것을 의미합니다. 캡슐화를 통해 높은 응집도 낮은 결합도를 유지할 수 있게됩니다.

  • 높은 응집도란 모듈 내의 요소들이 서로 밀접한 관련이 있어 하나의 목표를 위해 긴밀하게 협력하도록 설계되는 것입니다.
  • 낮은 결합도란 낮은 의존성을 나타내며, 즉 다른 모듈에 대한 지식을 얼만큼 가지고있는지를 나타내는 척도입니다.

7) Spring Boot의 어노테이션 중 @Getter와 @Setter의 무분별한 사용을 지양해야하는 이유는 무엇인가?

더보기

Getter와 Setter의 사용은 캡슐화를 위반하는 행위이기 때문입니다. 캡슐화는 객체의 상태는 숨기고 행동만을 외부에 공개해야합니다. 그렇기에 객체의 상태를 변경하거나 조회할 수 있는 Getter와 Setter은 캡슐화를 위반하는 것이 됩니다.

8) 상속이란?

더보기

상속이란 부모 클래스를 상속하여 기능을 추가하거나 재정의한 자식 클래스를 만드는 것을 의미합니다. 상속을 통해 코드의 중복을 없앨 수 있고 클래스 사이에 계층적인 관계를 구성해 다형성의 문법적 토대를 만듭니다

 

9) IS-A 관계와 HAS-A 관계의 차이점이란 무엇인가?

더보기

IS-A 관계는 'A는 B이다'와 같은 상속 관계를 나타냅니다. 이 정의에서 A는 상속을 받는 자식 클래스, B는 부모 클래스에 해당하며 예를들면 '사자는 동물이다'와 같이 사자가 완전히 동물에 종속되는 관계를 나타냅니다.

HAS-A 관계는 'A는 B를 가지고있다'와 같은 포함 관계를 나타냅니다. 이는 상속이 아닌 클래스가 다른 클래스를 소유하는 관계로, '컴퓨터는 CPU를 가지고있다'와 같이 컴퓨터 객체가 CPU 객체를 구성하 것과 같은 관계를 나타냅니다.

10) 다형성이란?

더보기

다형성이란 하나의 클래스나 함수가 다양한 방식으로 동작이 가능한 것을 의미합니다.

상속과 overriding을 통해 같은 타입의 객체더라도 다른 생성자로 생성된 객체는 동일한 이름의 함수를 다르게 동작시킬 수 있습니다.

또한 overloading을 통해 한 클래스 내에서 동일한 이름의 함수를 서로 다른 매개변수 타입과 개수를 가지게 해 동일한 이름이더라도 다양한 방식으로 동작할 수 있습니다.

 


11) 자바의 컴파일 과정을 설명하시오

더보기

개발자가 .java 소스파일을 작성합니다.

자바 컴파일러가 소스 파일을 컴파일해 JVM이 이해할 수 있는 .class 자바 바이트코드 파일을 생성합니다.

JVM내의 클래스 로더를 통해 바이트코드 파일을 JVM 메모리 내로 로드합니다.

JVM은 각 OS가 실행할 수 있는 기계어로 변환시킵니다

12) JVM (Java Virtual Machine) 의 역할은 무엇인가?

더보기

스택 기반으로 동작하는 가상 머신인 JVM은 자바 바이트 코드 파일을 OS에 맞게 해석해주는 역할과 가비지 컬렉션을 통해 메모리 관리를 해주는 역할을 가지고있습니다.

13) JVM의 내부 구조는?

더보기

JVM의 구조는 크게 garbage collector, execution engine, class loader, runtime data area가 있고 각자의 역할에 따라 동작합니다

  • Garbage collector는 heap 메모리 영역에서 동적으로 할당했던 메모리 중 유효하지 않은 메모리인 garbage를 주기적으로 정리해 주는 역할을 합니다.
  • Execution engine는 클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명렁어 단위로 읽어서 실행합니다. 
  • Class loader은 JVM 내로 .class 파일을 로드하고, JVM이 운영체제로부터 할당 받은 Runtime Data Area에 적재합니다. 런타임 시에 동적으로 클래스를 로드합니다.
  • Runtime data area는 자바 어플리케이션을 실행할 때 사용되는 데이터들을 적재하는 데이터 영역으로, method, stack, heap, PC register, native method stack과 같은 다섯가지 영역으로 나누어져있습니다.

14) 자바의 메모리 영역의 종류와 그 특성은?

더보기

자바의 메모리 공간은 method, stack, heap, PC register, native method stack 영역으로 구분되고 데이터의 타입에 따라 적절한 영역에 할당됩니다.

  • Method 영역에는 전역 변수, static으로 선언되는 것들을 저장하며, 클래스 정보, static 변수, 변수 정보, 메소드 정보, 런타임 상수풀등을 저장합니다. 프로그램의 시작부터 종료까지 메모리에 남아있으며 모든 쓰레드가 공유합니다. 그렇기 때문에 이 영역에 저장되어있는 데이터들을 어디서든 사용할 수 있게 됩니다. JVM이 동작해서 클래스가 로딩될 때 할당됩니다.
    • 런타임 상수풀: JVM은 런타임 상수풀에서 해당 메소드나 필드의 실제 메모리 상 주소를 찾아 참조합니다
  • Heap 영역에는 Object 타입의 데이터 배열을 저장합니다. 가비지 컬렉터가 주기적으로 관리하는 영역이기도합니다. Compile time시 할당되며 이 또한 모든 쓰레드가 공유합니다.
  • Stack 영역은 메서드 호출 시마다 스택 프레임(그 메서드만을 위한 공간)의 형태로 생성됩니다. 그리고 메서드 안에서 사용되는 값들을 저장하고, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장합니다. 만약, 지역변수이지만 Reference Type일 경우에는 Heap 에 저장된 데이터의 주소값을 Stack 에 저장해서 사용하게 됩니다. 마지막으로, 메서드 수행이 끝나면 프레임별로 삭제하게되고 쓰레드 당 하나씩 존재합니다.
  • PC register 영역은 쓰레드가 생성될 때마다 생성되는 영역으로 프로그램 카운터, 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역입니다.
  • Natvie method stack 영역은 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역입니다. JNI(Java Native Interface)를 통해 호출되는 다른 언어의 코드를 수행하기 위해 존재합니다.

15) 가비지 컬렉션을 위해 만들어진 heap 영역의 구조와 가비지 컬렉션의 동작방식은?

더보기

Heap 영역은 young generation, tenured generation으로 나누어져있으며 해당 영역은 application에서 사용됩니다. Java 7까지는 이에 추가로 JVM이 사용하는 permanent generation영역이 존재했으나 Java 8부터는 OS가 관리하는 native 영역의 메모리의 Metaspace로 바뀌었습니다.

Young generation은 또다시 eden영역과 survivor 영역으로 나누어져있습니다. Heap영역에 객체가 새로 생성되면 eden에 저장이 되고 eden이 어느정도 차면 참조 정도에 따라 survivor 영역의 빈 공간으로 이동됩니다.

Tenured generation에는 old영역이 있으며 young generation 영역이 차게되면 참조 정도에 따라 이 영역으로 옮겨집니다. 이 과정은 minor garbage collection이라고 불립니다. Old 영역의 허용치가 넘어가면 old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 major GC가 진행됩니다. Major GC가 진행되는 중에는 GC를 진행하는 쓰레드를 제외한 모든 쓰레드가 멈추는 'stop-the-world'가 발생합니다.


16) Java 7의 특징은?

더보기
  • Try-with-resources 지원: try문 안에서 사용되는 Connection, Files, Input/OutStream 등과 같은 자원들을 자동적으로 해제를 할 수 있게 되었습니다.
    • try (final InputStream inputStream = connection.getInputStream();
                   final OutputStream outputStream = connection.getOutputStream()){ /*code*/ }
  • 다이아몬드 연산자를 활용한 Type Reference(타입 추론)지원: 생성자 호출시에 필요한 파라미터(매개변수)를 다이아몬드 연산자(<>)을 사용함으로 생략할 수 있습니다.
    • Map<String, List<String>> myMap = new HashMap<>();
  • 다중 Exception Catching: 하나의 catch 블록에서 여러개의 예외처리가 가능합니다.
    • try{ /*code*/ } catch (FirstException | SecondException ex) {
           log.info(ex);
           throw ex;
      }
  • 숫자 리터럴에서 언더스코어(underscore) 지원: 숫자 리터럴의 숫자 사이에 언더스코어(_)를 사용할 수 있습니다. 이 구분자를 사용하면 의미 있는 숫자끼리 그룹화하는 것이 가능하며, 이로 인해 코드의 가독성이 높아집니다.
    • int oneMillion = 1_000_000;
  • Switch문에서 String 객체 사용가능

17) Java 8의 특징은?

더보기
  • Heap Permanent Generation 제거: 이전에는 permanent generation이라는 이름을 가지고 초기 설정시 설정해여야했던 메모리가 metaspace로 변경되었습니다. Metaspace는 런타임시 메모리 요구 사항에 따라 다이나믹하게 자체 크기 조절이 가능하며 OS레벨에서 관리되는 native 메모리 영역에 위치합니다. 
  • Interface에 Default, Static Methods를 추가할 수 있게됨: default method는 하위 클래스에서 재정의가 가능하지만 static method는 불가합니다.
  • 함수형 interfaces: 하나의 기능을 제공하는 단 하나의 추상 메소드를 정의하는 인터페이스가 추가되었습니다. 단, 추상 메소드 외에 디폴트 메소드나 정적 메소드는 원하는 만큼 사용할 수 있고, @FunctionalInterface와 함께 쓰이며, 만약 추상 메소드가 여러 개라면 컴파일 타임에서 에러를 잡아낼 수 있습니다. 주요 함수형 인터페이스로는 Consumer, Supplier, Function 등이 있습니다.
  • 람다 표현식: 람다 표현식은 함수를 식으로 나타내는 것으로 함수를 변수로 나타낼 수 있다는 장점이 있습니다.이러한 람다 표현식은 기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높이는 데 그 목적이 있습니다. Java 8 버전부터는 람다 표현식을 사용하여 자바에서도 함수형 프로그래밍을 할 수 있게 되었습니다. 
  • 메서드 참조: 람다식의 가독성을 높이기 위해 사용하는 방법입니다. 종류로는 정적 메서드참조, 인스턴스 메서드 참조, 특정 유형의 객체의 인스턴스 메서드 참조, 생성자 참조 등이 있으며 모두 더블콜론을 사용하여 사용됩니다.
  • Stream API: 스트림은 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해 주는 내부 반복자입니다. 스트림 API는 데이터를 추상화하여 다루므로, 다양한 방식으로 저장된 데이터를 읽고 쓰기 위한 공통된 방법을 제공합니다. 
    • 컬렉션은 데이터를 어떻게 저장/관리하고 접근하는지를 목표하고 있습니다.
      이와 반대로 스트림은 데이터를 직접 접근하거나 조작하는 기능을 제공하지 않으며, 데이터를 어떻게 계산할지에 대한 목표를 가지고있습니다.
      즉, 데이터의 저장/관리가 목적이라면 컬렉션을, 데이터의 계산이 목적이라면 스트림을 사용하는게 좋다고 볼 수 있습니다.
  • Date and time API 지원 
  • Optional 지원: null에 대한 참조를 안전하게할 수 있게됩니다.
  • 배열 정렬의 병렬처리: 이전의 Arrays.sort는 merge sort와 같은 순차적 실행이 되는 방식을 사용했으나 Arrays.parallelSort가 추가되며 병렬처리가 가능해졌습니다.
  • Base64 encoding and decoding 지원

18) Java 11의 특징은?

더보기
  • String, Files 클래스와 Collection 인터페이스에 새로운 메서드가 추가되었습니다.
  • 람다에서 로컬변수인 var을 이용할 수 있게되었습니다.
  • javac를 통해 컴파일하지 않고 바로 컴파일할 수 있게되었습니다
  • Default garbage collector이 parallelGC에서 G1GC로 변경되었으며 G1GC는 더 좋은 성능을 냅니다.

19) 많은 기업이 아직 Java 8을 사용하는 이유는?

더보기

Java 8보다 나중에 나온 LTS인 Java 11과 Java 17보다도 더 긴 지원기간을 가지고있습니다.


20) 제네릭이란?

더보기

데이터 타입을 일반화 하는 것으로, 데이터 타입에 대한 정의를 외부로 미루는 것입니다.

21) String, StringBuilder, StringBuffer의 차이점은?

더보기

String은 불변하는 특성을 가지고있기 때문에 수정이 불가합니다. 따라서 수정이 발생할때마다 새로운 인스턴스가 생성되고 이전 값들은 가비지 컬렉션 발생 시 삭제됩니다. StringBuffer은 가변하는 특성을 가지고있으며 동기화를 지원하기 때문에 멀티스레드 환경에서 안전합니다. StringBuilder 또한 가변하는 특성을 가지고있으나 동기화를 지원하지 않기에 멀티스레드 환경에서 사용하기에 적합하지 않으나 단일 스레드 환경이라면 StringBuffer보다 높은 성능을 보입니다.

22) String을 선언할 때 따옴표를 사용하는 것과 new를 사용하는 것의 차이점은?

더보기

String은 primitive type가 아니기 때문에 heap에 저장됩니다. 그러나 java는 String 객체를 다른 객체들과 달리 heap 메모리 영역 안의 String constant pool에서 관리합니다. 만약 따옴표로 선언이 되면 이 String 상수풀에서 해당 값을 가진 String이 있는지 확인하고 있다면 그 주소값을 리턴하고, 없다면 String 상수풀에 해당 객체를 생성, 할당한 뒤 그 주소값을 리턴합니다. 이를 통해서 같은 값을 가진 String 객체가 생성되는 것을 막을 수 있습니다.

만약 new를 사용한다면 다른 객체들처럼 강제로 heap 영역에 객체를 생성합니다. 그러나 이럼에도 다른 객체와 다르게 동작하는데, 만약 new를 사용했다 하더라도 String 상수풀에 그 값이 있는지 확인하고 없다면 String 상수풀에도 객체를 생성하여 총 두개의 객체를 생성합니다.

 

'CS > 면접준비' 카테고리의 다른 글

네트워크  (0) 2024.08.17
데이터베이스  (0) 2024.08.17
운영체제  (0) 2024.08.17

Oracle을 이용해 프로그래머스 레벨1 문제를 모두 풀며 잊지 않기 위한 내용을 정리합니다. 문제링크는 생략합니다.

 

 

1. 상위 N개 행 조회하기

ROWNUM을 이용하는 방법.

SELECT NAME
FROM (SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME)
WHERE ROWNUM <= 1;

 

2. NULL 처리

NVL : NULL값이 있으면 다른 NULL이 아닌 지정값으로 조회되도록 하는 함수

SELECT warehouse_id, warehouse_name, address, NVL(freezer_yn, 'N')
from food_warehouse
where address like '경기도%';

 

-- 코드를 입력하세요
SELECT PT_NAME, PT_NO, GEND_CD, AGE, NVL(TLNO, 'NONE')
FROM PATIENT
WHERE AGE <= 12 AND GEND_CD = 'W'
ORDER BY AGE DESC, PT_NAME;

 

3. 날짜처리

TO_CHAR : 날짜 데이터와 형식을 인자로 넘기면 형식에 맞추어 출력해주는 함수

SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE TO_CHAR(JOINED, 'YYYY') = '2021' AND AGE >=20 AND AGE <= 29;

 

-- 코드를 입력하세요
SELECT dr_name, dr_id, mcdp_cd, to_char(hire_ymd, 'yyyy-mm-dd')
from doctor
where mcdp_cd IN ('CS', 'GS')
order by hire_ymd desc, dr_name asc;

 

 

4. 기본 JOIN

아직 JOIN에 대해 깊이있게 이해를 못해서 추가적으로 공부가 필요합니다.

SELECT H.FLAVOR
FROM FIRST_HALF H
INNER JOIN ICECREAM_INFO I ON H.FLAVOR = I.FLAVOR
WHERE H.TOTAL_ORDER > 3000 AND I.INGREDIENT_TYPE = 'fruit_based';

 

SELECT B.TITLE,
       B.BOARD_ID,
       R.REPLY_ID,
       R.WRITER_ID,
       R.CONTENTS,
       TO_CHAR(R.CREATED_DATE, 'YYYY-MM-DD') AS CREATED_DATE
FROM USED_GOODS_BOARD B
INNER JOIN USED_GOODS_REPLY R ON B.BOARD_ID = R.BOARD_ID
WHERE TO_CHAR(B.CREATED_DATE, 'YYYYMM') = '202210'
ORDER BY R.CREATED_DATE, B.TITLE;

 

 

5. 평균, 반올림

AVG는 평균을 구해주며

ROUND는 반올림한 값을 줍니다. ROUND의 두번째 인자값에 따라 반올림 위치를 지정할 수 있습니다.

두번째 인자를 적지 않는다면 0으로 인식하며 소수점 첫째짜리에서 반올림한 값을 리턴합니다.

SELECT ROUND(AVG(DAILY_FEE)) AS AVERAGE_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE = 'SUV';

 

 

6. CASE-WHEN-THEN

주어진 테이블의 정보를 통해 새로운 컬럼을 만들고 싶을때 사용하는 것으로 이해했습니다.

조건이 여러개라면 WHEN-THEN-WHEN-THEN...형태로 이어붙이면 되는것 같습니다.

-- 코드를 입력하세요
SELECT HISTORY_ID, CAR_ID, TO_CHAR(START_DATE, 'YYYY-MM-DD') AS START_DATE, TO_CHAR(END_DATE, 'YYYY-MM-DD') AS END_DATE,
CASE WHEN(END_DATE - START_DATE + 1) >= 30 THEN '장기 대여' ELSE '단기 대여' END AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE TO_CHAR(START_DATE, 'YYYY-MM') = '2022-09'
ORDER BY HISTORY_ID DESC;

 

 

 

옵저버 패턴

정의

옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자 객체들이 관찰하는 객체에 변화가 있을 때마다 변경 정보를 받고 갱신되도록 하는 디자인 패턴입니다.

옵저버 패턴은 1:1혹은 1:N 의존성을 가지는데, 주로 분산 이벤트 처리 시스템에서 많이 사용됩니다.

발행/구독 모델로 알려져 있기도 합니다.

객체 사이의 의존성을 줄이고 유연하게 상호작용하도록

즉, Coupling을 느슨하게 유지하는 것을 도와주는 패턴입니다.

이해하기 가장 쉬운 예시는 유튜브 혹은 인스타그램을 생각하면 됩니다.

유튜브에서 내가 구독한 채널이 새로운 영상을 올리면 새 영상 업로드 알림을 받습니다.

나 뿐만아니라 같은 채널을 구독한 다른 모든 구독자들도 알림을 받을것입니다.

옵저버 패턴에서 유튜브 채널이 Subject가 되고, 구독자들이 Observer가 됩니다

 

관찰자(Observer)라고 해서 관찰자 객체들이 Subject를 스스로 관찰하는 것처럼 느껴지지만
직접 관찰한다는 느낌 보다는 Subject의 변화를 통한 정보 갱신을 하기 위해 변경사항을 전달받길 기다리는 수동적인 상태에 더 가깝습니다.

 

옵저버 패턴의 클래스 다이어그램을 그리면 아래와 같습니다.

Subject와 Observer는 인터페이스 이며 이것을 구현하는 클래스가 필요합니다.

Subject에서 observerCollection을 갖는데 타입으로 L등이 될 수 있습니다.

Subject를 구현한 클래스를 ConcreteSubjet라고 하겠습니다.

ConcreteSubjets는 Observer들을 List, Set, Map 등의 Collection에 모아 갖고 있습니다.

또한 Observer들을 내부에서 등록 및 삭제하는 구조이며 Subject의 상태가 변경되면 Observer들에게 알림을 발행합니다.

 

 

옵저버 패턴 흐름

1. 한개의 주체(Subject)와 여러개의 관찰자(Observer)로 구성되어습니다.

2. Observer 패턴에서는 Subject의 상태가 바뀌면 변경사항을 Obsever들에게 전달합니다.

3. Subject로부터 받은 정보로 Observer의 정보를 바꿀 수 있습니다.

4. Observer들은 Subject의 Collection에서 삭제/추가 될 수 있습니다.

유튜브 채널이 있고, 영상을 게시했을때 구독자에게 알림을 보내는 상황을 가정하여 코드를 작성해봤습니다.

 

Observer.java

public interface Observer {
    void update(String title);
}

관찰자/구독자 역할을 하게될 Observer 인터페이스입니다.

ObserverImpl.java

public class ObserverImpl implements Observer{
    String name;
    public ObserverImpl(String name){
        this.name = name;
    }
    @Override
    public void update(String title) {
        System.out.println(this.name + "님, [" + title + "] 영상이 게시되었습니다.");
    }
}

Observer를 구현한 클래스입니다.

 

Subject.java

public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObserver(String title);
}

 

SubjectImpl.java

import java.util.ArrayList;
import java.util.List;

public class SubjectImpl implements Subject{

    private final List<Observer> observerList;
    public SubjectImpl(){
        observerList = new ArrayList<>();
    }

    // Observer 추가
    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }

    // Observer 삭제
    @Override
    public void removeObserver(Observer o) {
        observerList.remove(o);
    }

    // Observer들에게 이벤트 알림
    @Override
    public void notifyObserver(String title) {
        for (Observer o : observerList)
            o.update(title);
    }
}

 

Subject를 구현한 클래스입니다.

Observer들을 List를 이용해 관리합니다.

옵저버를 등록하고 알림을 보내는 것을 간단하게 구현했습니다.

public class youtube {
    public static void main(String[] args) {
        // 유튜브 채널 생성
        Subject channel = new SubjectImpl();
        
        // 구독자 생성
        Observer subscriber1 = new ObserverImpl("철수");
        Observer subscriber2 = new ObserverImpl("영희");
        
        // 구독자 등록
        channel.registerObserver(subscriber1);
        channel.registerObserver(subscriber2);
        
        // 영상 업로드 알림
        channel.notifyObserver("웃긴 짤");
        channel.notifyObserver("무서운 짤");
        
        // 영희가 구독 취소
        channel.removeObserver(subscriber2);
        
        // 영상 업로드 알림
        channel.notifyObserver("슬픈 짤");
    }
}

 

 

실행 결과는 아래와 같습니다.

영희가 구독을 취소한 이후로는 영희에게 알림이 가지 않습니다.

 

 

 

장점

1. 옵저버 패턴을 사용하면 Subject의 상태 변경을 매번 일일히 확인하지 않고도 자동으로 감지가 가능합니다.

2. Subject의 코드를 변경하지 않아도 새 구독자 클래스를 도입이 가능해 OCP를 준수합니다.

3. 런타임 시점에서 Subject와 Observer가 구독 알림 관계를 맺을 수 있습니다.

4. Subject와 Observer의 관계를 느슨하게 유지할 수 있습니다.

단점

1. 알림의 순서를 제어할 수 없으며, 무작위 순서로 알림을 받게됩니다.

2. 무분별한 사용은 코드의 복잡도가 증가합니다.

3. 옵저버 객체 등록 이후 해지하지 않으면 메모리 누수가 발생할 수 있습니다.

 


MVC 패턴

정의

MVC 패턴은 사용자 인터페이스를 설계하는 데 사용되는 디자인 패턴으로, 애플리케이션을 세 가지 주요 구성 요소로 나눕니다.

1. Model: 애플리케이션의 데이터와 비즈니스 로직을 처리합니다.

2. View: 사용자 인터페이스 요소를 처리하고 모델의 데이터를 사용자에게 표시합니다.

3. Controller: 사용자 입력을 처리하고 모델과 뷰를 업데이트합니다.

옵저버 패턴은 MVC 패턴의 모델과 뷰 간의 관계를 구현하는 데 자주 사용됩니다.

모델이 옵저버 패턴의 Subject이고, 뷰가 Observer가 됩니다.

모델의 상태가 변경되면, 모델은 뷰에게 변경 사항을 알리고, 뷰는 이를 반영하여 화면을 업데이트 합니다.

이것을 통해 MVC 패턴에서 모델과 뷰 간의 느슨한 결합을 유지할 수 있습니다.


옵저버 패턴을 직접 구현하지 않아도 자바의 내장 Observer 객체가 있어 클래스를 상속하기만 하면 쉽게 이용할 수 있습니다. (java.util.Observer, java.util.Observable)

하지만 Observable는 인터페이스가 아닌 클래스입니다. Observable클래스를 상속해야 하는데, 자바에서는 단일 상속만 지원하기 때문에

Subject역할을 하는 클래스가 다른 클래스를 상속하고 있는 상태라면 내장 객체를 이용할 수 없습니다.

메서드 위임을 해주면 되지 않나 싶지만, Observable의 메서드가 protected로 선언되어 있기 때문에 결국 자식 클래스에서 호출할 수 밖에 없습니다.

따라서 내장 객체를 이용할 수 없는 상황이라면 직접 구현해줘야만 합니다.

 

 

 

 

출처 및 참고

https://shan0325.tistory.com/33

https://gsbang.tistory.com/entry/Design-Pattern-Observer-Pattern%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4

https://velog.io/@te-ing/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%98%B5%EC%A0%80%EB%B2%84Observer-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

https://xzio.tistory.com/289

https://refactoring.guru/design-patterns/observer

https://ssdragon.tistory.com/144

 

'CS > JAVA' 카테고리의 다른 글

JVM 이해하기 (2) - Class Loader  (2) 2025.01.29
JVM 이해하기 (1) - 도입  (3) 2025.01.28

+ Recent posts