Post

Spring 아키텍처

Spring 아키텍처

Spring 아키텍처

Controller · Service · Repository · JPA · DTO · Entity



1. Controller

Controller는 클라이언트의 요청(URL) 을 받아 비즈니스 로직(Service) 을 호출하고

View 또는 데이터(JSON) 를 반환하는 역할을 담당

👉 요청 → 처리 흐름을 연결해주는 입구 역할



1-1. @Controller

  • View(화면) 반환이 주 목적
  • API와 View를 동시에 사용하는 경우에 사용
  • 객체를 반환하려면 @ResponseBody를 명시적으로 사용
1
2
3
4
5
6
7
8
9
@Controller
public class SampleController {

    @GetMapping("/test")
    @ResponseBody
    public String test() {
        return "hello";
    }
}



1-2. @RestController

  • View가 필요 없는 API 전용 Controller
  • Spring 4.0.1부터 제공
  • 모든 메서드에 @ResponseBody가 자동 적용
1
2
3
4
5
6
7
8
@RestController
public class ApiController {

    @GetMapping("/api/test")
    public ResponseEntity<String> test() {
        return ResponseEntity.ok("hello");
    }
}
  • @RestController = @Controller + @ResponseBody

  • return : JSON / XML 등 데이터





2. Service 계층

Service는 비즈니스 로직을 담당하는 계층

  • 여러 Repository 조합
  • 트랜잭션 처리
  • 도메인 로직 구현


2-1. Service Interface 와 Impl 을 나누는 이유

1. AOP (관점 지향 프로그래밍)

Spring AOP는 특정 메서드 호출 시점에 프록시 객체(Proxy Bean) 를 생성하여 트랜잭션, 로깅 같은 부가 기능을 수행

프록시 생성 방식은 크게 두 가지

구분설명
JDK Dynamic Proxy인터페이스 필수
CGLIB클래스 기반 프록시


과거 CGLIB의 문제점

  • 별도 의존성 필요
  • 기본 생성자 필수
  • 생성자 2번 호출

이로 인해 과거에는 JDK Dynamic Proxy 권장


현재 Spring Boot

  • Spring 3.2 이후 CGLIB 문제점 개선
  • Spring Boot 기본 설정


1
spring.aop.proxy-target-class=true
  • 인터페이스가 있어도 CGLIB 사용
  • 성능도 JDK Proxy보다 우수


1
2
3
4
5
# JDK Dynamic Proxy 사용
spring.aop.proxy-target-class=false

# CGLIB 사용 (기본값)
spring.aop.proxy-target-class=true



2. OOP (객체지향 설계)

Service를 인터페이스로 분리했을 때 장점 :

  • 구현체 변경에 유연
  • 결합도 감소
  • 다형성 활용 가능

OCP (개방-폐쇄 원칙)

  • 기존 코드는 변경하지 않고
  • 기능 확장은 가능해야 한다


DIP (의존관계 역전 원칙)

  • 구현 클래스 ❌
  • 추상화(인터페이스)에 의존 ⭕



언제 나누는 것이 좋을까?

  • 구현체가 2개 이상 존재할 가능성이 있을 때
  • ex) 카드 결제
    • 결제
    • 취소
    • 부분 취소 등





3. 트랜잭션(Transaction)

트랜잭션이란 db 상태를 변경하는 하나의 논리적 작업 단위

  • 모두 성공하거나
  • 하나라도 실패하면 전체 롤백



트랜잭션의 특징

  • 작업의 완전성 보장
  • 일부만 반영되는 현상 방지
  • DB 관점에서는 CRUD 단위



Spring의 트랜잭션 처리 방식

Spring에서는 선언적 트랜잭션을 주로 사용

1
2
3
4
@Transactional
public void save() {
    ...
}
  • @Transactional 적용 시 프록시 객체 생성
  • PlatformTransactionManager가 트랜잭션 제어
    • 정상 : Commit
    • 예외 : Rollback


트랜잭션은 어디에 적용해야 할까?

❌ Controller
❌ Repository
⭕ Service 계층

이유:

  • 여러 Repository 조합
  • 비즈니스 단위 처리



참고로 트랜잭션에 대해 잘 정리된 글이 있어서 링크 첨부한다.

[Java]@Transactional Annotation 알고 쓰자





4. Repository 계층

Repository는 Entity를 통해 DB 테이블에 접근하는 계층

  • CRUD 처리
  • DB 접근 코드 담당





5. Spring Data JPA

JPA란?

  • Java Persistence API
  • ORM 기술 표준
  • 객체 ↔ 관계형 DB 간 차이 해결


구조 :

1
2
3
4
5
6
7
8
9
Application
   ↓
JPA
   ↓
Hibernate
   ↓
JDBC
   ↓
DB



Hibernate

  • JPA 구현체 중 가장 대표적
  • EntityManager 등 JPA 인터페이스 구현



Spring Data JPA

  • JPA를 한 번 더 추상화
  • Repository 인터페이스 제공
  • CRUD 메서드 자동 제공
1
2
3
public interface RegistryRepository 
        extends JpaRepository<Registry, Long> {
}
  • <Entity, PK 타입> 지정 필수
  • @Repository 생략 가능



정리

  • JPA: ORM 기술 명세
  • Hibernate: JPA 구현체
  • Spring Data JPA: Repository 제공 프레임워크

image





6. DTO · Entity · Repository

DTO (Data Transfer Object)

  • 순수 데이터 객체
  • getter / setter 만 존재
  • 계층 간 데이터 전달 목적

VO는 DTO와 유사하지만 Read Only



Entity

  • DB 테이블과 1:1 매핑
  • @Entity 필수
  • JPA 관리 대상



계층 흐름

1
2
3
4
5
6
7
8
9
Client
 ↔ DTO
Controller
 ↔ DTO
Service
 ↔ DTO
Repository
 ↔ Entity
DB





7. DAO · Model (JPA 미사용 시)

  • JPA 미사용 환경
  • MyBatis 등 사용



DAO

  • DB 접근 객체
  • Service ↔ DB 연결 역할
  • @Repository 사용
1
2
3
4
5
<mapper namespace="project.dao.SampleDAO">
    <select id="methodName" resultType="">
        SELECT ...
    </select>
</mapper>



흐름

1
2
3
4
5
Client
 ↔ Controller
 ↔ Service
 ↔ DAO
 ↔ DB






REFERENCE

This post is licensed under CC BY 4.0 by the author.