Spring과 Spring Boot 그리고 동작 순서

Sang_WJ·2025년 4월 15일
post-thumbnail

Spring VS Spring Boot

항목Spring FrameworkSpring Boot
목적유연하고 확장성 높은 프레임워크 제공설정 없이 빠르게 개발 가능하게 지원
설정XML 또는 Java Config로 수많은 설정 필요자동 설정 제공 (@SpringBootApplication)
웹 서버외부 톰캣 필요 (war 파일 배포)내장 웹 서버 포함 (jar 실행만으로 동작)
의존성개발자가 직접 필요한 의존성을 조합스타터(Starter)로 의존성 묶음 자동 제공
예시Spring + 외부 Tomcat + web.xml 등java -jar로 실행만 하면 서버 실행됨

즉, Spring은 유연하지만 설정이 복잡하고 Spring Boot는 내장톰켓 + 자동설정으로 빠른 개발이 가능하다.

  • Spring Boot는 Spring을 “더 쉽고 빠르게” 쓰기 위한 도구
  • 복잡한 설정은 없애고, 개발자가 비즈니스 로직에 집중할 수 있게 도와주는 프레임워크

Spring Boot Application 동작 순서

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

1️⃣ 애플리케이션 시작

  • main() 메서드 실행
  • SpringApplication.run() 호출 → 내부적으로 SpringApplication 객체 생성 및 실행

2️⃣ SpringApplication 객체 초기화

  • 어떤 타입의 애플리케이션인지 판단 (웹인지, CLI인지 등)
  • ApplicationContext 전략 결정 (ex: AnnotationConfigServletWebServerApplicationContext)
  • 로깅 시스템 초기화 (Logback, Log4j 등)

3️⃣ @SpringBootApplication 스캔

  • @SpringBootApplication은 내부적으로 다음 3개를 포함
    • @SpringBootConfiguration: @Configuration과 동일, 설정 클래스 역할
    • @EnableAutoConfiguration: 자동 설정 활성화
    • @ComponentScan: 현재 패키지부터 하위 컴포넌트들(@Component, @Service 등) 스캔

4️⃣ Environment 생성 및 초기화

  • application.properties 또는 application.yml 로드
  • OS 환경 변수, JVM 옵션 등과 통합한 Environment 객체 생성

5️⃣ ApplicationContext 생성 및 구성

  • 스프링의 핵심인 ApplicationContext를 생성
  • 앞에서 로드한 설정을 바탕으로 빈(bean) 등록 시작
  • @Component, @Service, @Repository, @Controller, @Configuration 등 모두 등록

6️⃣ Auto Configuration 수행

  • @EnableAutoConfiguration 덕분에 spring.factories 안의 설정 클래스들 자동 등록
    • 예: spring-boot-starter-web을 의존성으로 넣었다면

→ DispatcherServlet, Tomcat, Jackson 등이 자동으로 설정됨


7️⃣ ApplicationRunner / CommandLineRunner 실행

  • 빈으로 등록된 ApplicationRunner 또는 CommandLineRunner 구현 클래스가 있다면 여기서 실행됨
  • 주로 초기 데이터 셋업, 테스트용 코드 등에 사용
@Component
public class TestRunner implements CommandLineRunner {
    public void run(String... args) {
        System.out.println("애플리케이션 실행 후 초기 작업 수행!");
    }
}

8️⃣ 내장 웹 서버 실행

  • 내장 톰캣 (또는 Jetty, Undertow)이 실행됨
  • 웹 서버가 포트를 열고 HTTP 요청을 받을 준비 완료

9️⃣ 애플리케이션 실행 완료

  • 사용자 요청을 받을 수 있는 상태로 진입
  • 이 시점 이후부터 컨트롤러나 REST API가 동작함

🔁 간단히 도식으로 요약

main()
  ↓
SpringApplication.run()
  ↓
SpringApplication 초기화
  ↓
@Configuration, @ComponentScan, @EnableAutoConfiguration
  ↓
Environment 설정
  ↓
ApplicationContext 생성
  ↓
빈 등록 및 Auto Configuration
  ↓
웹 서버 실행 (Tomcat 등)
  ↓
요청 대기 및 서비스 시작

Spring Boot 동작 순서(TCP/IP 부터)

🧭 전체 흐름 개요

[Client] → [TCP/IP Layer] → [HTTP Layer] → [Tomcat] → [Servlet] → [Spring DispatcherServlet] → [Controller]

🧩 1. 클라이언트가 요청을 보냄

브라우저나 Postman에서 예를 들어 다음과 같이 요청했다고 하자:

GET /hello HTTP/1.1
Host: myserver.com
User-Agent: Chrome

🧩 2. TCP/IP 계층 (OS 레벨)

🧱 클라이언트 → 서버로 TCP 연결 시도

  • 클라이언트가 myserver.com:8080 으로 TCP 3-way handshake
SYN → SYN-ACK → ACK

🧱 서버 (Spring Boot 애플리케이션 실행 중)

  • 내장 톰캣이 8080 포트 열고 ServerSocket 으로 대기 중
  • TCP 커널 계층에서 해당 포트로 연결을 accept

🧩 3. HTTP Layer (Tomcat 처리)

🧾 HTTP 요청은 사실 TCP 바이트 스트림 속에 들어있음

