✍️
dodeon
  • 개발왕, 도던
  • 스프링 시큐리티 인 액션
    • 오늘날의 보안
    • 안녕! 스프링 시큐리티
    • 사용자 관리
    • 암호 처리
    • 인증 구현
    • 실전: 작고 안전한 웹 애플리케이션
    • 권한 부여 구성: 액세스 제한
    • 권한 부여 구성: 제한 적용
    • 필터 구현
    • CSRF 보호와 CORS 적용
    • 실전: 책임의 분리
    • OAuth 2가 동작하는 방법
    • OAuth 2: 권한 부여 서버 구현
  • 스프링 고급편
    • 스레드 로컬
    • 템플릿 메서드 패턴과 콜백 패턴
    • 프록시 패턴과 데코레이터 패턴
  • 스프링 입문
    • 프로젝트 환경설정
    • 스프링 웹 개발 기초
    • 회원 관리 예제 - 백엔드
    • 스프링 빈과 의존 관계
    • 회원 관리 예제 - MVC
    • 스프링 DB 접근 기술
      • JDBC
      • JPA
    • AOP
  • 스프링 핵심 원리
    • 객체 지향 설계와 스프링
      • 스프링의 탄생
      • 객체 지향 프로그래밍
      • 좋은 객체 지향 설계의 원칙
      • 객체 지향 설계와 스프링
    • 스프링 핵심 원리 이해
      • 회원 도메인 개발
      • 주문 도메인 개발
    • 객체 지향 원리 적용
      • 관심사의 분리
      • 새로운 구조와 정책 적용
      • 정리
      • IoC, DI, 컨테이너
      • 스프링으로 전환하기
    • 스프링 컨테이너와 스프링 빈
      • 스프링 빈 기본 조회
      • 동일 타입이 둘 이상일 때 조회
      • 상속일 때 조회
      • BeanFactory와 ApplicationContext
      • 다양한 설정 형식
      • 스프링 빈 설정 메타 데이터
    • 싱글턴 컨테이너
      • @Configuration과 싱글턴
    • 컴포넌트 스캔
      • 탐색 위치와 기본 탐색 대상
      • 필터와 중복 등록
    • 의존 관계 자동 주입
      • 롬복과 최신 트렌드
      • 조회 빈이 2개 이상일 때
      • 애너테이션 직접 만들기
      • 조회한 빈이 모두 필요할 때
      • 올바른 실무 운영 기준
    • 빈 생명 주기 콜백
      • 인터페이스 방식
      • 메서드 지정 방식
      • 애너테이션 방식
    • 빈 스코프
      • 프로토타입 스코프
      • Provider
      • 웹 스코프
  • 스프링 MVC
    • 웹 애플리케이션 이해
      • 서버
      • 서블릿
      • 멀티 스레드
      • HTML, HTTP API, CSR, SSR
      • 자바 백엔드 웹 기술 역사
    • 서블릿
      • HttpServletRequest
      • HTTP 요청 데이터
      • HttpServletResponse
      • HTTP 응답 데이터
    • 서블릿, JSP, MVC 패턴
      • 서블릿으로 만들기
      • JSP로 만들기
      • MVC 패턴
    • MVC 프레임워크 만들기
      • 프론트 컨트롤러 패턴
      • View 분리
      • Model 추가
      • 단순하고 실용적인 컨트롤러
      • 유연한 컨트롤러
      • 정리
    • 스프링 MVC의 구조 이해
      • 스프링 MVC 전체 구조
      • 핸들러 매핑과 핸들러 어댑터
      • 뷰 리졸버
      • 스프링 MVC 시작하기
      • 스프링 MVC 컨트롤러 통합
      • 스프링 MVC 실용적인 방식
    • 스프링 MVC 기본 기능
      • 프로젝트 생성
      • 로깅
      • 요청 매핑
      • HTTP 요청의 기본 및 헤더 조회
      • HTTP 요청 파라미터
      • HTTP 요청 메시지
      • HTTP 응답
      • HTTP 메시지 컨버터
      • 요청 매핑 핸들러 어댑터
    • 스프링 MVC 웹 페이지 만들기
    • 메시지, 국제화
      • 스프링 메시지 소스
    • Validation
      • BindingResult
      • FieldError, ObjectError
      • 오류 코드와 메시지 처리
      • Validator 분리
    • Bean Validation
      • Form 전송 객체 분리
      • HTTP 메시지 컨버터
    • 로그인
      • 쿠키
      • 세션
      • 서블릿 HTTP 세션
      • 서블릿 필터
      • 스프링 인터셉터
      • ArgumentResolver 활용
    • 예외 처리와 오류 페이지
      • 오류 화면 제공
      • 필터
      • 인터셉터
      • 스프링 부트 오류 페이지
    • API 예외 처리
      • 스프링 부트 기본 오류 처리
      • HandlerExceptionResolver
      • ExceptionResolver
      • ControllerAdvice
    • 스프링 타입 컨버터
      • Converter
      • ConversionService
      • 뷰 템플릿에 적용하기
      • Formatter
    • 파일 업로드
      • 서블릿과 파일 업로드
      • 스프링과 파일 업로드
      • 파일 업로드 및 다운로드 예제
  • 자바 ORM 표준 JPA 프로그래밍
    • JPA 소개
    • JPA 시작하기
    • 영속성 관리
      • 영속성 컨텍스트
      • 플러시
      • 준영속 상태
    • Entity 매핑
      • 객체와 테이블 매핑
      • 데이터베이스 스키마 자동 생성
      • 필드와 칼럼 매핑
      • 기본 키 매핑
      • 실전 예제
    • 연관 관계 매핑
      • 단방향 연관 관계
      • 양방향 연관 관계
      • 실전 예제
    • 다양한 연관 관계 매핑
      • 다대일
      • 일대다
      • 일대일
      • 다대다
      • 실전 예제
    • 고급 매핑
      • 상속 관계 매핑
      • 매핑 정보 상속
      • 실전 예제
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이와 고아 객체
      • 실전 예제
    • 값 타입
      • 기본값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교
      • 값 타입 컬렉션
      • 실전 예제
    • 객체 지향 쿼리 언어 - 기본
      • 기본 문법과 쿼리 API
      • 프로젝션
      • 페이징
      • 조인
      • 서브 쿼리
      • JPQL 타입 표현과 기타 식
      • 조건식
      • JPQL 함수
    • 객체 지향 쿼리 언어 - 중급
      • 경로 표현식
      • fetch join
      • 다형성 쿼리
      • Entity 직접 사용
      • Named 쿼리
      • 벌크 연산
  • 스프링 부트와 JPA 활용 - 웹 애플리케이션 개발
    • 프로젝트 환경설정
    • 도메인 분석 설계
      • 도메인 분석 설계
      • Entity 클래스 개발
      • Entity 설계 시 주의점
    • 애플리케이션 아키텍처
    • 회원 도메인 개발
    • 상품 도메인 개발
    • 주문 도메인 개발
      • Entity, 리포지토리, 서비스 개발
      • 주문 기능 테스트
      • 주문 검색 기능 개발
    • 웹 계층 개발
      • 변경 감지와 병합
  • 스프링 부트와 JPA 활용 - API 개발과 성능 최적화
    • API 개발 기본
      • 회원 등록 API
      • 회원 수정 API
      • 회원 조회 API
    • 지연 로딩과 조회 성능 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환
      • JPA에서 DTO 직접 조회
    • 컬렉션 조회 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환: 페치 조인
      • Entity를 DTO로 변환: 페이징과 한계 돌파
      • DTO 직접 조회
      • DTO 직접 조회: 컬렉션 조회 최적화
      • DTO 직접 조회: 플랫 데이터 최적화
      • 정리
    • OSIV와 성능 최적화
  • 스프링 데이터 JPA
    • 예제 도메인 모델
    • 공통 인터페이스 기능
      • 순수 JPA 기반 리포지토리
      • 공통 인터페이스 설정
    • 쿼리 메서드 기능
      • JPA Named Query
      • @Query
      • 파라미터 바인딩
      • 반환 타입
      • 페이징과 정렬
      • 벌크성 수정 쿼리
      • @EntityGraph
      • JPA Hint & Lock
    • 확장 기능
      • 사용자 정의 리포지토리
      • Auditing
      • Web 확장
    • 스프링 데이터 JPA 분석
    • 나머지 기능
      • Specifications
      • Query By Example
      • Projections
      • Native Query
  • Querydsl
    • 프로젝트 환경 설정
    • 예제 도메인 모델
    • 기본 문법
      • JPQL vs Querydsl
      • Q-Type 활용
      • 검색 조건
      • 결과 조회
      • 정렬
      • 페이징
      • 집합 함수
      • 조인
      • 서브 쿼리
      • Case 문
      • 상수, 문자 더하기
    • 중급 문법
      • 프로젝션과 결과 반환
      • 동적 쿼리
      • 수정, 삭제 벌크 연산
      • SQL Function 호출
    • 순수 JPA와 Querydsl
      • 순수 JPA 리포지토리와 Querydsl
      • 동적 쿼리와 성능 최적화 조회
      • 조회 API 컨트롤러 개발
    • 스프링 데이터 JPA와 Querydsl
      • 스프링 데이터 페이징 활용
      • 스프링 데이터 JPA가 제공하는 Querydsl 기능
  • 데이터 접근 핵심 원리
    • JDBC 이해
      • JDBC와 최신 데이터 접근 기술
      • 데이터베이스 연결
      • JDBC 개발
  • 백엔드 시스템 실무
    • CPU bound 애플리케이션
      • CPU를 극단적으로 사용하는 애플리케이션
      • 스트레스 테스트 툴로 성능 측정
      • Dockerized 애플리케이션 GCP 배포
      • Jenkins를 이용한 배포
    • CPU bound 애플리케이션 무중단 배포
      • nginx를 통한 로드밸런싱 구성
      • 서버를 늘려서 성능 측정
    • 배포 자동화와 협업을 위한 Git
      • GitHub Webhook과 jenkins로 배포 자동화
      • 머지할 때 발생하는 충돌 해결하기
      • 실무에서 유용한 Git 꿀팁
    • I/O bound 애플리케이션
    • Message Queue를 도입하여 데이터 유실 방지
      • 스트레스 테스트
    • 검색과 분석을 위한 저장소 ElasticSearch
    • Kubernetes
  • 모든 개발자를 위한 HTTP 웹 기본 지식
    • 인터넷 네트워크
      • IP
      • TCP, UDP
      • PORT
      • DNS
    • URI와 웹 브라우저 요청 흐름
    • HTTP 기본
      • 클라이언트-서버 구조
      • stateful, stateless
      • 비 연결성
      • HTTP 메시지
    • HTTP 메서드
    • HTTP 메서드 활용
    • HTTP 상태 코드
    • HTTP 헤더 - 일반
      • 표현
      • 콘텐츠 협상
      • 전송 방식
      • 정보
      • Authorization
      • 쿠키
    • HTTP 헤더 - 캐시
      • 검증 헤더와 조건부 요청
      • 조건부 요청 헤더
      • 프록시 캐시
      • 캐시 무효화
  • 김영한의 실전 자바
    • 제네릭
  • 예제로 배우는 스프링 입문
    • 예제로 배우는 스프링 입문(개정판)
      • PetClinic 예제
      • 스프링 IoC
      • 스프링 AOP
      • 스프링 PSA
  • 스프링 프레임워크 핵심 기술
    • 스프링 프레임워크 핵심 기술
      • IoC 컨테이너와 빈
        • 스프링 IoC 컨테이너와 빈
        • ApplicationContext와 빈 설정
        • @Autowired
        • @Component와 컴포넌트 스캔
        • 빈의 스코프
        • Environment
        • MessageSource
        • ApplicationEventPublisher
        • ResourceLoader
      • Resource/Validation
        • Resource 추상화
        • validation 추상화
      • 데이터 바인딩 추상화
      • SpEL
      • 스프링 AOP
      • Null-Safety
  • 스프링 부트 개념과 활용
    • 스프링 부트 원리
      • 자동 설정
      • 내장 서버
        • 컨테이너와 서버 포트
        • HTTPS와 HTTP2
      • 독립적으로 실행 가능한 JAR
    • 스프링 부트 활용
      • Spring Application
      • 외부 설정
      • 프로파일
      • 로깅
      • 테스트
      • Spring Boot Devtools
    • 스프링 웹 MVC
      • 소개
      • HttpMessageConverters
      • ViewResolver
      • 정적 리소스
      • 웹 JAR
      • index 페이지와 파비콘
      • ExceptionHandler
      • Spring HATEOAS
      • CORS
  • THE JAVA
    • JVM 이해하기
      • 자바, JVM, JDK, JRE
      • JVM 구조
      • 클래스 로더
      • Heap
      • Garbage Collector
    • 리플렉션
      • 클래스 정보 조회
  • The Java - Test
    • JUnit 5
      • JUnit 시작하기
      • JUnit 시작하기
    • Mockito
