Revert "archive 삭제"

This reverts commit 973af1937e.
This commit is contained in:
2026-04-09 10:17:21 +09:00
parent 3ff1886267
commit 69ab355bb9
245 changed files with 3799 additions and 0 deletions
@@ -0,0 +1,9 @@
JVM이 메모리를 자동으로 관리해주는 것은 개발자의 입장에서 상당한 메리트이다.
하지만 문제는 GC를 수행하기 위해 Stop The World가 발생되고 이 때문에 애플리케이션이 중지되는 문제점이 발생하게 됭써다.
또한 자바가 발전됨에 따라 Heap의 사이즈가 커지면서 애플리케이션의 지연(Suspend) 현상이 두드러지게 되었고, 이를 최적화 위해 다양한 Garbage Collection(가비지 컬렉션) 알고리즘이 개발 되었다.
![[GC Algorithm 종류.png]]
알고리즘 종류
@@ -0,0 +1,27 @@
- 자바 옵션에 `-verbosegc` 라는 옵션을 주면 되고, `>` 리다이렉션 명령어를 통해서 파일로 저장하고 분석할 수 있다.
```bash
java -jar -verbosegc app.jar
```
Eclipse에서 찍는 방법
```ruby
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:D:\log\gclog\gclog.log
```
"할당 실패"는 GC 주기가 시작되는 원인입니다.
"할당 실패"는 Eden에 객체를 할당할 공간이 더 이상 남아 있지 않음을 의미합니다. 따라서 이는 ***Young GC의 정상적인 원인***입니다.
이전 JVM은 사소한 GC 주기에 대한 GC 원인을 인쇄하지 않았습니다.
"할당 실패"는 마이너 GC의 원인일 수 있는 거의 유일한 원인입니다. 마이너 GC가 발생하는 또 다른 이유는 CMS 설명 단계(+XX:+ScavengeBeforeRemark가 활성화된 경우) 때문일 수 있습니다.
"Allocation Failure" is a cause of GC cycle to kick in.
"Allocation Failure" means that no more space left in Eden to allocate object. So, it is normal cause of young GC.
Older JVM were not printing GC cause for minor GC cycles.
"Allocation Failure" is almost only possible cause for minor GC. Another reason for minor GC to kick could be CMS remark phase (if `+XX:+ScavengeBeforeRemark` is enabled).
@@ -0,0 +1,3 @@
![[GC Log 읽는법.png]]
[gceasy.io](http://gceasy.io/)등의 사이트를 이용하면 GC로그를 분석해 시각화 해주는 기능을 이용할 수있다!
@@ -0,0 +1,117 @@
### Gc tuning 절차 간단히 맛보기
[[GC]] 상황을 모니터링하며 현재 운영되는 시스템의 GC 상황을 확인한다.
```bash
# jstat gcutil 명령어로 현재 실행중인 8884번 프로세스에 대해 1초에 한번 씩 총 10번 GC와 관련된 정보를 출력하도록 모니터링
jstat -gcutil -t 8844 1000 0
```
![[jstat.png]]
| 컬럼 | 설명 |
| ---- | -------------------------------- |
| S0 | Survivor 영역 0의 사용율(현재 용량에 대한 비율) |
| S1 | Survivor 영역 1의 사용율(현재 용량에 대한 비율) |
| E | Eden 영역의 사용율 (현재 용량에 대한 비율) |
| O | Old 영역의 사용율 (현재 용량에 대한 비율) |
| P | Permanent 영역의 사용율 (현재 용량에 대한 비율) |
| YGC | Young 세대의 GC 이벤트 수 |
| YGCT | Young 세대의 GC 시간 |
| FGC | Full GC 이벤트 수 |
| FGCT | Full GC 시간 |
| GCT | GC 총 시간 |
#### **2.** **모니터링 결과 분석 후 GC 튜닝 여부 결정**
GC 상황을 확인한 후에는, 결과를 분석하고 GC 튜닝 여부를 결정해야 한다.
- **Minor GC 수행시간** : YGCT / YGC (0.314 / 19) = 0.016초
- **Major GC 수행 시간** : FGCT / FGC (0.291 / 3) = 0.097초
![[jstat 2.png]]
만약 모니터링 결과가 다음의 조건에 모두 부합한다면, GC 튜닝이 굳이 필요하지는 않다.
- Minor GC의 처리 시간이 빠르다 (50ms 내외)
- Minor GC의 주기가 빈번하지 않다 (10초 내외)
- Full GC의 처리 시간이 빠르다 (1초 내외)
- Full GC의 주기가 빈번하지 않다 (10분에 1회)
#### **3.** **GC 알고리즘 방식 지정**
위의 모니터링 결과를 보고, GC 튜닝을 진행하기로 결정했다면 GC 알고리즘 방식을 선정한다.
이때 서버가 여러 대이면 서버에 GC 옵션들을 서로 다르게 각각 지정해서, 현재 내 어플리케이션의 GC 알고리즘에 따른 차이를 확인하는 것이 좋다. (알고리즘이 더 최신이라고 해서 반드시 내 어플리케이션에서 해당 GC 방식이 적절하다라고 보증 할수 없다)
| | |
|---|---|
[[GC Algorithm]]
[[Parallel GC]]
- **'처리량'이 중요한 시스템에서 주로 사용** <br>- Full GC 수행 시 compaction 작업이 수행되기 때문에 GC 시간 자체는 많이 소요되나 일정한 멈춤 시간을 제공함|
CMS GC|
- **응답시간이 중용한 시스템에사 주로 사용** <br>- compaction 미수행으로 Stop-The-World 시간은 짧으나 자주 Compaction이 발생하는 시스템의 경우 오히려 Full GC 보다 Compation 시간이 오래 걸릴 수 있음 <br>- 자원 사용량이 증가하는 점도 고려해야 함|
G1 GC|
- 성능적으로 가장 우수한 GC 방식이나, JDK 7 버전부터 정식 제공되었으며, Java 9 에서 Default GC 방식으로 채택|
#### **4. 힙 메모리 크기 지정**
[[JVM Heap Area]]는 크기에 따라 GC 발생 횟수와 수행 시간에 영향을 끼치기 때문에 옵션을 통해 조절하면 어플리케이션 성능 향상 효과를 가져올 수 있다.
여기서 말하는 메모리 크기는 JVM의 시작 크기(-Xms)와 최대 크기(-Xmx)를 말한다.
[[Xms, Xmx]]
메모리 크기와 GC 발생 횟수, GC 수행 시간의 관계는 다음과 같다.
- 메모리 크기가 크면,
- GC 발생 횟수는 감소한다.
- GC 수행 시간은 길어진다.
- 메모리 크기가 작으면,
- GC 발생 횟수는 짧아진다.
- GC 수행 시간은 증가한다.
| 구분 | 옵션 | 설명 |
| ------------- | ------------------ | ------------------------ |
| 힙(heap) 영역 크기 | \-Xms | JVM 시작 시 힙 영역 크기 |
| 힙(heap) 영역 크기 | \-Xmx | 최대 힙 영역 크기 |
| New 영역의 크기 | \-XX:NewRatio | New 영역과 Old 영역의 비율 |
| New 영역의 크기 | \-XX:NewSize | New 영역의 크기 |
| New 영역의 크기 | \-XX:SurvivorRatio | Eden 영역과 Survivor 영역의 비율 |
> [!note] 이 중에서 중요한 옵션은 -Xms 옵션, -Xmx 옵션, -XX:NewRatio 옵션이다.
특히 ==-Xms 옵션과 -Xmx 옵션은 왠만하면 필수로 지정하길 권장==하며, 그리고 NewRatio 옵션을 어떻게 설정하느냐에 따라서 GC 성능에 많은 차이가 발생한다.
==NewRatio는 New 영역과 Old 영역의 비율이다.==
-XX:+NewRatio=1로 지정하면 (New 영역):(Old 영역)의 비율은 1:1이 된다.
만약 1GB라면 (New 영역):(Old 영역)은 500MB:500MB가 된다.
NewRatio가 2이면 (New 영역):(Old 영역)이 1:2가 된다.
즉, **값이 커지면 커질수록 Old 영역의 크기가 커지고 New 영역의 크기가 작아진다.**
```bash
# 힙 시작 크기 256mb, 힙 최대 크기 2gb
# young 영역과 old 영역 비율 1:2 로 설정 (New 영역:Old 영역 = 1:2)
# Parallel GC 로 실행
java -Xms256m -Xmx2048m -XX:+NewRatio=2 -XX:+UseParallelGC
```
#### **5.** **튜닝 결과 분석**
GC 옵션을 지정하고 24시간 이상(하루, 이틀) 데이터를 수집한다.
그리고 로그를 분석해 메모리가 어떻게 할당되는지 확인한다.
그 다음에 GC 방식 / 메모리 크기를 변경해 가면서 최적의 옵션을 찾아 나가면 된다.
분석할 때는 다음의 사항을 중심으로 살펴보는 것이 좋다. 이는 우선 순위 별로 나열되어 있다.
1. FullGC 수행 시간
2. MinorGC 수행 시간
3. Full GC 수행 간격
4. MinorGC 수행 간격
5. 전체 Full GC 수행 시간
6. 전체 Minor GC 수행 시간
7. 전체 GC 수행 시간
8. Full GC 수행 횟수
9. Minor GC 수행 횟수
#### **6.** **전체 서버에 반영 및 종료**
GC 튜닝 결과가 만족스러우면 전체 서버에 GC 옵션을 적용하고 마무리한다.
@@ -0,0 +1,61 @@
[[GC]]
GC 튜닝이 필요한 이유: [[STW (Stop The World)]]
- STW가 발생하면 [[GC]]를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춤.
- GC작업이 완료된 이후에야 중단했던 작업을 다시 시작됨.
- GC가 자주 발생하거나, 또는 시간이 오래 걸리는 경우는 어플리케이션이 비정상 동작하는 시간이 길어진다는 의미이기 때문에 대게의 경우 ==gc 튜닝이란 STW 시간을 줄이는 것을 의미==
### **GC 튜닝의 주의점**
그런데 GC 튜닝에 있어서 꼭 명심해야 하는 점이 있다.
**첫째는, GC 튜닝 옵션은 서비스의 특징 마다 적정 값이 다르다는 것이다.**
예를 들어 '누가 이 옵션값을 썼을 때 성능이 잘 나왔으니 우리도 이렇게 적용하자.' 라고 생각하면 절대 안 된다.
왜냐하면 서비스 주제와 특징마다 생성되는 객체의 크기도 다르고 살아있는 기간도 다르기 때문이다. 
따라서 별도의 성능 모니터링을 통해 어느 지점에서 GC의 STW 문제가 나는지 **서비스마다 제각각 파악**하여 GC 튜닝을 진행할 필요가 있다.
**둘째는, GC 튜닝은 가장 마지막에 하는 작업이라는 것이다.**
GC 튜닝은 필요한 선행 지식과, 신경써야할 요소, 리스크에 비해서 얻어가는 부분이 너무 적기 때문에, GC를 건드리는 것보다 애플리케이션 코드로써 메모리 최적화를 더 신경 쓸것을 권장하는 의견도 있다.
GC 튜닝을 왜 하는지 근본적인 이유를 생각해보자.
일반적으로 Java에서 생성된 객체는 가비지 컬렉터가 처리해서 지운다.
즉, 생성된 객체가 많으면 많을수록 가비지 컬렉터가 처리해야 하는 대상도 많아지고, GC를 수행하는 횟수도 증가한다는 말이다. 그리고 GC의 수행 횟수가 늘어나면 STW 횟수도 많아지니 성능에 영향이 가게 된다.
따라서 GC 자체를 튜닝 하기 이전에 먼저 코드 단에서 **쓸모없는 객체 생성을 줄이는 리팩토링 작업을 먼저** 하는 것이 근본적인 해결법이 된다.
예를들어 ~~String~~ 대신 ~~StringBuilder~~나 ~~StringBuffer~~를 사용하는 거나, 로그를 최대한 적게 쌓도록 하는 등 임시 메모리를 적게 사용하도록 해주는 것이 먼저이다.
그리고 리팩토링 작업과 어플리케이션 메모리 조정을 해도 여전히 성능에 문제가 생기면 그제서야 GC 튜닝을 진행한다.
다시 말하자면 GC 튜닝은 자바 어플리케이션 성능 향상 작업에서 가장 마지막에 하는 작업이라는 것을 잊지 말자.
### **GC 튜닝의 목표**
**GC 튜닝**이란, 성능상 이슈를 일으키기 쉬운 GC에 대하여 최적화를 진행 하는 것을 말한다.
GC 튜닝의 목표의 핵심은 [[Minor GC]] 보다 Stop-The-Wold 시간이 긴 [[Major GC]]의 관리이다.
**첫째는, Old 영역으로 넘어가는 객체의 수 최소화하기 이다.**
위에서 살펴봤듯이, Old 영역의 크기는 Young(New) 영역의 크기보다 훨씬 거대하다.
따라서 Old 영역의 GC는 Young(New) 영역의 GC에 비해 상대적으로 시간이 오래 소요되기 때문에, 애초에 Old 영역으로 이동하는 객체의 수를 줄이면 Full GC가 발생하는 빈도를 많이 줄일 수 있게 된다.
이말은 즉, **Young(New) 영역의 크기를 잘 조절**하여 Old 영역으로 넘어가는 빈도를 줄이면 큰 효과를 볼 수 있다는 뜻이다.
**둘째는, Full GC 시간 줄이기 이다.**
Full GC의 실행 시간은 상대적으로 Minor GC에 비해 길기 때문에, Old 영역의 크기를 적절하게 설정하는 것도 하나의 방법이다.
그렇다고 Old 영역의 크기를 막 줄여버리면 자칫 OutOfMemoryError가 발생하거나 Full GC 횟수가 늘어날 수도 있다.
반대로 Old 영역의 크기를 늘리면 Full GC 횟수는 줄어들지만 실행 시간이 늘어나게 된다.
즉, GC 튜닝의 관건은 이 둘 사이를 잘 아우르는 적정 범위를 찾는 것이라 할 수 있다.
@@ -0,0 +1,16 @@
[[GC]]은 어떤 Object를 Garbage로 판단해서 스스로 지워버릴까?
가비지 컬렉션은 특정 객체가 garbage인지 아닌지 판단하기 위해서 도달성, 도달능력(Reachability) 이라는 개념을 적용한다.
객체에 레퍼런스가 있다면 Reachable로 구분되고, 객체에 유효한 레퍼런스가 없다면 Unreachable로 구분해버리고 수거해버린다. 
- Reachable : 객체가 참조되고 있는 상태
- Unreachable  : 객체가 참조되고 있지 않은 상태 (GC의 대상이 됨) 
![[Heap Unrechable.png]]
예를들어 JVM 메모리에서는 객체들은 실질적으로 Heap영역에서 생성되고 Method Area이나 Stack Area 에서는 Heap Area에 생성된 객체의 주소만 참조하는 형식으로 구성된다.
하지만 이렇게 생성된 Heap Area의 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap Area 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면, 위의 그림에서의 빨간색 객체와 같이 Heap영역에서 어디서든 참조하고 있지 않은 객체(Unreachable)들이 발생하게 된다.
이러한 객체들을 주기적으로 가비지 컬렉터가 제거해주는 것이다.
@@ -0,0 +1,15 @@
### GC (Garbage Collection)
==사용하지 않는 메모리를 자동으로 회수하여 가용한 공간을 만드는 작업==
- GC 전담 thread가 별도로 존재하여 메모리가 부족하다고 판단되는 시점에 주기적으로 일어남
- JVM(자바 가상 머신)의 **Heap 영역**에서 **동적으로 할당했던 메모리** 중 **필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거**하는 프로세스를 말한다.
[[GC에 대한 별첨설명]]
[[Major GC]] , [[Minor GC]]
[[GC 대상]]
[[GC Tuning]]
[[JVM Heap Area]]
[[GC Algorithm]]
[[GC Tuning 절차]]
[[GC Log 수집 방법]]
@@ -0,0 +1,46 @@
가비지 컬렉션(Garbage Collection, 이하 GC)은 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 **Heap 영역**에서 **동적으로 할당했던 메모리** 중 **필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거**하는 프로세스를 말한다.
C / C++ 언어에서는 이러한 가비지 컬렉션이 없어 프로그래머가 수동으로 메모리 할당과 해제를 일일이 해줘야 했었다.
반면 Java에서는 가비지 컬렉터가 메모리 관리를 대행해주기 때문에 Java 프로세스가 한정된 메모리를 효율적으로 사용할수 있게 하고, 개발자 입장에서 메모리 관리, 메모리 누수(Memory Leak) 문제에서 대해 관리하지 않아도 되어 오롯이 **개발에만 집중**할 수 있다는 장점이 있다.
예시를 들자면 다음과 같은 조금 억지스러운(?) 코드를 실행한다고 가정하자.
```java
for (int i = 0; i < 10000; i++) {
NewObject obj = new NewObject();
obj.doSomething();
}
```
루프문에 의해서 10000 건의 NewObject 객체는 for문 스코프 내에서 생성되고 사용되지만, 루프가 끝나고 루프 밖에서는 더이상 사용할 일이 없어진다.
만일 이런 객체들이 메모리를 계속 점유하고 있다면, 다른 코드를 실행하기 위한 메모리 자원은 지속적으로 줄어들기만 할 것이다. 하지만 우리는 이에 대해서 별다른 작업을 하지 않고 구현 코드를 이어 나간다.
이것이 가능한 이유는, 가비지 컬렉션(GC)이 한번쓰이고 버려지는 객체들을 주기적으로 비워줌으로써 한정된 메모리를 효율적으로 사용할 수 있게 해주기 때문이다.
또한 가비지 컬렉션(GC)는 꼭 자바(Java)에만 있는 개념이 아니다.
파이썬, 자바스크립트, Go 언어 등 **많은 프로그래밍 언어에서 가비지 컬렉션이 기본으로 내장**되어 있다.
당장 여러분이 보고있는 이 브라우저 역시도 자체적으로 구현된 가비지 컬렉션이 있기 때문에 별다른 메모리 관리 없이 웹페이지를 만들수 있는 것이다.
따라서 이번 시간에 가비지 컬렉션에 대해 제대로 학습한다면, 자바 외의 언어의 가비지 컬렉션 동작에 대해서도 어느정도 통달되었다고 말할 수 있다.
그러나 이런 만능 같은 가비지 컬렉션에도 **단점**이 존재한다.
자동으로 처리해준다 해도 메모리가 언제 해제되는지 정확하게 알 수 없어 제어하기 힘들며, 가비지 컬렉션(GC)이 동작하는 동안에는 다른 동작을 멈추기 때문에 **오버헤드**가 발생되는 문제점이 있다.
이를 전문적인 용어로 **Stop-The-World** 라 한다.
[[STW (Stop The World)]]
따라서 이 시간을 최소화 시키는 것이 쟁점이다.
이로 인해 GC가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 되기도 하다.
예를들면 익스플로러는 이 가비지 컬렉션를 너무 자주 실행하여 성능 문제를 일으키는 것으로 악명이 높았다.
이런 특성에 따라 실시간 성이 매우 강조되는 포로그램일 경우 가비지 컬렉터(GC)에게 메모리를 맞기는 것은 맞지 않을 수 있다.
따라서 어플리케이션의 사용성을 유지하면서 효율적이게 GC를 실행하는 최적화 작업이 개발자의 숙제가 된다.
그리고 이러한 GC 최적화 작업을 [[GC Tuning]]이라고 한다.
@@ -0,0 +1,24 @@
### Major GC (Full GC)
[[Young Generation]]영역에서 살아남은 객체가 이동된 [[Old Generation]]에서 발생하며, Full GC==로 불리기도 함
Old 영역에서 일어나는 GC로, 기본적으로 [[Mark-Sweep-Compact]] 알고리즘 사용
- ==Major GC는 작업이 진행되는 동안 어플리케이션 동작이 멈추기== 때문에, 실제 성능 및 안정성에 큰 영향을 미치게 됨
**Major GC**는 Old 영역이 가득 차면 GC를 실행하는 단순한 방식이다. 
Old 영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 Major GC가 실행되게 된다.
하지만 Old Generation은 Young Generation에 비해 상대적으로 큰 공간을 가지고 있어, 이 공간에서 메모리 상의 ==객체 제거에 많은 시간이 걸리게 된다.==
예를들어 Young 영역은 일반적으로 Old 영역보다 크키가 작기 때문에 GC가 보통 0.5초에서 1초 사이에 끝난다.
그렇기 때문에 Minor GC는 애플리케이션에 크게 영향을 주지 않는다.
하지만 Old 영역의 Major GC는 일반적으로 Minor GC보다 시간이 오래걸리며, 10배 이상의 시간을 사용한다.
이 때 [[STW (Stop The World)]] 가 문제가 된다.
[[Major GC]]가 일어나면 Thread가 멈추고 Mark and Sweep 작업을 해야 해서 CPU에 부하를 주기 때문에 어플리케이션이 멈추거나 버벅이는 현상이 일어나기 때문이다.
따라서 자바 개발진들은 끊임 없이 **가비지 컬렉션 알고리즘을 발전** 시켜왔다.
@@ -0,0 +1,7 @@
- Mark
Old 영역의 객체 중 사용하는 것과 사용하지 않는 객체 식별
- Sweep
Heap의 앞 부분부터 사용하지 않는 것으로 식별된 객체 삭제
- Compact
삭제된 객체가 사용하고 있던 공간을 정리하여 각 객체가 heap의 앞부분부터 연속적으로 쌓이도록 정리
@@ -0,0 +1,12 @@
새로 생성된 객체가 위치하는 Young 영역에서 발생
- Eden([[Young Generation]]) 영역의 GC
- Eden 영역 1개와 Survivor 영역 2개를 이용해 Copy & Scavenge 방식으로 GC를 진행
##### 1st GC
- 새로 생성된 대부분의 객체는 Eden 영역에 위치
- Eden 영역이 차게 되면 Minor GC가 발생하게 되며 살아남은 객체는 Survivor 영역 중 하나로 이동
- 이후 Eden 영역에서 GC가 발생하면 기존에 살아남은 객체가  존재하는 Survivor 영역 쪽으로 계속 쌓임
##### 2nd GC
- 하나의 Survivor 영역이 가득 차게 되면 그 중에 살아남은  객체를 다른 Survivor 영역으로 이동하며, 가득 찼던 Survivor  영역은 데이터가 없는 상태가 됨
- 이 과정을 반복하다가 계속해서 살아남아 있는 객체는 Old  영역으로 이동
@@ -0,0 +1,9 @@
Old Generation은 길게 살아남는 메모리들이 존재하는 공간이다.
Old Generation의 객체들은 거슬러 올라가면 처음에는 [[Young Generation]]에 의해 시작되었으나, GC 과정 중에 제거되지 않은 경우 age 임계값이 차게되어 이동된 녀석들이다.
그리고 [[Major GC]]는 객체들이 계속 Promotion되어 Old 영역의 메모리가 부족해지면 발생하게 된다.
Tip
Major GC는 Full GC라고도 불리운다.
@@ -0,0 +1,11 @@
- Java 8의 디폴트 [[GC]]
- [[Serial GC]]와 기본적인 알고리즘은 같지만, [[Young Generation]]영역의 [[Minor GC]]를 멀티 쓰레드로 수행 ([[Old Generation]] 영역은 여전히 싱글 쓰레드)
- Serial GC에 비해 [[STW (Stop The World)]]시간 감소
- Parallel GC의 스레드는 기본적으로 cpu 개수만큼 할당된다.
(Single Core에서 Parallel GC로 동작 시 Serial GC로 작동한다.)
# Parallel Old GC
- Parallel GC를 개선한 버전
- Young 영역 뿐만 아니라, Old 영역에서도 멀티 쓰레드로 GC 수행
- 새로운 가비지 컬렉션 청소 방식인 Mark-Summary-Compact 방식을 이용 (Old 영역도 멀티 쓰레드로 처리)
@@ -0,0 +1,4 @@
- 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 [[GC]]
- GC를 처리하는 쓰레드가 1개 (싱글 쓰레드) 이어서 가장 [[STW (Stop The World)]] 시간이 길다
- [[Minor GC]]에는 Mark-Sweep을 사용하고, [[Major GC]]에는 [[Mark-Sweep-Compact]]를 사용한다.
- 보통 실무에서 사용하는 경우는 없다 (디바이스 성능이 안좋아서 CPU 코어가 1개인 경우에만 사용)
@@ -0,0 +1,7 @@
Young Generation 영역은 짧게 살아남는 메모리들이 존재하는 공간이다.
모든 객체는 처음에는 Young Generation에 생성되게 된다.
==Young Generation의 공간은 Old Generation에 비해 상대적으로 작기 때문에 메모리 상의 객체를 찾아 제거하는데 적은 시간이 걸린다. ==(작은 공간에서 데이터를 찾으니까)
이 때문에 Young Generation 영역에서 발생되는 [[GC]]를 [[Minor GC]]라 한다.
@@ -0,0 +1,8 @@
## Heap Area
힙 메모리(Heap Memory)는 프로그램에서 동적으로 할당된 메모리를 관리하는 데 사용되는 영역입니다. 프로그램이 실행될 때, 운영체제는 프로그램에 메모리 공간을 할당하며, 이 공간은 스택(Stack)과 힙(Heap)으로 구성됩니다. 스택은 지역 변수와 함수 호출 시 생성되는 변수들을 저장하는 영역이고, 힙은 동적으로 할당되는 메모리를 저장하는 영역입니다.
힙 메모리는 프로그램에서 필요한 만큼의 메모리를 동적으로 할당하여 사용합니다. 이러한 동적 할당은 프로그램에서 사용되는 데이터의 크기를 미리 예측하기 어려울 때 유용합니다. 힙 메모리는 일반적으로 malloc(), calloc(), realloc()과 같은 함수를 사용하여 할당됩니다. 이러한 함수는 메모리의 크기를 결정하고, 메모리 주소를 반환합니다. 반환된 메모리 주소는 포인터 변수에 저장되며, 이 포인터 변수를 통해 할당된 메모리에 접근할 수 있습니다.
힙 메모리는 스택과 달리, 메모리 블록을 계속해서 할당하거나 해제할 수 있기 때문에, 메모리 누수(Memory Leak)가 발생하기 쉽습니다. 메모리 누수란, 할당된 메모리를 해제하지 않은 채로 프로그램이 종료되거나, 해당 메모리를 더 이상 사용하지 않을 때 발생합니다. 메모리 누수는 시스템의 성능에 영향을 미치며, 심각한 경우 시스템 충돌을 일으킬 수 있습니다. 따라서, 동적으로 할당된 메모리를 사용하는 프로그램에서는 할당된 메모리를 적절한 방법으로 해제하여 메모리 누수를 방지해야 합니다.
힙 메모리는 운영체제와 프로그램 사이의 중간 영역으로써, 프로그래머가 메모리 관리를 주도적으로 수행할 수 있는 유연성을 제공합니다. 그러나 이러한 유연성은 부적절한 사용으로 인해 메모리 누수와 같은 문제를 발생시킬 수 있으므로, 프로그래머는 힙 메모리를 사용할 때 주의를 기울여야 합니다.
@@ -0,0 +1,33 @@
**프록시(Proxy)란 '대리', '대신'이라는 뜻을 가지며, 프로토콜에 있어서는 대리 응답 등에서 사용하는 개념**이다.
==클라이언트와 서버 사이에 존재하며, 중계기로서 대리로 통신을 수행==하는 것을 Proxy라고 하며, 그 중계 기능을 하는 주체를 Proxy Server라고 한다.
##### 프록시 서버의 종류
###### 포워드 프록시(Forward Proxy)
보통 말하는 프록시가 바로 이 포워드 프록시를 말한다.
Client와 Server 사이에 위치하여 요청을 중계하며, 요청과 응답은 Proxy Server를 거친다.
클라이언트를 감추는 효과가 있다.
###### 리버스 프록시(Reverse Proxy)
포워드 프록시와 마찬가지로 요청과 응답이 Proxy Server로 이동하는데, 포워드 프록시와 다르게 Server들이 주로 내부망으로 구성되며 프록시에게만 연결을 허용한다. 즉, 서비스를 위한 보안 채널을 구축한다.
이런 경우 Client가 Server에 직접 접근이 불가능하므로, Reverse Proxy에서 요청을 적극적으로 중계하는 Load Balancing의 역할을 수행하기도 한다.
서버를 감추는 효과가 있다.
##### 프록시 서버를 사용하는 이유
###### 개인정보를 보호할 수 있다
프록시 서버 없이 클라이언트가 서버에 요청 시 본인의 IP 주소가 노출되는데, 프록시 서버를 사용 시 서버측에서 나의 IP가 아닌 프록시 서버의 IP를 보게 된다.
즉, IP를 숨길 수 있다.
###### 캐시를 사용해서 속도가 향상된다
프록시 서버는 웹페이지를 가져올 때 자신의 DB에 최근 데이터를 저장하는데, 이것을 Cache라 한다.
이렇게 될 시, 같은 요청이 들어오면 Cache자원을 반환하여 서비스의 속도를 높이고 대역폭도 줄일 수 있다.
###### 로그를 기록, 관리할 수 있다
서버 측에선 클라이언트의 기록대신 프록시 서버의 기록이 있지만, 프록시 서버에겐 클라이언트의 기록이 남아있다.
이 기록들을 보면 어떤 IP에서 어떤 IP로 얼마나 접속해 있는지 확인할 수 있고, 특정 IP가 방문할 수 있는 웹사이트도 제한할 수 있어서 회사에서 많이 사용한다.
###### 접속을 우회할 수 있다
특정 사이트에서 IP를 검사해 한국에서의 접속을 차단하는 경우가 있는데, 이런 경우 프록시 서버를 사용해 접속 시 다른나라에서 접속한 것처럼 우회할 수 있다.
@@ -0,0 +1,2 @@
GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미.
GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어 서비스 이용에 차질이 생길 수 있다.