스터디용 심화 Q&A
질문: 정적 리소스 요청이 90%이고, 나머지 10%만 주문/결제 같은 동적 요청이라면 웹 서버와 WAS를 왜 굳이 분리할까? 그냥 WAS 하나로 다 처리하면 안 되나?
답변: 가능은 하지만, 분리했을 때 운영상 이점이 크다. 정적 리소스는 계산이 거의 필요 없어서 웹 서버가 빠르고 안정적으로 처리할 수 있고, WAS는 비즈니스 로직에 집중할 수 있다. 이렇게 분리하면 정적 트래픽이 급증할 때는 웹 서버만 늘리고, 동적 요청이 늘 때는 WAS만 증설할 수 있어 자원 활용이 효율적이다. 또 WAS 장애 시 웹 서버가 에러 페이지나 기본 정적 페이지를 대신 제공할 수 있어 장애 대응도 유리하다.
질문: “WAS도 정적 파일을 줄 수 있는데 왜 웹 서버가 따로 필요하냐”는 질문에 어떻게 답할까?
답변: WAS도 정적 파일 제공은 가능하지만, 핵심 강점은 애플리케이션 로직 처리다. 정적 리소스까지 WAS가 전부 담당하면, 로직 처리에 써야 할 자원이 단순 파일 응답에 소모된다. 결국 기능적으로 “할 수 있느냐”보다, 아키텍처적으로 “어디에 집중시키는 게 맞느냐”의 문제다. 실무에서는 역할 분리를 통해 성능, 확장성, 운영 편의성을 같이 가져간다.
질문: 서블릿이 싱글톤처럼 관리된다는 말은 정확히 어떤 의미고, 왜 멤버 변수를 조심해야 할까?
답변: 서블릿은 요청마다 새 객체를 만드는 게 아니라, 보통 하나의 인스턴스를 여러 요청이 공유해서 사용한다는 뜻이다. 문제는 동시에 여러 스레드가 같은 객체에 접근한다는 점이다. 이때 멤버 변수에 사용자별 상태를 저장하면 요청 간 데이터가 섞이거나 덮어써질 수 있다. 그래서 서블릿이나 스프링 빈에서는 요청별 데이터는 지역 변수, 파라미터, 별도 스코프 객체로 다루고, 공유 상태는 신중하게 설계해야 한다.
질문: “개발자는 싱글 스레드처럼 코딩하면 된다”는 말은 맞는 말일까?
답변: 반은 맞고 반은 틀리다. WAS가 스레드 생성과 관리 자체를 대신해주기 때문에 개발자가 직접 스레드를 만들 일은 많지 않다. 하지만 실행 환경 자체는 멀티스레드이므로, 코드가 공유 자원에 접근할 때 동시성 문제를 항상 의식해야 한다. 즉, 스레드 생성 책임은 줄었지만 멀티스레드 환경이라는 사실이 사라진 것은 아니다.
질문: 요청마다 새 스레드를 만들면 동시 처리가 더 잘될 것 같은데, 왜 스레드 풀이 필요한가?
답변: 요청마다 새 스레드를 만드는 방식은 처음엔 단순해 보이지만, 실제로는 생성 비용과 컨텍스트 스위칭 비용이 크고, 요청이 몰리면 스레드 수가 폭증하면서 CPU와 메모리를 빠르게 소모한다. 결국 시스템 전체가 느려지거나 다운될 수 있다. 스레드 풀은 미리 제한된 수의 스레드를 만들어 재사용하기 때문에 성능과 안정성을 동시에 확보한다. 핵심은 “무한 동시성”이 아니라 “통제된 동시성”이다.
질문: Max Thread 값을 크게 잡으면 무조건 좋은가?
답변: 아니다. 너무 작으면 처리량이 낮아지고 요청 대기가 길어지지만, 너무 크면 오히려 CPU 문맥 전환 비용과 메모리 사용량이 늘어나 전체 성능이 나빠질 수 있다. 특히 DB 커넥션 수, 외부 API 응답 속도, 비즈니스 로직의 무거움까지 함께 고려해야 한다. 결국 적정 스레드 수는 시스템 전체 병목을 기준으로 잡아야 하고, AB나 JMeter 같은 도구로 부하 테스트를 하며 튜닝해야 한다.
질문: SSR과 CSR 중 어떤 방식이 더 좋다고 말할 수 있을까?
답변: 절대적으로 더 좋은 방식은 없다. SSR은 서버가 완성된 HTML을 내려주기 때문에 초기 화면 구성과 SEO 측면에서 유리하다. 반면 CSR은 클라이언트가 API를 통해 데이터를 받아 화면을 구성하므로 사용자 상호작용이 많은 앱형 UI에 유리하다. 결국 서비스 특성에 따라 선택해야 한다. 예를 들어 검색 노출이 중요한 콘텐츠 서비스라면 SSR이 유리하고, 관리자 페이지나 복잡한 대시보드라면 CSR이 더 잘 맞는다.
질문: 같은 기능이라도 “동적 HTML”로 줄지 “HTTP API(JSON)”로 줄지는 어떤 기준으로 나눌까?
답변: 서버가 화면까지 책임질지, 데이터만 책임질지가 기준이다. 서버가 최종 HTML을 만들어 내려주면 동적 HTML이고, 화면 구성은 프론트엔드가 맡고 서버는 데이터만 주면 HTTP API다. 최근에는 웹, 앱, 외부 시스템 등 다양한 클라이언트를 지원해야 해서 API 중심 구조가 많아졌지만, 관리자 페이지나 단순한 서버 렌더링 화면은 동적 HTML이 더 생산적일 수 있다.
질문: 스프링 MVC가 오래 살아남은 이유를 단순히 “유명해서” 말고 구조적으로 설명해보면?
답변: 스프링 MVC는 서블릿 기반의 안정성과 MVC 패턴의 역할 분리를 결합했고, 어노테이션 기반으로 개발 생산성까지 높였다. 즉, 저수준 HTTP 처리 위에 일관된 프로그래밍 모델을 제공해 복잡도를 크게 줄여준 것이다. 실무 입장에서는 성숙한 생태계, 검증된 운영 경험, 방대한 레퍼런스까지 갖췄기 때문에 팀 단위 개발과 유지보수에 매우 강하다. 단순히 인기의 문제가 아니라, 기술적 안정성과 조직 생산성이 함께 검증된 결과라고 볼 수 있다.
질문: Spring Boot에서 JAR 배포가 보편화된 이유를 WAR 방식과 비교해서 설명해보면?
답변: WAR 방식은 외부 WAS 설치와 설정, 배포 환경 관리가 필요해서 운영 복잡도가 높았다. 반면 Spring Boot는 내장 톰캣을 포함한 실행형 JAR를 제공해서 “애플리케이션과 실행 환경”을 함께 묶어 배포할 수 있다. 이 방식은 개발 환경과 운영 환경 차이를 줄이고, 실행 방법도 단순해진다. 그래서 현대적인 배포, 특히 컨테이너 환경과도 잘 맞는다.
질문: 트래픽이 갑자기 급증했는데 CPU보다 DB가 먼저 버거워진다면, WAS 스레드 수만 늘리는 게 해결책일까?
답변: 아니다. 이 경우 병목은 애플리케이션 서버가 아니라 DB일 가능성이 크다. WAS 스레드만 늘리면 DB로 동시에 들어가는 요청 수도 더 늘어나서 오히려 전체 장애를 키울 수 있다. 성능 문제는 항상 가장 느린 지점을 기준으로 봐야 한다. 즉, 스레드 수 조정은 만능 해법이 아니라, DB 커넥션 풀, 쿼리 튜닝, 캐시, 읽기/쓰기 분리 같은 전체 시스템 관점과 함께 봐야 한다.
질문: WebFlux 같은 리액티브 기술이 있는데도, 왜 많은 서비스가 여전히 Spring MVC를 쓰는 걸까?
답변: 리액티브는 높은 동시성과 비동기 논블로킹 처리에서 강점이 있지만, 모든 서비스가 그 복잡성을 감수할 만큼 이득을 보지는 않는다. 일반적인 CRUD 중심 서비스는 Spring MVC만으로도 충분히 안정적이고 생산적이다. 즉 기술 선택은 “최신 기술인가”보다 “문제에 비해 복잡도가 정당한가”로 봐야 한다. WebFlux는 특정 상황에 매우 강력하지만, 기본 선택지가 무조건 되지는 않는다.