1. ORM (Object-Relational Mapping)


ORM은 객체 지향 언어의 객체와 관계형 DB의 테이블 / 행 / 열을 매핑해, 코드를 객체 중심으로 작성하면 내부에서 적절한 SQL을 생성, 실행해 주는 기술이다.

 

이를 통해 간단한 CRUD는 대부분 SQL 쿼리를 직접 작성하지 않고도 사용이 가능하여 단순 반복작업이 줄어들어 개발 과정이 단순화되고, 코드의 가독성 또한 향상된다.

 

ORM을 이용해 작성된 쿼리는 중간에 DB가 바뀌더라도 그에 맞는 방언(dialect)으로 맞춰 번역해 주는 어댑터 역할도 한다.

 

 

2. JPA (JAVA Persistence API)


자바에서 객체와 RDB 테이블 간 매핑(ORM)을 표준화한 스펙으로 구현체로는 Hibernate, EclipseLink 등이 있지만 Hibernate가 사실상 표준처럼 쓰인다.


 

 

2-1 주요 개념

 

  1. Entitiy : 테이블과 매핑되는 클래스
  2. Persistence Context(영속성 컨텍스트) : 엔티티 인스턴스를 1차 캐시에 보관하고 생명주기를 관리
    • 영속성 컨텍스트는 키(식별자) - 엔티티 맵을 가지고 있어 같은 식별자를 find()하면 DB 재조회 없이 캐시에서 반환
    • 쓰기 지연(Write - Behind) : persist()를 실행하면 바로 Insert 쿼리가 나가지 않고 Flush 시점에 일괄 Insert
    • 변경 감지(Dirty Checking) : 엔티티 스냅샷을 보관하여 달라진 필드를 감지하여 UPDATE 쿼리 생성
    • 지연 로딩과 프록시 : 관계가 있는 엔티티를 필드로 가지고 있고 지연 로딩(LAZY)으로 설정되어 있다면 실제 접근 시 조회 그전까진 프록시

2-2 매핑 예시

 

@Entity
@Table(name = "member")
public class Member {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column(nullable = false, length = 50)
  private String username;

  @Column
  private int age;
}

 

 

3. JPQL (JAVA Persistence Query Language)


객체 모델(Entity)를 대상으로 하는 질의 언어(Query Language)로 SQL과 매우 유사하지만 테이블과 컬럼이 아닌 Entity와 필드를 대상으로 쿼리를 작성할 수 있다


3-1 특징

  1. 엔티티/필드 기반
    • 키워드는 대소문자 무관, 엔티티/필드명은 대소문자 구분
    • ex) select m from Member m where m.name = :name
  2. 경로 표현식과 암시적 조인
    • 단일 값 연관(@ManyToOne)은 암시적 INNER JOIN 가능 m.team.name
    • 컬렉션 연관(@OneToMany)은 명시적 JOIN 필요 join m.members mm
  3. 조인 & 페치 조인
    • join, left join 지원 (right join은 없음)
    • join fetch로 연관 엔티티 즉시 로딩(N+1 방지)
  4. 프로젝션
    • 엔티티 : select m from Member m
    • 특정 필드 : select m.name, m.age Member m
    • DTO : select new com.example.MemberDto(m.id, m.name) from Member m

'CS > Spring' 카테고리의 다른 글

DispatcherServlet  (3) 2025.08.25
Servlet? ServletContainer?  (5) 2025.08.18
AOP 정리  (5) 2025.08.13

DispatcherServlet 없이 순수 서블릿일 때의 실행 흐름을 간소화해보면

  1. web.xml 또는 @webServlet의 URL 패턴을 기준으로 HttpServlet 인스턴스를 선택
  2. 컨테이너가 선택된 서블릿의 service()를 호출하고, 내부 HTTP 메서드의 따라 분기(doGet, doPost...)
  3. JSON or getWrite(), getOutputStream() 그리고 JSP라면 그에 맞게 응답을 직접 작성
  4. 2번 전, 3번 후 필터 체인

으로 정리해 볼 수 있다

 

핵심은 모든 걸 직접 해야 한다는 것인데 단순한 기능이 늘수록 반복 코드가 증가하는 단점이 있는데 이를 보안해주는 기술이 DispatcherServlet이다.

 