예: 아래처럼 raw byte 데이터가 도착

GET /hello HTTP/1.1\r\n
Host: myserver.com\r\n
User-Agent: Chrome\r\n
\r\n

🧰 톰캣의 Http11InputBuffer가 이 바이트들을 읽고 → HTTP 요청 객체 생성

  • 이 객체는 HttpServletRequest 타입
  • 또한 응답 객체 HttpServletResponse 도 생성됨

🧩 4. 톰캣이 서블릿으로 전달

  • Tomcat이 최종적으로 호출하는 핵심 객체는 DispatcherServlet
  • DispatcherServlet은 Spring에서 등록한 Front Controller 패턴이야

🌟 즉, 흐름은 다음과 같아:

Tomcat → DispatcherServlet.service(request, response)

🧩 5. DispatcherServlet 처리

DispatcherServlet은 내부에서 다음과 같은 작업 수행:

  1. HandlerMapping을 통해 어떤 Controller가 이 요청을 처리할지 찾음
@GetMapping("/hello")
public String hello() { ... }
  1. HandlerAdapter를 통해 실제 메서드 호출
  2. 메서드 결과(String, @ResponseBody, 등)를 View 또는 JSON으로 변환

🧩 6. Controller까지 도달

Spring이 매핑된 메서드를 호출:

@GetMapping("/hello")
public String hello() {
    return "Hello from Spring!";
}

→ 결과는 HttpServletResponse 객체에 담겨

→ 톰캣이 다시 이걸 HTTP 응답 → TCP 응답으로 만들어 클라이언트로 전송해줘


🔄 요약: 요청에서 컨트롤러까지 흐름

[브라우저/클라이언트]
   │
   └── HTTP 요청 (TCP 위에 올림)
         ↓
[서버의 TCP 계층]
   └── 커널이 포트 8080에서 리스닝 중인 Tomcat에게 전달
         ↓
[Tomcat]
   └── 바이트 스트림 → HttpServletRequest/Response 객체 생성
         ↓
[DispatcherServlet (Spring)]
   └── HandlerMapping → Controller 메서드 실행
         ↓
[Controller]
   └── 응답 반환
         ↓
[Tomcat]
   └── 응답을 HTTP 메시지 → TCP 전송
         ↓
[클라이언트가 응답 수신]

MVC 패턴과 DispatcherServlet

MVC 패턴이란?

MVC (Model-View-Controller) 패턴은 웹 애플리케이션에서 로직을 세 부분으로 나누는 설계 패턴

구성 요소역할
Model데이터 및 비즈니스 로직 (ex. DB에서 데이터 가져오기, 계산 처리 등)
View사용자에게 보여지는 화면 (HTML, JSP, Thymeleaf 등)
Controller사용자 입력/요청 처리, Model과 View 연결

DispatcherServlet이란?

Spring MVC의 핵심 중앙 컨트롤러(Front Controller) 역할을 하는 서블릿이야.

핵심 역할

  • 클라이언트로부터 들어온 요청을 받아서
  • 어떤 컨트롤러에 전달할지 판단하고
  • 뷰를 어떻게 응답할지 결정하는 중앙 처리자

DispatcherServlet의 주요 책임

순서기능
1클라이언트의 요청을 받는다
2HandlerMapping에게 어떤 컨트롤러가 처리할지 물어본다
3HandlerAdapter를 통해 실제 컨트롤러 호출
4컨트롤러 로직 실행 → 결과 객체 (ModelAndView) 반환
5ViewResolver를 통해 어떤 뷰를 보여줄지 결정
6최종적으로 뷰 렌더링 후 클라이언트에게 응답

🔄 요청 처리 전체 흐름 (Spring Context 포함)

[클라이언트 요청]
       ↓
[내장 톰캣 (WAS)]
       ↓
[DispatcherServlet (Front Controller)]
       ↓
[HandlerMapping] ← 어떤 컨트롤러로?
       ↓
[HandlerAdapter] ← 실제 컨트롤러 실행 도와줌
       ↓
[Controller (비즈니스 로직)]
       ↓
[ModelAndView 반환]
       ↓
[ViewResolver] ← 어떤 화면(View) 보여줄까?
       ↓
[View (ex. Thymeleaf, JSP)]
       ↓
[DispatcherServlet이 최종 렌더링]
       ↓
[클라이언트에게 응답]

🧠 DispatcherServlet은 언제 등록되냐?

  • Spring Boot에서는 @SpringBootApplication 실행 시 DispatcherServlet이 자동으로 등록돼.
  • ServletRegistrationBean을 통해 내부적으로 등록되며, URL 패턴은 기본적으로 "/" (전체 요청 처리)

📌 예시 코드 흐름

@GetMapping("/hello")
public String hello(Model model) {
    model.addAttribute("msg", "Hello!");
    return "helloPage"; // View 이름
}
  • DispatcherServlet이 /hello 요청을 감지
  • HandlerMapping으로 해당 메서드 찾음
  • HandlerAdapter가 메서드 실행
  • ViewResolver가 "helloPage" → helloPage.html로 변환
  • 클라이언트에게 응답!

참고자료

스프링 웹 동작 흐름

아파치와 톰캣

MVC와 DispatcherServlet

profile
성장의 흔적을 남기는 블로그입니다.

0개의 댓글