Powered by GitBook
On this page
  • 스레드
  • 단일 스레드
  • 단일 요청
  • 다중 요청
  • 다중 스레드
  • 요청마다 스레드 생성
  • 스레드 풀
  • 실무 팁
  • 스레드 풀의 적정 숫자
  • WAS의 멀티 스레드 지원

Was this helpful?

  1. 스프링 MVC
  2. 웹 애플리케이션 이해

멀티 스레드

Previous서블릿NextHTML, HTTP API, CSR, SSR

Last updated 3 years ago

Was this helpful?

브라우저가 요청을 보내면 WAS가 응답을 한다. 요청을 했을 때 TCP 커넥션이 연결되면서 서블릿이 호출된다.

그런데 이 서블릿 객체는 누가 호출하는 걸까? 바로 스레드다.

스레드

  • 애플리케이션 코드를 하나하나 순차적으로 실행한다.

  • 자바 메인 메서드를 처음 실행하면 main이라는 이름의 스레드가 실행된다.

  • 스레드가 없다면 자바 애플리케이션 실행이 불가능하다.

  • 스레드는 한 번에 하나의 코드 라인만 수행한다.

  • 동시 처리가 필요하면 스레드를 추가로 만들어야 한다.

단일 스레드

스레드가 하나만 있다고 가정해보자.

