0. 스프링(Spring)이란?
스프링은 자바 기반의 엔터프라이즈 애플리케이션 개발을 위한 프레임워크이다. 핵심 철학은 POJO (Plain Old Java Object) 프로그래밍을 지향한다는 것이다. 과거(EJB 시절)에는 자바 코드가 프레임워크에 종속되어 복잡하고 무거웠지만, 스프링은 **가장 기본적인 자바 객체(POJO)**만으로도 웹 사이트나 엔터프라이즈급 서비스를 만들 수 있게 도와준다.
참고 : 최근에는 설정이 복잡한 'Spring Legacy' 대신, 톰캣 서버를 내장하고 설정을 자동화한 'Spring Boot'를 표준으로 사용한다.
1. 스프링의 구성 (Web Container와 라이브러리)
1) 스프링의 핵심 구성 요소 스프링은 거대한 컨테이너 집합체다.
- Core Container (핵심): 빈(Bean)을 관리하는 IoC/DI 컨테이너. (우리가 아는 그 스프링)
- Spring MVC (웹): 웹 요청을 처리하기 위해 Core 위에 얹은 모듈. (내장 톰캣 포함)
- Data Access (DB): JDBC, JPA, 트랜잭션 관리를 담당하는 모듈.
- Security (보안): 인증/인가를 담당하는 모듈.
스프링 부트는 이 모든 걸 간편하게 묶어놓은 패키지다
2) 스프링 부트의 웹 구성 (Web Container)
2-1) spring-boot-starter-web 라이브러리의 정체 이 라이브러리를 추가하면 **내장 톰캣(Embedded Tomcat)**이 함께 설치된다.
- 과거: 톰캣(WAS)을 따로 컴퓨터에 설치하고, 그 안에 자바 코드를 넣어서 돌려야 했다.
- 현재(Spring Boot): 프로젝트 자체가 톰캣을 품고 있다. 실행 버튼만 누르면 알아서 서버가 뜬다.
2-2) 웹 컨테이너 (Web Container / Servlet Container) 자바가 웹 요청을 받을 수 있게 해주는 그릇이다. 대표적으로 Tomcat이 있다.
- 클라이언트(브라우저)가 요청을 보내면 -> **Tomcat(웹 컨테이너)**이 가장 먼저 받는다.
- Tomcat은 이 요청을 스프링의 대장인 **DispatcherServlet**에게 넘겨준다.
- 여기서부터 비로소 스프링의 영역이 시작된다.
2. 스프링의 동작 방식 (MVC 패턴)
모든 요청은 **DispatcherServlet (프론트 컨트롤러)**이 가장 먼저 받아서 적절한 곳으로 배분한다.
1) 정적 콘텐츠 (Static Content)
- 설명: 서버가 뭐 계산할 필요 없이, 파일 그대로 주는 것. (HTML, CSS, JS, 이미지)
- 동작: 요청 -> 내장 톰캣 -> 스프링 부트가 resources/static 폴더를 뒤져서 파일이 있으면 바로 반환한다. (Controller까지 안 감)
2) MVC와 템플릿 엔진 (Server-Side Rendering)
- 설명: 서버에서 데이터를 가공해서 HTML을 완성해 내려주는 방식. (Thymeleaf, JSP)
- 동작:
- 요청 -> DispatcherServlet -> Controller (비즈니스 로직 수행)
- Controller가 결과 데이터(Model)와 보여줄 화면 이름(View Name)을 리턴.
- **ViewResolver**가 화면 이름을 보고 실제 템플릿 파일(예: home.html)을 찾는다.
- 템플릿 엔진이 Model의 데이터를 HTML에 쏙쏙 박아넣어 변환 후 브라우저에 전달.
3) API (Client-Side Rendering)
- 설명: 요즘 제일 많이 쓰는 방식. HTML이 아니라 **데이터(JSON)**만 내려주는 방식. (React, Vue, 앱 통신용)
- 동작:
- 요청 -> DispatcherServlet -> Controller (@ResponseBody 또는 @RestController)
- Controller가 **객체(Object)**를 바로 리턴.
- ViewResolver 대신 **HttpMessageConverter**가 동작.
- 객체를 JSON 문자열로 바꿔서 브라우저에 반환.
2-1 갑자기 궁금해진 csr vs ssr
1. SSR vs CSR: 데이터와 HTML의 만남
가장 큰 차이는 **"완성된 HTML을 만드느냐, 아니면 재료(JSON)만 보내느냐"**다.
SSR (Server Side Rendering)
- 작동 방식: 브라우저가 요청을 보내면, 서버가 DB에서 데이터를 꺼내와 HTML 템플릿(Thymeleaf 등)에 직접 박아 넣는다. 이렇게 완성된 HTML을 브라우저에 던져준다.
- Controller: @Controller를 사용한다. 메서드의 반환값은 보통 String이며, 이는 templates 폴더에 있는 HTML 파일의 이름이다.
- HTML 위치: 서버의 src/main/resources/templates 폴더 안에 위치한다.
CSR (Client Side Rendering)
- 작동 방식: 브라우저는 처음에 데이터가 비어있는 '뼈대만 있는 HTML'과 JS 파일을 받는다. 그 후 JS가 서버의 API로 "데이터 좀 줘"라고 요청하면, 서버는 JSON 데이터만 보내준다. 브라우저의 JS가 이 데이터를 받아 화면을 그린다.
- Controller: @RestController를 사용한다. 메서드는 객체(DTO)나 리스트를 직접 반환하며, 이는 메시지 컨버터를 통해 JSON으로 변환된다.
- HTML 위치: 보통 별도의 프론트엔드 프로젝트(React, Vue 등) 폴더에 있거나 서버의 static 폴더에 정적 파일로 존재한다.
2. 질문하신 내용들에 대한 명쾌한 답변
Q1. CSR은 컨트롤러에서 데이터를 안 받나요?
아니다. 둘 다 컨트롤러에서 데이터를 받는다. 다만 **"반환하는 형태"**가 다르다.
- SSR: 데이터를 Model 객체에 담아 **뷰(View)**로 보낸다.
- CSR: 데이터를 JSON 문자열로 바꿔서 HTTP 응답 바디(Body)에 직접 담아 보낸다.
Q2. 서비스나 리포지토리 레이어는 똑같이 동작하나요?
그렇다. 완전히 똑같다.
이것이 계층형 아키텍처의 장점이다. 비즈니스 로직(Service)과 데이터 접근(Repository)은 화면을 어떻게 그릴지에 관심이 없다. 보현님의 주식 프로젝트에서도 StockService는 SSR이든 CSR이든 상관없이 '주식 정보를 가져오는 일'만 하면 된다.
Q3. CSR의 연결은 어떻게 하나요?
프론트엔드(클라이언트)가 서버와 연결되는 핵심 도구는 **AJAX (Fetch API 또는 Axios 라이브러리)**다.
- 브라우저의 JS가 fetch("/api/stocks")라고 서버에 호출한다.
- 서버의 @RestController가 JSON 데이터를 응답한다.
- JS가 이 데이터를 받아서 document.getElementById(...) 같은 코드로 HTML 요소에 값을 채워 넣는다.
📊 SSR vs CSR 비교 정리
| 항목 | SSR (예: Thymeleaf) | CSR (예: React + API) |
| 백엔드 어노테이션 | @Controller | @RestController |
| 반환값 | 뷰 파일 이름 (String) | 데이터 (DTO, List 등) |
| 데이터 전달 방식 | Model 객체에 담음 | HTTP Message Body (JSON) |
| 초기 로딩 속도 | 빠름 (이미 완성된 HTML을 받음) | 느림 (JS 실행 전까지 빈 화면) |
| 페이지 이동 | 전체 페이지가 깜빡이며 새로고침됨 | 필요한 부분만 부드럽게 바뀜 |
💡 내 프로젝트에 대입해 본다면
실시간 가상 자산 거래 플랫폼은 시세가 실시간으로 변해야 하므로 CSR 방식이 훨씬 적합하다. 페이지 전체를 새로고침(SSR)하지 않고, JS가 주기적으로 API를 호출하여 시세 데이터만 받아와 화면의 숫자만 슥슥 바꿔주는 것이 훨씬 사용자 경험이 좋기 때문이다.
3. 스프링의 계층형 구조 (Layered Architecture)
스프링은 역할에 따라 철저하게 **계층(Layer)**을 나눈다. 이를 **관심사의 분리(Separation of Concerns)**라고 한다.
1) Controller (프레젠테이션 계층)
- 역할: 웹 요청과 응답을 처리하는 '창구'.
- 하는 일: "사용자가 회원가입 요청을 보냈네? 파라미터 체크하고 Service한테 일 시켜야지."
- 어노테이션: @Controller, @RestController
2) Service (비즈니스 계층)
- 역할: 실제 핵심 **'업무 로직'**을 수행하는 곳.
- 하는 일: "회원가입 하려면 중복 회원인지 확인하고, 비밀번호 암호화하고, 등급 설정해야지." (트랜잭션 처리가 여기서 일어남 @Transactional)
- 어노테이션: @Service
3) Repository (데이터 접근 계층)
- 역할: DB에 접근해서 데이터를 넣고 빼는 '창고지기'.
- 하는 일: "Service가 저장하래. SQL 날려서 DB에 insert 하자." (JPA, Mybatis 등 사용)
- 어노테이션: @Repository
4) Domain (Entity/Model)
- 역할: 데이터 그 자체. DB 테이블과 매핑되는 객체.
- 특징: 모든 계층에서 이 도메인 객체를 주고받으며 일을 처리한다.
4. 스프링의 주요 라이브러리 (Starters)
스프링 부트는 starter라는 이름으로 의존성 세트를 제공한다.
- spring-boot-starter-web: 톰캣(Tomcat) + 스프링 웹 MVC (가장 기본).
- spring-boot-starter-data-jpa: DB 작업을 쉽게 해주는 ORM 기술(Hibernate 등) 포함.
- spring-boot-starter-thymeleaf: 서버 사이드 렌더링용 템플릿 엔진.
- spring-boot-starter-test: 테스트를 위한 라이브러리 모음 (JUnit, Mockito, AssertJ 등).
- Lombok: Getter, Setter, 생성자 등을 어노테이션(@Data, @RequiredArgsConstructor)으로 자동 생성해 주는 필수 라이브러리.
💡 (심화) 개발자가 꼭 알아야 할 '싱글톤 컨테이너'
스프링이 관리하는 객체(Bean)들은 기본적으로 **싱글톤(Singleton)**으로 관리된다.
- 왜? 웹 애플리케이션은 동시에 수천 명의 요청이 들어온다.
- 요청이 올 때마다 MemberService 객체를 new로 새로 만들면 메모리가 터져버릴 것이다.
- 그래서 스프링은 딱 1개의 객체만 생성해 놓고, 모든 요청이 그 객체를 공유해서 쓰도록 관리한다.
- 주의점: 그래서 스프링 빈은 상태를 가지게 설계하면 안 된다(Stateless). (특정 사용자의 돈을 멤버 변수에 저장하면, 다른 사람 요청에서 그 돈이 보일 수 있음!)
5. Tomcat vs Servlet vs DispatcherServlet (+ Template Engine) 용어 정리
이 네 가지의 관계는 **'회사(웹 애플리케이션)'**에 비유하면 이해가 빠릅니다.
1) Servlet (서블릿) → "직원(Worker)을 정의하는 규칙"
- 역할: 자바 진영에서 "웹 요청을 받아서 처리하고 응답을 줄 수 있는 객체"라면 반드시 지켜야 하는 **표준 규칙(Interface)**입니다.
- 비유: 회사의 '사무 분장' 또는 '직무 기술서'. "손님이 오면 인사하고(Request), 원하는 걸 해결해서 보내줘라(Response)"라는 규칙을 따르는 모든 자바 클래스는 서블릿입니다.
2) Tomcat (Web Container / Servlet Container) → "사무실(Office)이자 관리자"
- 역할: 서블릿들이 살아서 움직일 수 있는 공간입니다. 서블릿은 main() 메소드가 없어서 혼자 실행될 수 없습니다.
- 기능:
- 서블릿을 생성하고 메모리에 올립니다 (출근).
- 요청이 들어오면 적절한 서블릿을 호출해서 일시킵니다 (업무 배정).
- 서버가 종료되면 서블릿을 메모리에서 제거합니다 (퇴근/해고).
- 비유: 책상, 의자, 전기가 제공되는 사무실 건물. 건물이 없으면 직원은 일할 수 없습니다.
3) DispatcherServlet → "스프링에서 파견한 대표 전화 상담원 (Front Controller)"
- 정체: 이 녀석도 본질은 HttpServlet을 상속받은 **'서블릿'**입니다. 그래서 톰캣 안에서 살아갈 수 있습니다.
- 차이점:
- (과거) 로그인 서블릿, 게시판 서블릿 등 요청마다 직원을 따로 고용했습니다. 관리가 힘들고 코드가 중복됩니다.
- (현재-스프링) DispatcherServlet이라는 똑똑한 상담원 한 명만 톰캣에 등록합니다.
- 흐름: 모든 요청을 DispatcherServlet이 가장 먼저 받습니다. 그리고 요청 내용을 분석해서 뒤에 있는 적절한 부서(Controller)로 업무를 토스합니다.
4) Template Engine (템플릿 엔진) → "보고서 출력기 / 완성 담당"
- 역할: Controller가 일을 마치고 넘겨준 **데이터(Data)**를, 미리 만들어둔 **구멍 뚫린 HTML(양식)**에 채워 넣어서 **완성된 문서(HTML)**를 만드는 도구입니다. (SSR: Server Side Rendering)
- 종류: Thymeleaf (스프링 부트 표준), JSP (레거시).
- 비유: 실무 담당자(Controller)가 "매출: 100억"이라는 쪽지를 주면, 보고서 양식(Template)에 그 숫자를 예쁘게 박아 넣고 **인쇄(Rendering)**해서 손님(브라우저)에게 건네주는 역할입니다.
[전체 흐름 요약]
- 손님(브라우저)이 회사(Tomcat)에 옴.
- 대표 상담원(DispatcherServlet)이 맞이함.
- 담당자(Controller)에게 업무 토스.
- 담당자가 계산 끝내고 데이터(Model)를 넘김.
- 출력기(Template Engine)가 데이터를 양식에 찍어서 문서(HTML) 완성.
- 손님에게 전달 (응답).
'개발 공부 > 스프링' 카테고리의 다른 글
| 순수 Java로 WAS 구현해보기 (1) - 스프링과 WAS의 핵심 개념 이해 (1) | 2026.04.06 |
|---|---|
| SpringApplication에 대한 정리 (0) | 2026.03.25 |
| 백엔드 계층 구조 정리 2 (0) | 2026.03.11 |
| 백엔드 계층 구조 정리 1 (0) | 2026.03.11 |
| 스프링 정리 (0) | 2026.02.16 |