1. MVC 아키텍처
1. DTO (Data Transfer Object)
a) 클라이언트와 서버 사이에서 데이터를 전송하기 위한 객체이다.
b) Controller 계층에서 Request/Response 용도로 사용한다.
c) Entity를 직접 노출하기보다 DTO로 주고받는 편이 좋다(보안, 유지보수 측면).
2. Controller
주로 DTO 유효성 검증 및 요청/응답을 처리한다.
Controller에 Entity를 직접 두는 것은 좋은 설계가 아니다(관심사 분리).
(예: controller -> service -> repository 구조로 진행)
3. Repository
JPA에서는 Entity 중심으로 DB에 접근하는 계층이다.
일반적인 흐름은 controller(dto) -> service(dto, entity) -> repository(entity).
Repository는 DB 접근 로직을 담당하고, 핵심 비즈니스 로직 및 데이터 정합성 검증은 Service가 담당한다.
4. Service
DTO와 Entity를 모두 처리하며, 비즈니스 로직을 수행한다.
트랜잭션 범위 안에서 데이터 정합성을 검증하고, 필요한 경우 Repository를 호출해 DB에 접근한다.
2. Annotation
@RestController vs @Controller
@Controller: View(템플릿) 렌더링을 주로 담당.
@RestController: @ResponseBody + @Controller를 합친 것으로, JSON 등 데이터 자체를 반환하기에 적합.
API 서버라면 @RestController를, 템플릿 엔진을 사용할 경우 @Controller를 주로 쓴다.
@Controller, @Service, @Repository, @Component
전부 @Component를 메타로 하는 스테레오타입 애노테이션이다.
@Service, @Repository는 각각 비즈니스 로직 계층, DB 접근 계층임을 명시적으로 나타내 유지보수를 용이하게 한다.
@Configuration은 @Component를 포함하여, 클래스 단위로 Bean 등록을 위한 설정을 모아두는 용도다.
@Bean은 @Configuration 내부의 메서드에 붙여서 Bean 생성을 명시한다.
@ComponentScan
@SpringBootApplication 내부에 포함되어 있으며, @Component 계열(@Controller, @Service, @Repository 등)과 @Configuration을 찾아서 Bean으로 등록한다.
등록된 클래스들은 BeanFactory에 의해 인스턴스화되고 관리된다.
Bean 등록
간단히 말해, 스프링 컨테이너가 객체를 생성(new)하고 필요한 의존성을 주입(생성자 주입 등)하여 관리하는 과정을 말한다.
클래스가 인스턴스화될 때 생성자가 실행되고, 필요한 Bean들이 자동으로 연결된다.
final 전역 상수
final 키워드를 사용해 불변(Immutable) 필드를 선언하고, 생성자에서 주입 받는 패턴을 자주 쓴다(생성자 패턴).
이를 통해 값이 한 번 설정된 후 변경되지 않도록 보장한다.
정리
@ComponentScan으로 스캔된 클래스들은 BeanFactory에 등록(인스턴스화)된다.
인스턴스화 시점에 생성자가 실행되고, 필요한 Bean들이 자동으로 주입된다.
3. JPA
JpaRepository
JpaRepository<Entity, ID> 형태로 상속받으면, 기본적인 CRUD 메서드가 제공된다.
메서드 이름으로 쿼리를 만드는 방법이 복잡해지면 @Query 애노테이션과 JPQL을 사용한다.
JPA 설정(ddl-auto)
spring.jpa.hibernate.ddl-auto=update일 경우 Entity 스키마가 변경되었을 때 컬럼 삭제 등은 자동 반영되지 않는다.
개발 단계에서는 create-drop을 써서 부트 시점마다 DB를 새로 만들 수도 있다(데이터도 함께 삭제되므로 주의).
DDL
@Entity가 선언된 클래스는 테이블로 매핑되고, @Id로 PK를 지정하며, @GeneratedValue로 채번 전략을 설정한다.
@ManyToOne, @OneToMany, @JoinColumn 등을 통해 관계를 설정한다.
fetch 전략으로 LAZY/EAGER를 선택할 수 있는데, LAZY는 실제 필요 시점에, EAGER는 즉시(조인 또는 추가 SELECT 등) 로딩한다.
JPA N+1 문제
ORM 기술에서 특정 객체를 대상으로 수행한 쿼리가 해당 객체가 가지고 있는 연관관계 또한 조회하게 되면서 N번의 추가적인 쿼리가 발생하는 문제다.
fetch join(@Query 사용)으로 한 번에 가져오거나, 필요 시점에만 LAZY 로딩 등을 활용해 해결한다.
상황에 따라 EAGER, LAZY를 적절히 선택하고 limit 등을 설정해 성능을 조절할 수 있다.
4. TODO
- JPA를 포함한 MVC 구조의 프로젝트 생성
- ERD 그리기(테이블 5개 이내)
- Entity 클래스 작성
- Docker로 MySQL 컨테이너 띄우기
- Spring 설정(yml/properties)에서 DB 연결 정보 등록
'dev > 프로젝트' 카테고리의 다른 글
[프로젝트] JPA 영속성 Context & AOP (2) | 2025.01.16 |
---|---|
[프로젝트] ERD & Docker 적용 (6) | 2025.01.15 |
[프로젝트] openAI API 사용해보기 (4) | 2025.01.14 |
[프로젝트] openAI API 발급하기 (4) | 2025.01.13 |
[프로젝트] 데이터 전처리를 위한 데이터 수집(2) (2) | 2025.01.09 |