단일 요청

요청이 오면 스레드를 할당한다. 이 스레드를 가지고 서블릿을 실행한다.

다 실행하고 나면 응답을 보낸다.

다중 요청

요청 1이 들어와서 스레드를 사용해 서블릿을 요청한다. 여러 가지 이유로 인해 처리에 시간이 많이 걸린다고 해보자.

이때 요청 2가 들어오면 스레드를 사용할 수 있을 때까지 기다린다. 이렇게 되면 둘 다 죽게된다. 1번이 잡고 있으니 2번이 실행 자체를 못하게 되고 결국 타임 아웃이 발생하는 것이다.

다중 스레드

문제를 해결하려면 요청마다 스레드를 생성하면 된다.

요청마다 스레드 생성

요청 1이 들어오고 처리가 지연되어도 요청 2가 오면 새로 스레드를 만든다. 같은 서블릿을 호출해도 스레드는 다르기 때문에 각 스레드대로 요청을 처리하고 응답을 보낸다. 응답이 끝나면 스레드를 날린다.

장점

  • 동시 요청을 처리할 수 있다.

  • 리소스(CPU, 메모리)가 허용할 때까지 처리할 수 있다.

  • 하나의 스레드가 지연되어도 나머지 스레드는 정상 동작한다.

단점

  • 스레드는 생성 비용이 매우 비싸다.

    • 고객 요청이 올 때마다 스레드를 생성하면 응답 속도가 늦어진다.

  • 스레드는 컨텍스트 스위칭 비용이 발생한다.

    • 스레드는 코어 수만큼 동시에 돌아간다.

      • 2개라고 치면 사실 둘은 동시에 수행하는 게 아니라 번갈아가면서 수행한다.

      • 너무 빨라서 동시에 한다고 느껴지는 것 뿐이다.

    • 이 두 개를 전환할 때 비용이 발생하는데 이것을 컨텍스트 스위칭 비용이라고 한다.

    • 스레드가 많아지면 이 비용 자체가 점점 커지게 된다.

  • 스레드 생성에 제한이 없다.

    • 고객의 요청이 너무 많이 오면 CPU와 메모리 임계점을 넘어서 서버가 죽을 수 있다.

