스터디 진행 일시
날짜 : 11월 06일 (목요일) 시간 : 오후 7시 ~ 9시 (2시간) 장소 : 강남 (오프라인) 오늘 함께한 멤버 ❣️ : 준호님 / 은지님 / 요한님 / 유경님 / 소영님/ 근우님
🔧 금주 스터디 일정
- 아이스 브레이킹
- 코루틴과 가상 스레드 (은지님 세미나)
- 슬로우 쿼리는 왜 일어날까?
코루틴과 가상 스레드
🙌 은지님의 세미나 🙌
- 은지님이 정리하신 노션
- JDK 21부터 정식 지원된 기능으로, OS 스레드보다 훨씬 가벼운 사용자 모드 스레드이다.
- 기존 스레드보다 생성 비용이 낮고, 블로킹 호출 시에도 실제 OS 스레드를 점유하지 않는다.
- 그로 인해 DB I/O 대기 중에도 다른 요청 처리가 가능해져, 스레드 고갈 문제를 크게 줄인다.
- 왜 나왔을까?
- Java는 “요청당 스레드(Thread per Request)” 모델을 기반으로 한다.
- 이 구조는 단순하지만, DB나 외부 API 호출처럼 I/O 블로킹이 많은 작업에서는 아래 한계를 가진다.
- 스레드 하나가 블로킹되면 OS 스레드 자원도 함께 대기
- Thread Pool이 금방 포화 상태로 가고, 요청이 밀림
-
비동기 리액티브 프로그래밍(WebFlux 등)은 구조가 복잡하고 유지보수 난이도 높음
- 이런 문제를 해결하기 위해, “비동기 모델의 복잡함 없이 동시성 효율을 높이자”는 목적에서 가상 스레드가 등장했다.비동기의 효율성과 동기 코드의 단순함을 동시에 얻기 위한 해법이다.
- Java는 “요청당 스레드(Thread per Request)” 모델을 기반으로 한다.
- 가상 스레드의 이점
- 가벼운 스레드 생성 비용
- 수천~수만 개 스레드 생성이 가능하며, OS 자원 부담이 거의 없음
- 블로킹 I/O 효율화
- DB나 네트워크 대기 중에도 OS 스레드를 반환해 CPU 낭비를 줄임
- 기존 코드와 호환
- 비동기 리액티브로 전환하지 않아도 동기 코드 그대로 효율 향상
- 직관적 디버깅
- 콜백 지옥 없이 스택트레이스 유지 가능
- 가벼운 스레드 생성 비용
슬로우 쿼리는 왜 일어날까?
- 인덱스가 없거나 잘못된 경우
- WHERE, JOIN, ORDER BY 절에 인덱스가 없으면 풀스캔을 하게 된다.
- 쿼리 구조가 복잡한 경우
- SELECT * 사용, 불필요한 JOIN, 중첩 서브쿼리 등은 실행 계획을 복잡해진다.
- 데이터가 너무 많아진 경우
- 초기에는 빨랐던 쿼리도 데이터가 수백만 건을 넘으면 달라진다.
- GROUP BY, ORDER BY, DISTINCT 같은 연산은 특히 부담이 커진다.
슬로우 쿼리, 어떻게 해결할 수 있을까?
- 실행 계획 확인 (EXPLAIN, EXPLAIN ANALYZE)
- 먼저 쿼리가 실제로 어떤 인덱스를 타고, 얼마나 많은 데이터를 읽는지 확인한다.
- 인덱스 재설계
- 조회 조건, 정렬, JOIN 키 컬럼에 맞게 인덱스를 설계한다.
- 불필요한 인덱스는 삭제 (쓰기 성능 저하 방지)
- 자주 쓰이는 조건에 맞게 커버링 인덱스(covering index) 고려
- 불필요한 연산 제거
- SELECT * 대신 필요한 컬럼만 조회
- 중첩된 서브쿼리 대신 JOIN 또는 CTE로 단순화
- 중복된 ORDER BY, GROUP BY 최소화