DispatcherServlet의 동작 흐름


  1. 핸들러 선택
    • 핸들러 검색(HandlerMapping)
      • URL, HTTP 메서드 등 조건에 맞는 컨트롤러(핸들러)를 찾는다
      • 매칭된 핸들러에 연결된 인터셉터( preHandle() )가 호출된다
  2. 핸들러 실행(HandlerAdapter -> 인자 바인딩 -> 컨트롤러 메서드)
    • 핸들러 타입(@controller, 레거시 컨트롤러, @webServlet 등)에 맞는 핸들러 어댑터를 선택한다
    • @RequestParam, @PathVariable, @RequestHeader, @RequestBody, @ModelAttribute 등 파라미터가 각 애노테이션에 맞게 자동 주입
      • @RequestBody의 경우 HttpMessageConverter가 HTTP 바디(JSON/XML 등)를 객체로 역직렬화
    • 컨트롤러 메서드 실행
  3. 반환값 처리(body 직렬화, 뷰 렌더링)
    1. @ResponseBody, @RestController의 경우 HttpMessageConverter를 통해 객체를 바디에 직렬화
    2. @Controller의 경우 문자열/ ModelAndView/ 모델 객체를 반환하면 논리 뷰 이름을 만들고 ModelAndView 객체를 반환
      • 문자열의 경우 ViewResolver가 미리 정해 둔 prefix / suffix를 붙여 물리 뷰로 바꿔 준다
        • ex) jsp의 경우 prefix = "WEB-INF/views/"
          suffix = ".jsp"

    3. produces, Accept 헤더 조건을 고려해 적절한 메세지 컨버터(JSON, XML 등)를 고른다
    4. 뷰 렌더링(ViewResolver) ModelAndView가 있다면 DispatcherServlet이 ViewResolver 체인으로 논리뷰 이름으로 실제 뷰를 찾아 렌더링한다(Thymeleaf/ JSP 등)

 

'CS > Spring' 카테고리의 다른 글

JPA  (1) 2025.08.27
Servlet? ServletContainer?  (5) 2025.08.18
AOP 정리  (5) 2025.08.13

Servlet


서블릿이란 HTTP 요청과 응답을 처리하는 자바 클래스이다.

 

서블릿 컨테이너(Tomcat)가 요청을 서블릿 객체에 전달하고 서블릿은 HttpServletRequest / Response로 데이터를 읽고 응답한다. 

 

서블릿의 생명 주기


@WebServlet(name = "itemServlet", urlPatterns = "/exam/item")
public class ItemServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        // 여기서 DB 커넥션 풀 획득, 캐시 로딩 등 "초기화" 수행(필수는 아님)
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("application/json;charset=UTF-8");
        try (PrintWriter out = resp.getWriter()) {
            String id = req.getParameter("id");
            out.print("{\"path\":\"/exam/item\",\"id\":\"" + (id != null ? id : "") + "\"}");
        }
    }

    @Override
    public void destroy() {
        // init()에서 연 외부 자원 정리
    }
}

 

서블릿은 보통 미리 로드 되거나 첫 요청 시 1회 생성되어 재사용된다

 

객체는 생성후 최초 1회만 init 메서드에서 DB 커넥션 풀 획득, 캐시 로딩 등 초기화를 수행하고 호출된 메서드와 일치하는 메서드를 찾아 실행하고(get 요청이면 doGet, post면 doPost) 만약 일치하는 메서드가 없다면 405응답을 하게된다.

 

서블릿은 기본적으로 하나의 인스턴스로 다수의 요청을 받게되는 구조로 상태를 가지면 안돼고 서블릿 인스턴스가 정상 종료될 때 destroy메서드를 실행해 외부 자원을 반납하게 된다

 

 

 

ServletContainer

 


 

서블릿에는 위에 내용에 추가로 서블릿 스펙에서 HTTP 요청/응답 서블릿 생명주기, 디스패처 타입 등 동작을 등을 인터페이스나 추상 클래스 형태로 정의하는데 그것의 구현한 것이 서블릿 컨테이너이고 Spring에선 Tomcat이 서블릿 컨테이너의 역할을 한다.

 

스펙 수준에서 반드시 제공하는 기능


  1. 컴포넌트 생명주기 관리
    • 서블릿/ 필터를 리스너의 로딩 -> 인스턴스 생성 -> init() -> service()분기 ->destory() 호출까지의 과정을 표준 순서로 관리
  2. request, response 객체 생성
    • 소켓에서 읽은 HTTP를 파싱해 HttpServletRequest / Response를 생성
  3. Disfetching(매칭)과 실행 파이프라인
    • Host, Context, servlet을 순서대로 매칭
    • 등록된 Filter Chain을 전/후로 처리
  4. I/O 버퍼링, 커밋 관리
  5. 멀티스레드 지원 및 관리
    • 컨테이너 내부에서 스레드 풀에서 요청을 처리할 스레드를 관리
    • 요청이 들어오면 스레드 풀에서 사용 가능한 스레드를 할당하고 요청 처리가 끝나면 반환
    • 사용 가능한 스레드가 없다면 큐에서 대기 하고 대기중인 스레드가 생긴다면 할당받아 사용

 

 

 

