[Springboot] Client-Server 구조 정리
Client (사용자)
- URL 입력, 링크 클릭 등 다양한 이벤트를 통해 HTTPS(443) 요청 발생
- 브라우저는 요청을 도메인 기반으로 DNS 조회 → IP 주소로 전환
- 443 포트를 리스닝 중인 Apache HTTP Server로 전달
Apache HTTP Server (httpd)
HTTPS 요청을 수신 (443 포트)
- SSL 처리 (HTTPS 복호화 → 평문 HTTP)
- 정적 리소스 제공 (HTML, JS, 이미지 등 직접 응답 가능)
- 동적 요청은 리버스 프록시로 Tomcat에 전달
(보통 ProxyPass, ProxyPassReverse 사용)
Apache Tomcat (WAS)
- Apache로부터 들어온 요청을 Tomcat의 Connector가 수신 (8080, 8009 등)
- Connector는 요청을 서블릿 컨테이너에 전달
- 서블릿 컨테이너는 다음 작업 수행:
- HttpServletRequest 객체 생성
- HttpServletResponse 객체 생성
- 요청 처리를 위한 Thread 하나 생성 (Tomcat은 기본적으로 요청 1개당 쓰레드 1개 할당)
- 생성된 쓰레드에서 DispatcherServlet.service(request, response) 호출
Server(Spring boot)
DispatcherServlet : Front Controller의 역할
- 서블릿 컨테이너로부터 요청 및 응답 객체를 전달받음
- 요청 URI에 따라 적절한 Controller를 매핑하여 호출
- 생명주기 관리 및 요청 처리 흐름 제어는 톰캣이, 로직 실행은 스프링이 담당
Controller : 요청에 따라 필요한 서비스 로직 호출
Service : 요청에 따라 비즈니스 로직을 수행
- 필요한 경우 캐시 확인
- 캐시에 데이터가 없으면 Repository를 통해 DB 조회
- 조회된 데이터 가공 후 Controller로 반환
Repository : DB에 직접 접근하여 데이터를 조회하거나 저장(일반적으로 JPA 기반으로 구성)
DB
실제 데이터 저장소로, Java의 경우 JDBC를 통해 DB와 연결한다
JDBC(Java Database Connectivity)
Java와 DB 연결을 제공하여 java에서 DB에 접속하고, SQL 쿼리를 실행하여 CRUD를 할 수 있도록 한다
객체지향 언어와 관계형 데이터베이스 사이의 불일치로 인해 SQL을 직접 작성하고 ResultSet을 객체로 변환하는 과정이 필요하며, 반복적인 코드가 많아 유지보수가 어렵다
이러한 문제를 해결하기 위해 ORM(Object-Relational Mapping) 기술이 등장했다
ORM(Object-Relational Mapping)
객체(Object)와 관계형 데이터베이스(RDBMS)의 테이블을 자동으로 매핑해주는 기술
객체를 RDBMS 테이블과 연결하여, SQL을 직접 작성하지 않고도 데이터베이스와 상호작용할 수 있도록 도와준다
- 객체지향 프로그래밍과 관계형 데이터베이스 간의 불일치(Impredance Mismatch)를 해결
- SQL을 직접 다루지 않고도 데이터를 저장, 조회, 수정, 삭제 가능
- 코드의 재사용성, 유지보수성 증가
Java에서 ORM을 표준화하기 위해 정의한 인터페이스로 JPA가 존재한다.
JPA (Java Persistence API)
Java에서 ORM을 표준화하기 위해 정의한 인터페이스
ORM을 구현하는 데 필요한 기능들을 표준화 및 인터페이스화하여 다양한 JPA 구현체(Hibernate, EclipseLink, OpenJPA 등)가 동일한 코드로 동작할 수 있도록 한다
- ORM 구현체에 종속되지 않고 다양한 DB와 작업할 수 있는 유연성을 제공한다.
- DB와 상호작용을 추상화하여 쿼리를 직접 작성하는 것을 최소화한다
- JPA를 구현한 대표적인 구현체로 Hibernate가 있다
Hibernate
- ORM을 사용하기 위해 인터페이스인 JPA를 구현한 대표적인 구현체(ORM 프레임워크)
- 캐싱, 성능 최적화 등 추가적인 여러 기능들도 제공한다
Hibernate 외에도 EclipseLink, OpenJPA 같은 다른 JPA 구현체도 존재한다
JPA는 인터페이스일 뿐인데 어떻게 JPA로 쿼리를 작성할 수 있는가?
// Java의 다형성을 활용
// EntityManagerFactory는 JPA
// new HibernateEntityManagerFactory(); 를 통해 Hibernate 로 구현한다
EntityManagerFactory emf = new HibernateEntityManagerFactory();
// JPA Query를 호출하여 사용하지만 Hibernate가 실제로 SQL 실행
em.persist(user);
JPA 다형성의 특성으로 인해 부모 객체를 사용하더라도, 자식 객체(Hibernate)의 메서드가 실행된다
Hibernate는 JPA 명세에 맞게 내부적으로 JDBC 코드로 SQL을 변환 및 실행하여 데이터를 처리한다