스레드 풀

요청마다 생성하는 단점을 보완해 스레드 풀 안에 스레드를 미리 만들어놓고 쓰는 방법이다.

요청이 오면 스레드 풀에서 스레드를 가져다 쓴다. 200개니까 2개가 줄어 198개가 된다. 응답을 보내고 나면 스레드를 다시 반납해서 200개로 돌아간다.

만약 200개보다 더 많은 요청이 온다면 추가적인 요청들은 대기하고 있다가 200개 중에 응답을 보내고 반납한 스레드를 사용할 수 있다. 그래도 감당하기 힘들면 거절을 하기도 한다.

특징

  • 필요한 스레드를 스레드 풀에 보관하고 관리한다.

  • 스레드 풀에 생성 가능한 스레드의 최대치를 관리한다.

    • 톰캣은 최대 200개가 기본 설정이며 변경 가능하다.

  • 스레드가 필요하면 이미 생성되어있는 스레드를 스레드 풀에서 꺼내 사용한다.

  • 사용을 종료하면 스레드 풀에 해당 스레드를 반납한다.

  • 최대 스레드가 모두 사용중이어서 스레드 풀에 스레드가 없다면?

    • 기다리는 요청은 거절하거나 특정 숫자만큼만 대기하도록 설정할 수 있다.

