스터디 진행 일시
날짜 : 11월 06일 (목요일) 시간 : 오후 7시 ~ 9시 (2시간) 장소 : 강남 (오프라인) 오늘 함께한 멤버 ❣️ : 준호님 / 은지님 / 요한님 / 유경님 / 소영님/ 근우님


🔧 금주 스터디 일정
  • 아이스 브레이킹
  • 코루틴과 가상 스레드 (은지님 세미나)
  • 슬로우 쿼리는 왜 일어날까?


코루틴과 가상 스레드

🙌 은지님의 세미나 🙌


  • JDK 21부터 정식 지원된 기능으로, OS 스레드보다 훨씬 가벼운 사용자 모드 스레드이다.
  • 기존 스레드보다 생성 비용이 낮고, 블로킹 호출 시에도 실제 OS 스레드를 점유하지 않는다.
    • 그로 인해 DB I/O 대기 중에도 다른 요청 처리가 가능해져, 스레드 고갈 문제를 크게 줄인다.
  • 왜 나왔을까?
    • Java는 “요청당 스레드(Thread per Request)” 모델을 기반으로 한다.
      • 이 구조는 단순하지만, DB나 외부 API 호출처럼 I/O 블로킹이 많은 작업에서는 아래 한계를 가진다.
    • 스레드 하나가 블로킹되면 OS 스레드 자원도 함께 대기
    • Thread Pool이 금방 포화 상태로 가고, 요청이 밀림
    • 비동기 리액티브 프로그래밍(WebFlux 등)은 구조가 복잡하고 유지보수 난이도 높음

    • 이런 문제를 해결하기 위해, “비동기 모델의 복잡함 없이 동시성 효율을 높이자”는 목적에서 가상 스레드가 등장했다.비동기의 효율성과 동기 코드의 단순함을 동시에 얻기 위한 해법이다.
  • 가상 스레드의 이점
    • 가벼운 스레드 생성 비용
      • 수천~수만 개 스레드 생성이 가능하며, 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 최소화