동작 흐름


  1. 커넥터가 HTTP 요청 수신
  2. 서블릿 컨테이너가 HTTP 요청을 파싱해  HttpServletRequest/Response 객체로 만든다
  3. 호스트/ 컨텍스트/ 매핑 결정(컨테이너 디스패치)
    • 가상 호스트 선택 -> 웹앱(Context) 선택 -> 서블릿 매핑 결정(정확 일치 -> 경로 매핑 -> 확장자 매핑 순으로 우선순위를 둠)
    • 매핑 정보는 web.xml 또는 @WebServlet 으로 등록되어 있음
    • 이 단계에선 서블릿 메서드가 호출되지 않고, 어디로 보낼지만 확정하는 과정
  4. 필터 체인 전처리
    • 인증, 로깅, 인코딩 등
  5. 서블릿 service() 호출
    • 컨테이너는 최적으로 찾은 서블릿 인스턴스의 service()를 호출하고 service()는 메서드별로 분기 (doGet, doPost, doput()등)
    • 멀티스레드 환경으로 인스턴스 필드에 가변 상태를 두지 않는다
  6. 서블릿이 응답 헤더/본문 작성
    • resp.setStatus(), setHeader(), setContentType() 등 헤더 설정
    • resp.getWriter() 또는 getOutputSteam()으로 본문을 작성하면 버퍼에 쌓였다가 커밋 된다
  7. 필터 체인 후처리
    • 타이머 기록등
  8. 컨테이너가 소켓으로 전송 & 정리
    • request, response 객체는 스코프 종료로 참조에서 벗어나 GC 대상이 된다

 

'CS > Spring' 카테고리의 다른 글

JPA  (1) 2025.08.27
DispatcherServlet  (3) 2025.08.25
AOP 정리  (5) 2025.08.13

AOP(관점 지향 프로그래밍 - Aspect Oriented Programming)이란 여러 곳에 흩어져 있는 공통 관심사를 한곳으로 모아 중복을 줄이고 일관성을 확보하는 기법이다.

 

 

AOP의 핵심 개념


Aspect - 공통 기능을 담은 모듈(class)

  • Aspect는 클래스에 @Aspect를 붙여 선언한다

Advice - 적용 시점(전, 후, 예외)을 의미한다

  • @Before - 메서드 실행 전 기능을 실행
  • @After - 메서드 실행 후 기능을 실행한다 여기서 예외 여부는 관계없이 실행
  • @AfterReturning - 메서드가 정상적으로 실행된 후 실행
  • @AfterThrowing - 메서드 실행 중 예외가 발생되면 기능을 실행
  • @Around - 가장 강력한 기능으로 메서드 실행 전, 후, 예외 발생 등을 감싸서 어디서든 기능을 수행할 수 있다

Pointcut - 어떤 메서드들에 적용할지를 정의한 규칙

 

JoinPoint - 실제로 끼어들 지점(메서드 실행)

 

 

 

포인트컷 지정자


 

 

execution - 접근 제한자, 리턴 타입, 선언 타입, 메서드명, 파라미터 타입(개수)같은 정적 정보를 지정할 수 있다

  • 아래 이미지를 해석하면 public으로 선언되어야 하고 java.util.List를 반환하며, com.example 패키지에 속한 모든 클래스, 모든 메서드, 모든 매개 변수(타입이나 개수 상관X), throws 절에 java.io.IOException가 있을 시 적용 대상이라는 뜻이다
    ex) public List exam(int a) throws java.io.IOException

  • 추가적으로 *과 ..를 혼동할 수 있는데 *는 무엇이든 하나, .. 은 무엇이든 0개 이상이라고 해석할 수 있다

within - 패키지를 기준으로 매칭

// controller 패키지(하위 포함)에 '선언된' 모든 메서드
within(com.example.controller..*)

// 특정 클래스(또는 내부 클래스까지)
within(com.example.service.OrderServiceImpl)

 

this와 target - 비슷한 개념으로 this는 프록시 객체의 타입 기준, target은 실제 대상(원본) 객체의 타입 기준

// 프록시가 인터페이스 OrderService를 구현하면 매칭
this(com.example.order.OrderService)

// 실제 객체가 OrderServiceImpl이면 매칭(프록시 전략 무관하게 안전)
target(com.example.order.OrderServiceImpl)

 

args - 실제 전달된 매개변수를 기준으로 매칭

// 첫 매개 변수가 Long인 모든 호출
args(java.lang.Long, ..)

// 매개 변수가 2개 (String, *)
args(java.lang.String, *)

// 매개 변수가 0개
args()

 

@annotation - 애노테이션 기준으로 매칭

// @Timed 붙은 메서드만
@annotation(com.example.aop.Timed)

 

 

마지막으로 execution, within. annotation등은 정적 매칭으로 프록시 생성 시점에 매칭이 이루어지고 호출 때마다 재평가를 하지 않는다

하지만 args, this, target등은 동적매칭으로 런타임중 메서드가 호출될 때마다 런타임 정보(인자, 실제 타입)를 보고 추가로 검사한다

 

 

'CS > Spring' 카테고리의 다른 글

JPA  (1) 2025.08.27
DispatcherServlet  (3) 2025.08.25
Servlet? ServletContainer?  (5) 2025.08.18

+ Recent posts