묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨면접 전에 알고 가면 좋을 것들 - 신입 Java 백엔드 개발자편
JVM/GC 최적화 관련 질문드립니다!
안녕하세요! 강의에서 GC와 JVM 메모리 관리에 대해 설명해주신 부분을 듣다가, 제가 겪었던 Thread Starvation 문제가 떠올라 질문을 남기게 되었습니다 🤓 제가 겪었던 상황에 대해서 정리해보겠습니다. ✔ 1차 문제 발생[프로젝트 환경]- Spring Boot 3.x, Java 21- AWS EC2 t3.small (2 vCPU, 2GB RAM)- Docker 컨테이너 배포- 개발 서버 (비용 최적화 목적) [문제 발생 과정]초기에는 Docker 메모리 제한 없이 JVM만 -XX:MaxRAMPercentage=75.0로 설정했습니다. 카카오 소셜 로그인 기능을 추가한 후 배포 시 Thread Starvation 문제가 발생했습니다.# 초기 설정 (문제 발생)- Docker: 메모리 제한 없음- JVM: -XX:MaxRAMPercentage=75.0 (호스트 2GB의 75% = 1.5GB) [결과]- JVM이 힙 1.5GB + 스택/Metaspace 400MB = 총 1.9GB 사용- OS/Docker 600MB 사용- 총 2.5GB 필요 → t3.small 2GB 초과- Thread Starvation 발생 [1차 해결]Docker 메모리 제한을 추가하고 JVM heap을 축소했습니다.# DockerfileENTRYPOINT ["java", "-XX:+UseZGC", "-Xms512m", "-Xmx1g", "-jar", "app.jar"]# 배포 스크립트docker run -d --memory="1.5g" --memory-swap="1.5g" --cpus="1.8" ... ✔ 2차 문제 발생이후 구글/네이버 소셜 로그인, CRUD API들이 추가되면서 다시 Thread Starvation이 발생했습니다.AWS EC2 서버를 재부팅하고 SSH로 서버에 접속해서 원인을 파악해보았습니다. 아래 내용은 당시 작성했던 깃허브 이슈 내용입니다.✏ 문제 상황 정리1. 컨테이너 상태 확인- docker ps -a | grep nugudi-dev (컨테이너는 실행중이지만 unhealthy 상태)- docker top nugudi-dev (컨테이너 내부 프로세스 확인: 아무런 프로세스도 출력되지 않았습니다 → Java 프로세스가 죽은 상태) 2. 헬스체크 실패 원인 확인- Connection reset by peer 에러 → Spring Boot 애플리케이션이 정상적으로 응답할 수 없는 상태 3. 컨테이너 로그 확인- HikariCP에서 반복적으로 Thread Starvation 경고 → GC가 CPU를 독점하여 애플리케이션 스레드들이 실행될 기회를 얻지 못하고 있는 상태 4. OOM Killer 확인- docker inspect 명령으로 OOMKilled 여부 확인 → false → Linux의 OOM Killer가 프로세스를 강제 종료한 것이 아니라, Java 프로세스가 메모리 부족으로 인한 GC Thrashing 상태에서 스스로 응답 불가 상태 5. 메모리 사용량 측정- EC2 인스턴스의 실제 메모리 사용 현황을 파악하기 위해 컨테이너를 중지한 상태에서 free -m 명령 실행- OS + Docker 데몬: 256MB 사용- t3.small 인스턴스의 총 메모리: 1901MB- → 컨테이너에 안전하게 할당 가능한 메모리: 1901MB - 256MB = 1645MB (약 1.6GB) 6. Docker 메모리 사용량 확인 (docker stats nugudi-dev --no-stream)- 재부팅 후 안정화된 상태에서 컨테이너의 메모리 사용량 확인: 866MB / 1.5GB (56%) 사용- 안정화된 상태의 메모리 사용량. (따라서 애플리케이션 시작 단계에서의 피크 메모리 사용량은 아닙니다.) 7. CPU 크레딧 확인- 78-90 크레딧 유지하고 있음. 따라서 CPU 크레딧 고갈 문제는 아니라고 생각했습니다.- 문제의 원인은 메모리 부족으로 인한 GC Thrashing으로 예상됩니다. 🧐 원인 파악[메모리 부족 원인]애플리케이션 시작 단계에서는 모든 클래스를 한 번에 로딩하고, 모든 Spring Bean을 생성하며, DB 커넥션 풀을 초기화하는 등 메모리 사용량이 피크에 달합니다. 이 시점에서 필요한 메모리가 Docker limit인 1.5GB를 초과하면서 메모리 부족 상태가 발생했습니다.메모리를 확보할 수 없게 된 GC는 계속해서 메모리 확보를 시도하며 CPU의 90% 이상을 소비하게 되고, 이로 인해 애플리케이션 스레드들이 실행될 기회를 얻지 못하는 Thread Starvation 상태에 빠지게 된 것으로 예상됩니다.[ZGC의 문제점]현재 사용 중인 ZGC는 초저지연을 목표로 설계된 GC 알고리즘입니다. 이를 위해 복잡한 메모리 구조를 사용하며, 이 과정에서 heap 크기의 10-20%를 Native Memory로 추가 소비합니다. 현재 너구디의 설정인 1GB heap 기준으로 약 200MB의 Native Memory를 사용하는 것입니다.반면 G1GC는 heap의 약 5%만을 Native Memory로 사용하므로 약 50MB 정도만 필요합니다.따라서 ZGC를 G1GC로 변경하면 약 150MB의 Native Memory를 절약할 수 있습니다.ZGC는 수백 GB 이상의 대용량 heap과 초저지연이 중요한 프로덕션 환경에 적합하지만, 1GB 정도의 작은 heap을 사용하는 너구디 개발 서버에서는 오히려 메모리 오버헤드가 부담이 됩니다. G1GC는 10-50ms의 pause time을 가지지만, 개발 서버에서는 이 정도의 지연은 문제가 되지 않으며, 메모리 효율성이 훨씬 중요하다고 판단했습니다.[애플리케이션 시작 vs 안정화 메모리 차이]docker stats로 확인한 866MB(56%)는 애플리케이션이 시작을 완료하고 안정화된 상태의 메모리 사용량입니다. 하지만 애플리케이션 시작 단계에서는 훨씬 더 많은 메모리가 필요합니다.시작 단계(0-2분)에서는 JVM이 모든 클래스를 메모리에 로딩하고(+200MB), Metaspace를 초기화하며(+150MB), Spring Boot가 모든 Bean을 생성하고(+300MB), DB 커넥션 풀을 초기화하며(+100MB), 캐시를 초기화(+100MB)합니다.이 시점의 피크 메모리 사용량은 1400-1500MB 입니다. 시작이 완료된 후(3분 이후)에는 GC가 불필요한 임시 객체들을 정리하면서 메모리 사용량이 800-900MB로 감소하여 안정화됩니다. 🤔 질문1. GC 알고리즘 선택에 대해1GB 수준의 heap에서 ZGC보다 G1GC가 적합하다고 판단하여 변경했습니다. 이러한 판단이 적절한지 여쭤보고싶습니다. ZGC는 어느 정도 규모의 heap부터 효과적인지 궁금합니다. 2. -Xms = -Xmx 설정에 대해gemini 코드 리뷰에서 "서버 애플리케이션은 초기 힙과 최대 힙을 동일하게 설정하여 힙 확장 오버헤드를 제거하는 것이 좋다"는 의견을 받았습니다.메모리가 빡빡한 상황(여유 100MB)에서 처음부터 1.2GB를 할당하는 것이 안전한 선택이 맞을까요..! 오히려 512MB로 시작해서 필요할 때 늘리는 게 더 안전한것일지 여쭤보고 싶습니다. 3. Docker 메모리 제한과 JVM heap 비율에 대해현재 Docker 1.6GB 중 JVM heap 1.2GB (75%)로 설정했는데, 이 비율이 적절한지 여쭤보고 싶습니다. 일반적으로 권장되는 비율이 있는지 궁금합니다! 4. Native Memory 측정에 대해현재는 관련해서 정리해둔 기술 블로그 등을 통해 (G1GC는 heap의 5%, Metaspace 100MB 등)로 추정했는데, 실제로 정확히 측정하려면 어떻게 해야 하는지 궁금합니다! -XX:NativeMemoryTracking=detail 같은 옵션을 운영 환경에서 사용해도 성능에 영향이 없을까요?! 5. 현업에서의 리소스 관리이런 제한된 리소스 환경을 어떻게 관리하시나요?! 메모리 설정의 기준은 어떻게 정하시는지 궁금합니다! 6. 모니터링 지표Thread Starvation을 사전에 감지하려면 어떤 지표를 모니터링해야 할까요?? 강의 내용과 연결하여 최근에 개발하면서 궁금했던 부분들을 남기게 되었습니다! 초기 스타트업에서 백엔드 개발을 하고 있는데 개발하면서 이슈가 생기면, 강의들을 보기도 하고 구글링을 열심히 하기도 하고 AI와 정말 긴 대화를 나누기도 하면서 원인을 찾고 저희 상황에 제일 적합한 해결책을 찾고있습니다. 하지만 제가 문제 상황을 맞게 파악한건지, 가장 최선의 해결책을 찾은게 맞는지 늘 더 생각하게 되는 것 같습니다. 그리고 스스로의 판단에 확신을 갖기 위해서 더욱 더 많이 공부하고 기반을 탄탄하게 해야함을 느낍니다.Thread Starvation 문제를 겪고 제가 파악하고 해결한 방법이 적합한지, 리소스 관리와 관련해서 현업에서는 어떻게 관리하고 모니터링하는지 여쭤볼 수 있는 분이 주변에 없어서 긴 글을 남기게 되었습니다 🤓..읽어주셔서 감사합니다 :)
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
프로젝트 제안 수행에 대한 조언을 구하고 싶습니다.
안녕하세요. 강사님.한 번 훓어보고 2번째 보고, 코드를 타이핑 + 모르는 내용은 GPT한테 무슨 내용인지 물어보면서 진행하다보니 내용 이해가 술술 되고 있습니다. 그래서 후에 프로젝트 제안 주신 것도 이렇게 저렇게 할 수 있겠구나 생각을 하고 있습니다. 다만 고민되는 부분은 기간입니다. 제안 주신 프로젝트를 전부 수행하는데 2~3달 기간이 소요되는 느낌이 드는데...현재 자바 스프링 백엔드 개발자 목표로 하고 있습니다.현재 해야할 것이 JAVA + 알고리즘 공부 + HTML + DB + Spring 그 이후 필요한 것이 있다면 추가로 공부를 해야하는 데, 네트워크 프로젝트에 시간을 쏟으면 이후 공부가 너무 늦춰질까봐 어떻게 우선순위를 두어야 할지 고민을 하고 있습니다.현재 학원이라는 환경이 공부하기가 너무 좋은데 내년 1월까지만 자습으로 사용이 가능해서 앞서 해야할 걸 다 끝낸 후에 프로젝트를 들어갈지 아니면 주어진 프로젝트를 완수하고 들어갈지 의견을 구해봅니다.(프로젝트를 진행하고 넘어가는 것이 좋다면 그리 할 것 입니다.)
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
컴퓨터가 여러 대 있는 환경에서의 질문입니다.
안녕하세요. 강사님.현재 사용할 수 있는 컴퓨터가 여러대인 학원 자습실에서 학습을 하고 있습니다. 현재 강의 내용이 새롭다보니 강의를 한 번 쭉 훓어보고 본격적으로 학습에 들어가려고 합니다. 질문을 하게 된 계기는전에 소켓프로그래밍 채팅 예제를 할 때, 다른 컴퓨터에서 통신을 알려면 '공유기의 글로벌 IP주소'를 알아야한다고 해서 질문드리게 되었습니다. 여기서 질문 입니다. 노트북은 현재 없으며컴퓨터가 여러 대 있는 환경 / 학원인지라 공유기 정보 및 글로벌 IP 주소를 알 수 없는 상황의 경우에는 이번 강의에서 학습할 예제를 하기 어려운지 미리 알고 싶습니다. (컴퓨터는 다 LAN선으로 꽂혀있고 LAN선의 최종 연결 위치는 보이지 않습니다.) 만약 어렵다면, 대처방안을 어떻게 해야할지도 알고 싶습니다.
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
[자문자답] Windows 11 Evaluation VM Download
VM Windows 다운로드 해야 되는 분들은 참고하세요. 구글링하면 다 나오긴 해요.link(reddit)
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
스타,워크와 같은 디스창 (Disconnected)도 비정상 종료에 대응하는 시스템으로 봐야할까요?
-우아하지 않는 비정상 종료를 보고...랜뽑을 듣고 생각났던 것이 워크3와 스타크래프트의 디스(Disconnected)가 생각이 났습니다. 연결이 불안정한 유저가 누적 60초 동안 응답이 없으면 강퇴되는 시스템인데, 해당 방법이 비정상적인 종료에 대응에 대한 것이 맞는지 궁금해져서 질문드립니다.
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
VMNet에 대한 질문 드립니다.
안녕하세요. 강사님.항상 좋은 강의 감사합니다.복습할 겸 영상을 다시 보고 있는데 이해가 안되는 것이 있어서 질문 드립니다. 게스트 PC 입장에서 VMNet1은 L2 Switch에 연결되어 있는 NIC과 같다고 이해했습니다. 만약 그렇다고 한다면 호스트와 게스트의 IP를 봤을 때 IPv4 주소의 서브넷 마스크에 해당되는 부분은 같아야할 것으로 생각되는데 왜 다른지 이해가 되지 않습니다. 호스트에서 VMNet IP주소가 게이트웨이 주소처럼 되어있는 이유가 뭔지 알 수 있을까요?
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
dispatcher_handler가 호출되는 시점
안녕하세요. 강사님.강의 잘 보고 있습니다.dispatcher_handler가 호출되는 시점이 궁금해서 질문 드립니다.HttpSample 예제를 실행해보면 호스트가 GET 요청할 때만 dispatcher_handler가 호출되는 것처럼 보여서요.wireshark로 http-browse-ok.pcap 파일을 열어보면 GET 외에 서버 응답도 보이는데 왜 이 예제에서 서버에 대한 응답은 출력되지 않는지 궁금합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
수업과 관련해서 읽어볼 만한 책 있나요?
내용은 없음
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
패킷 분석 너무 재밌습니다!!
안녕하세요. 좋은 영상 감사합니다 실습으로 내주신 패킷 분석이 너무 재밌습니다. 덕분에 네트워크에 대해서 깊게 이해가 되는것같네요항상 감사합니다 ^^
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
안녕하세요 선생님 질문이 있습니다~
제가 패킷 캡처 프로그래밍을 하던 중 실제로 프로그래밍을 하는 부분인 packet_handler()함수에서실제로 캡쳐가 된 패킷을 저장하는 변수인 const u_char* pkt_data <- 이 부분이 왜 포인터 변수로 선언이 되어있는지 궁금합니다 알려주시면 감사드리겠습니다~~
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
서버가 끊어버리는것에 대한 질문
11:00 에 클라가 도배를 하면 서버에서 끊어버린다는 내용이 있어서 질문 드립니다. 서버에서 먼저 끊으면 안된다고 하셨는데,도배나 어떤 악질 유저 같은 경우에는 TIME_WAIT 남더라도 끊어버리는것이 맞나요?
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
안녕하세용 선생님 질문이 있습니다~~
저희가 프로토콜의 구조체를 만들 때자료형을 unsigned로 하잖아요~ 근데 굳이 unsigned를 고집을 하는 이유가 음수를 표현을 할 필요가 전혀 없어서죠?? 알려주시면 감사드리겠습니다좋은하루 보내세요~
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
안녕하세요 선생님~~ 질문이 있습니다~~
다름 아니라 제가 인터넷을 찾아보다가 확장자를 .c 즉 c언어로 할 경우외부 include 디렉터리와 외부 라이브러리 디렉터리를저희가 수업에서 진행을 했던 그대로설정을 하면LoadNpcapDlls() 해당 함수를 사용을 하지 않아도프로그램이 문제 없이 작동을 합니다 혹시 위에 외부 include와 라이브러리 디렉터리를올바르게 등록을 하면LoadNpcapDlls()함수 없이 코드를 작성해도 될까요??
-
미해결C# TCP/IP 소켓 프로그래밍
프로젝트가 더 이상 지원되지 않는 .NET 6.0을 대상으로 할 때
안녕하세요-섹션5C# TCP/IP 소켓 프로그래밍 로그인 부분입니다.자료 다운 후 실행 시 아래와 같은 에러가 발생합니다이 때. 프로젝트 우측 클릭 -> 7 & 8 &9버전등으로 빌드 -> 재실행하였으나 동일한데요. 어떤 방향으로 해결하면 좋을까요?
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
프로토콜 헤더 암기
안녕하세요 선생님~~강의 너무 잘 보고있습니다ㅎㅎ근데 프로토콜 헤더는 꼭 전부 외워서 작업을 해야하나요?? 그리고 선생님은 그걸 안보고 프로그래밍을 하실 수 있나요? 조금 개인적인 질문이라 실례가 될수 있는데요알려주시면 감사드리겠습니다ㅎㅎ 감사합니다.
-
미해결C# TCP/IP 소켓 프로그래밍
Tap강의에서 6분9초에 ReceiveAsync에 매개변수 e가 필요하다는 에러
안녕하세요Tap강의에서 6분 9초에 31번째 줄 내용이 궁금합니다. 저는 ReceiveAsync메서드에는 2개 인수를 쓰는 오버로드가 없다고 떠서, 어떻게 수정하면되는지 궁금합니다. -에러나는 내용ReceiveAsync메서드에는 2개 인수를 쓰는 오버로드가 없다 -제가 적은 코드 int n1 = await clientSocket.ReceiveAsync(buffer,SocketFlags.None); --전체 코드 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Net;using System.Net.Sockets;using System.Threading;namespace Server{ class Program { static async Task Main(string[] args) { Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.20.97"), 20000); serverSocket.Bind(endPoint); serverSocket.Listen(1000); //Tap( 작업기반 비동기 패턴) 작업짜기 while(true) { //서버 소켓에 어웨이트 소켓을 써라, 이 함수는 반환값이 <task>socket임 Socket clientSocket = await serverSocket.AcceptAsync(); // 제네릭한 값을 갖는 Task를 await하게하면 제네릭을 반환값으로 가질 수 있음 //스레드 풀에 일감을 던짐 , 즉 Readasync하라는거임 ThreadPool.QueueUserWorkItem(ReadAsync, clientSocket); } } /// <summary> /// 스레드풀에 들어갈 함수 , 클라이언트 소켓이 센더로 들어감 /// </summary> /// <param name="sender"></param> private static async void ReadAsync(object sender) { //클라이언트 소켓이 센더로 들어감 Socket clientSocket = (Socket)sender; //리시브 함수 루프 돌리기 while(true) { byte[] buffer = new byte[256]; int n1 = await clientSocket.ReceiveAsync(buffer,SocketFlags.None); //만약 0바이트면 종료된거니까 자원 해제하고 return으로 함수 종료 if (n1<1) { Console.WriteLine("Client disconnect"); clientSocket.Dispose(); return; } Console.WriteLine(Encoding.UTF8.GetString(buffer)); } } }}
-
미해결C# TCP/IP 소켓 프로그래밍
EAP강의에서 어떻게 여러개 클라이언트를 띄우는지 궁금합니다
제목과 내용이 같습니다.코드를 따라하며 진행중인데, 시연해주실때마다 클라이언트를 여러개 키는 모습을 보여주셨는데, 어떻게 하셨는지 궁금합니다.
-
미해결개발자를 위한 컴퓨터공학 2: 혼자 공부하는 네트워크
ipv6 패킷관찰
ipv6-fragmentation.pcapng 파일에서1,2 번 패킷들은 ip단편화가 일어나지않앗지만 2개의 패킷으로 전송된 이유가 뭔가요 ?
-
미해결개발자를 위한 컴퓨터공학 2: 혼자 공부하는 네트워크
와이어샤크
http 프로토콜의 패킷같은 경우http,tcp ipv4 , eth , rip 등 다양한 프로토콜을 사용하고 있을텐데,이 특정 패킷은 http,tcp,ipv4로 필터링 하면 다 검색이 되는건가요 ?
-
미해결개발자를 위한 컴퓨터공학 2: 혼자 공부하는 네트워크
HTTP 메시지
HTTP 메시지는 패킷의 어느부분에 들어가는건가요 ?