애노테이션 : 자바 소스 코드에 주석 처럼 추가하여 특별한 기능을 사용하는 메타데이터
🗒️ 예시 : @RequestHeader
📖 참고 📖 reflection
- 구체적인 Class Type을 알지 못해도, 해당 Class의 method, type, variable에 접근할 수 있도록 해주는 JAVA API
- 컴파일된 바이트 코드를 통해 Runtime에 특정 Class의 정보를 추출하도록 동적 바인딩 제공
📖 참고 📖 Spring 제공 Annotation
- 📌 @ComponentScan
- @Component, @Service, @Repository, @Controller, @Configuration이 붙은 클래스 Bean들을 찾아서 Context에 bean을 등록해주는 애노테이션
- 전부 다 @Component를 사용하지 않고 @Repository 등으로 분리해서 사용하는 이유는, 예를 들어 @Repository는 DAO에서 발생할 수 있는 unchecked exception들을 스프링의 DataAccessException으로 처리할 수 있기 때문이다.
- 또한 가독성에서도 해당 애노테이션을 갖는 클래스가 무엇을 하는지 단 번에 알 수 있다.
- 📌 @EnableAutoConfiguration
- autoConfiguration도 Configuration중 하나에 해당한다.
- spring.factories 내부에 여러 Configuration들이 있고 조건에 따라 Bean이 등록되게 되는데 메인 클래스 @SpringBootApplication을 실행하면 @EnableAutoConfiguration에 의해 spring.factories 안에 있는 수많은 자동 설정들이 조건에 따라 적용되어 수 많은 Bean들이 생성된다.
- 간단하게 정리하면, Application Context를 만들 때 자동으로 빈설정이 되도록 하는 기능이다.
- 📌 @Component
- 개발자가 직접 작성한 class를 Bean으로 등록하기 위한 애노테이션
- 📌 @Bean
- 개발자가 직접 제어가 불가능한 외부 라이브러리등을 bean으로 만들려할 때 사용되는 애노테이션
- 📌 @Configuration
- @Configuration을 클래스에 적용하고 @Bean을 해당 class의 메서드에 적용하면 @autowired로 Bean을 부를 수 있다.
- 📌 @Autowired
- 스프링이 Type에 따라 알아서 Bean을 주입해준다.
- Type을 먼저 확인한 후 못 찾으면 Name에 따라 주입한다.
- 강제로 주입하고자 하는 경우 @Qulifier을 같이 명시
- 📌 @Qualifier
- 같은 타입의 빈이 두 개 이상 존재하는 경우 스프링이 어떤 빈을 주입해야할 지 알 수 없어서 스프링 컨테이너를 초기화하는 과정에서 예외가 발생한다.
- @Qualifier는 @Autowired와 함께 사용하여 정확히 어떤 bean을 사용할지 지정하여 특정 의존 객체를 주입할 수 있다.
- 📌 @Resource
- @Autowired와 마찬가지로 Bean 객체를 주입해주는데 차이점은 Autowired는 타입으로, Resource는 이름으로 연결해준다.
- 애노테이션 사용으로 인해 특정 Framework에 종속적인 애플리케이션을 구성하지 않기 위해서 @Resource 사용을 권장한다.
- 📌 @Controller
- API와 view를 동시에 사용하는 경우에 사용
- 보통 view 화면 return을 목적으로 사용한다.
- 📌 @RestController
- view가 필요 없이 API만 지원하는 서비스에서 사용
- 📌 @SpringBootApplication
- @Configuration, @EnableAutoConfiguration, @ComponentScan 3가지를 하나로 합친 애노테이션
서블릿 컨테이너 : 웹서버와 통신을 지원하고, 서블릿의 생명주기와 멀티쓰레드 관리
🗒️ 예시 : 톰캣(Tomcat)
📖 참고 📖 Servlet Container 과정
- 1️⃣ : 요청 받으면 쓰레드 풀에서 쓰레드를 꺼내 할당하고, ServletRequest, ServletResponse 두 객체 생성
- 2️⃣ : 매핑할 서블릿 확인하고, Servlet Container에 없을 경우
init()
메서드, 있을 경우service()
메서드 호출- 3️⃣ : 응답 처리하면,
distroy()
메서드 실행하여 ServletRequest, ServletResponse 객체 소멸 (가비지 컬렉션)
1) 코드 영역 (Text)
2) 데이터 영역
3) 힙 영역
4) 스택 영역
📖 참고 📖 heap과 stack 차이
- 스택은 높은 주소부터, 힙은 낮은 주소부터 채워짐
- 서로 영역 침범하느냐에 따라 stack overflow, heap overflow 발생
각 프로세스는 독립된 메모리 공간을 가지고, 다른 프로세스의 메모리 공간에 접근할 수 없음
OS만이 운영체제 메모리 영역과 사용자 메모리 영역의 접근이 가능하여 적절한 관리가 필요함
메모리 관리 방식 : 가상 메모리를 이용한 Swapping, 페이징 및 세그멘테이션 전략, 고정길이 할당/가변길이 할당, 압축
Paging : 프로세스를 동일한 크기의 페이지로 분리, 메모리는 해당 페이지와 동일한 크기의 프레임으로 분리해서 메인 메모리에 불연속적으로 저장하는 방식 (내부 단편화 발생)
Segmentation : 프로세스를 가변적인 크기의 세그먼트로 분리, Code/Data/Stack/Heap으로 프레임을 분리해서 메인 메모리에 불연속적으로 저장하는 방식 (외부 단편화 발생)
단편화 : 프로세스들이 차지하는 메모리에 사용하지 못할 만큼의 작은 공간
내부 단편화 : 고정길이 할당/페이지에서 나타남, 메모리를 고정 길이로 잘랐을 때 해당 고정 길이보다 작은 프로세스가 저장되어 생기는 여백
외부 단편화 : 가변길이 할당/세그멘테이션에서 나타남, 메모리에 적재할 수 있는 크기가 프로세스보다 작으면 적재할 수 없을 때의 여백
Page Fault(프로세스 동작 중 필요한 페이지가 물리 메모리에 없는 상황)가 발생하면 원하는 페이지를 하드디스크의 Swapping을 통해 가져오는데, 물리 메모리가 가득찼을 경우 페이지 교체 발생
FIFO : 가장 오래된 페이지 교체
OPT (Optimal) : 가장 먼 미래 동안 사용되지 않을 페이지 교체 (불가능)
LFU (Least Frequently Use) : 가장 사용 빈도가 적은 페이지 고체
MFU (Most Frequently Use) : 가장 사용 빈도가 많은 펭지ㅣ 교체
LRU (Least Recently Use) : 가장 오랫동안 사용되지 않은 페이지 교체
NUR (Not Used Recently) : 가장 오랫동안 사용되지 않은 페이지 교체, 참조 비트와 변형 비트 사용하여 교체
Clock Algorithm : 각 페이지가 최근에 참조되었는지 reference bit 에 따라 페이지 교체 (오랫동안 참조되지 않은 페이지는 찾을 수 없고, 최근에 참조된 페이지는 피할 수 있음)
페이지 부재율이 높은 상태
메모리에 프로세스가 너무 많아지면, Page Fault가 일어나 페이지 교체가 일어나며 CPU 사용률이 줄어들게 되는데, CPU는 더 많은 프로세스를 메모리에 올리게 되며 악순환 발생
해결 방법
CPU 사용률과 메모리 적재량을 함께 체크하여 쓰레시 유무 파악
cache memory 사용 목적 : 앞으로 사용될 것으로 예상되는 데이터를 미리 저장하여, CPU와 메모리 사이의 속도 차이 완화
CPU hit ratio 높이기 위한 원리 : 참조 지역성 원리 사용
RAID : 여러 개의 디스크를 하나의 디스크처럼 사용(대용량 단일 볼륨 사용 효과), 디스크 I/O 병렬화로 성능 향상(RAID 0, RAID 5, RAID 6), 데이터 복제로 안전성 향상(RAID 1)
종류
📖 참고 📖 스트라이핑 (striping)
- 연속된 데이터를 여러 개의 디스크에 RR(라운드 로빈) 방식으로 기록하는 기술
📖 참고 📖 미러링 (mirroring)
- 다른 디스크에 디이터를 중복 저장하는 기술로 디스크가 에러 발생했을 때 복구 가능
Process : 메인 메모리에 적재되어 실행되는 프로그램
Thread : 한 프로세스 내의 실행 단위/실행 흐름을 의미
차이점 1️⃣
차이점 2️⃣
📖 참고 📖 크롬 브라우저는 한 탭에 오류가 생겨도, 다른 탭에 영향을 끼지 않습니다. 그렇다면 크롬은 프로세스인가요? 쓰레드인가요?
- 프로세스
- 크롬 탭이 쓰레드라면, 한 크롬탭에서 오류가 생기면 다른 크롬 탭에도 영향이 감
Multi Process : 하나의 프로그램을 여러 개의 프로세스로 구성해 프로세스가 병렬적으로 작업 수행 (타 프로세스에 영향X, 많은 메모리 공간 차지)
Multi Thread : 하나의 프로세스를 여러 개의 쓰레드로 구성해 쓰레드가 자원을 공유하면서 작업 수행 (문맥 교환 빠르고, 적은 메모리 공간 차지, 동기화 필요)
📖 참고 📖 멀티 쓰레드를 많이 사용하는 이유
- 하나의 프로그램 안에서 여러 작업을 해결하는게 더 효율적이고, Context Switching시 Stack 영역만 초기화하여 빠름
- 프로세스 생성시 자원 할당하는 콜이 줄어들어 자원 효율적 관리 가능
📖 참고 📖 Python에서의 멀티 프로세스
- 파이썬은 GIL(Global Interpreter Lock) 정책 사용
- 하나의 프로세스 안에 모든 자원의 Lock을 global하게 관리하여 한 번에 하나의 쓰레드만 자원을 컨트롤해 사용
- I/O 동작이 많은 프로그램의 경우 : 멀티 쓰레드만으로 효과
- CPU 동작이 많은 경우 : 멀티 프로세스를 이용해서 병렬적으로 수행 가능
Context Switching (문맥 교환) : 현재 진행중인 프로세스의 상태를 PCB에 저장하고, 다음 진행할 프로세스의 상태 값을 읽어 레지스터에 적재하는 과정
필요 원인 : CPU Cycle 속도가 I/O 작업에 비해 매우 빨라, 문맥 교환을 통해 다른 프로세스로 전환하여 CPU 사용률⬆️
📖 참고 📖 Context Switching 과정
- 1) CPU가 다른 프로세스로 전환하면, 시스템은 프로세스 상태를 PCB에 저장
- 2) 대기열에서 다음 프로세스를 선택하고, 해당 프로세스의 PCB를 복원
- 3) PCB의 프로그램 카운터(레지스터)가 로드되어, 이전까지 작업한 곳의 지점으로 돌아가 선택한 프로세스의 작업을 이어서 함
Process Control Block : 프로세스를 관리하기 위한 정보를 포함하는 OS 커널의 자료구조
과정 : OS는 프로세스의 생성과 동시에 고유한 PCB 생성 ➡️ 인터럽트 등 프로세스 전환이 발생하면, 진행하던 프로세스 관련 데이터를 PCB에 저장 ➡️ CPU 할당 받으면, PCB에서 내용 불러와 문맥 교환 후 다시 작업 수행
📖 참고 📖 PCB에 저장되는 정보
- 프로세스 식별자(PID) : 프로세스 식별번호
- 프로세스 상태 : new, ready, runnig, waiting, terminated 등 상태를 저장
- 프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소
- CPU 레지스터
- CPU 스케쥴링 정보 : 프로세스의 우선순위, 스케줄 큐에 대한 포인터
- 메모리 관리 정보 : 페이지/세그먼트 테이블 등 정보
- 입출력 상태 정보 : 프로세스에 할당된 입출력 장치와 열린 파일 목록
- 어카운팅 정보 : 사용된 CPU 시간, 시간제한, 계정정보 등
Sync : 요청을 하면 반드시 결과가 주어져야 함
Async : 요청과 결과가 동시에 일어나지 않음
동기/비동기 : 호출된 함수의 종료를 호출한 함수가 처리하는지, 호출된 함수가 처리하는지
Blocking : A함수가 B함수를 호출할 때, B함수가 자신의 작업 종료하기 전까지 A함수에게 제어권을 돌려주지 않는 것
Non-Blocking : A함수가 B함수를 호출할 때, B함수가 A함수에게 바로 제어권 돌려주는 것
blocking/non-blocking : 호출된 함수가 호출한 함수에게 제어권을 바로 주는지, 안주는지
자식 프로세스 : fork로 자식 프로세스를 만튼 상태 (부모의 데이터, 힙, 스택, PCB 복사)
데몬 프로세스 : 백그라운자에서 동작하면서 특정 서비스를 제공하는 프로세스
고아 프로세스 : 부모 프로세스가 먼저 종료되어 고립된 자식 프로세스
좀비 프로세스 : 자식 프로세스가 종료되었음에도 불구하고, 부모 프로세스로부터 작업 종료에 대한 승인을 받지 못한 프로세스
Race Condition (경쟁상태) : 2개 이상의 쓰레드가 공유자원에 대해 접근하려고 서로 경쟁하는 것
Crtical Section (임계 영역) : 공유자원이 존재하여 경쟁상태가 일어날 수 있는 영역
Mutual Exclusion (상호 배제) : 임계 영역에 대한 경쟁상태를 제거하기 위해서 1 공유자원에 1 쓰레드만 접근하도록 허락함
Deadlock : 2개 이상의 프로세스나 쓰레드가 서로 자원을 기다리면서 무한히 대기하는 상태
발생 조건
해결 방법
📖 참고 📖 은행원 알고리즘
- 프로세스가 자원을 요구할 때 시스템은 자원을 할당한 후에도 안정 상태로 남아있는지 사전 검사 알고리즘
- 발생하지 않으면 자원을 할당하고, 발생하면 다른 프로세스가 자원을 해제할 때까지 대기
- 안전상태 : 시스템이 교착상태를 일으키지 않으면서 각 프로세스가 요구한 최대 요구량만큼 필요한 자원을 할당해 줄 수 있는 상태
- 장점 : 항상 안전 상태를 유지할 수 있음
- 단점 : 최대 자원 요구량을 미리 알아야하고, 항상 불안전 상태를 방지해야 하므로 자원 이용도가 낮음
점유대기
비선점
환형대기
상호배제
Mutex : 오직 1개의 프로세스(스레드)만 접근 가능하고, 반드시 락을 획득한 프로세스는 락을 해제해야 함
Semaphore : 세마포어 변수만큼의 프로세스(스레드)가 접근 가능하고, 현재 수행중인 프로세스가 아닌 다른 프로세스가 세마포어 해제 가능
뮤텍스와 세마포어를 사용해 임계영역에서 경쟁상태 제거 가능
이진 세마포어 = 뮤텍스, 그 외 세마포어를 카운팅 세마포어라고 부름
스풀링 : 나중에 처리하거나 인쇄하기 위해 데이터를 일시적으로 저장하는 시스템 (다른 응용프로그램이 동시에 출력을 프린터로 보내면 스풀링은 모든 작업을 작업 풀(디스크 파일)에 보관하고 프린터에 따라 대기열에 넣음)
공통점 : 버퍼링과 스풀링은 CPU의 처리속도와 입출력 장치의 속도 차이를 보완하기 위한 방법
차이점
CPU Scheduling : Ready Queue에 있는 프로세스 중 다음에 CPU에 할당할 프로세스를 선택하는 알고리즘
비선점
선점
📖 참고 📖 입출력 제어 방식 4가지
- 1️⃣ : 프로그램에 의한 I/O (CPU 개입⭕)
- 2️⃣ : 인터럽트에 의한 I/O (CPU 개입⭕)
- 3️⃣ : DMA에 의한 I/O (CPU 개입❌)
- 4️⃣ : 채널에 의한 I/O (CPU 개입❌)
📖 참고 📖
- ✏️
➡️⬆️⬇️