장점

  • 스레드가 미리 생성되어 있어 스레드를 생성, 종료하는 비용(CPU)이 절약되고 응답 시간이 빠르다.

  • 생성 가능한 스레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.

    • 물론 너무 많은 요청이 들어오면 클라이언트에선 계속 연결이 안되겠지만 성공한 사람은 어찌저찌 내부에서 로직이 돌아간다.

실무 팁

  • WAS의 주요 튜닝 포인트는 최대 스레드 수이다.

  • 값을 너무 낮게 설정하면?

    • 동시 요청이 많을 때 서버 리소스는 여유롭지만 클라이언트는 금방 응답이 지연된다.

  • 값을 너무 높게 설정하면?

    • 동시 요청이 많으면 CPU, 메모리 리소스 임계점 초과로 서버가 다운된다.

  • 장애가 발생하면?

    • 클라우드라면 일단 서버부터 늘리고 이후에 튜닝한다.

    • 클라우드가 아니면 열심히 튜닝한다.

스레드 풀을 너무 낮게 설정했을 경우 가능한 스레드의 100개의 요청이 온다면 90개가 대기한다. 리소스를 확인하면 CPU를 5%로만 사용하고 있다고 나온다.

안에서 10개만 정상적으로 수행되고 요청은 계속 쌓인다. 내가 처리하는건 10개인데 요청은 더 많으니 밀리면서 장애가 발생한다. WAS는 살아있어도 서버 전체는 장애가 난다.

사실 이럴 경우 못해도 CPU를 50%는 써줘야 한다. 설정 하나만 잘해줘도 늘어나는데 잘못해서 5%밖에 못쓴다고 인스턴스를 늘리고 있으면 돈만 그만큼 나간다.

스레드 풀의 적정 숫자

  • 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다.

  • 최대한 실제 서비스와 유사하게 성능 테스트를 시도하자.

    • 아파치 ab, 제이미터, nGrinder

WAS의 멀티 스레드 지원

  • 멀티 스레드에 대한 부분은 WAS가 처리한다.

  • 개발자가 멀티 스레드 관련 코드를 신경쓰지 않아도 된다.

  • 개발자는 마치 싱글 스레드 프로그래밍을 하듯 편리하게 소스 코드를 개발한다.

  • 멀티 스레드 환경이므로 싱글턴 객체(서블릿, 스프링 빈)은 주의해서 사용한다.