목차

    ⏳ Time Log/1. One Day (Daily · TIL)

    [TIL] Day 66 — JPA 엔티티 연관관계 매핑 + Dockerfile 커스텀 이미지 빌드 (1/21)

    this.Serena 2026. 6. 8. 21:30

    [TIL] Day 66 — JPA 엔티티 연관관계 매핑 + Dockerfile 커스텀 이미지 빌드 (1/21)

    날짜: 2026-01-21
    기술 스택: Spring Boot JPA Hibernate Docker Dockerfile


    한 줄 요약: JPA 양방향 연관관계 매핑과 영속성 전이 설계 원칙 + Dockerfile로 nginx/MySQL 커스텀 이미지 직접 빌드


    JPA 엔티티 연관관계 매핑

    양방향 관계 설계 패턴

    // Order.java
    @Entity
    @ToString(exclude = {"member", "orderItems"}) // 순환 참조 방지
    public class Order {
    
        @ManyToOne
        @JoinColumn(name = "member_id")
        private Member member;
    
        @OneToMany(mappedBy = "order",
            cascade = CascadeType.ALL,   // 부모 저장 시 자식도 함께
            orphanRemoval = true)        // 부모에서 제거 시 자식 DB 삭제
        @Builder.Default
        private List<OrderItem> orderItems = new ArrayList<>();
    }

    @ToString(exclude) — StackOverflowError 방지

    양방향 관계에서 toString() 호출 시 서로를 무한 참조해 스택 오버플로우 발생
    → 연관 엔티티 필드를 exclude에 명시해 단순 값 필드만 출력

    @ToString(exclude = "orders")             // Member
    @ToString(exclude = {"member", "orderItems"}) // Order
    @ToString(exclude = "order")              // OrderItem

    cascade + orphanRemoval 조합

    설정 효과
    CascadeType.ALL 부모 저장/삭제 시 자식도 동일 작업 수행
    orphanRemoval = true 부모 컬렉션에서 제거된 자식을 DB에서도 삭제

    두 설정을 함께 쓰면 부모 엔티티 하나로 자식 생명주기를 완전히 제어 가능

    JPQL DISTINCT + ORDER BY

    @Query("SELECT DISTINCT o FROM Order o " +
           "WHERE o.member = :member " +
           "ORDER BY o.orderDate DESC")
    List<Order> findByMember(@Param("member") Member member);

    DISTINCT — 조인으로 인한 중복 제거 / DESC — 최신 주문 먼저


    Dockerfile로 커스텀 이미지 빌드

    nginx Dockerfile 예시

    FROM nginx
    COPY ./html /usr/share/nginx/html
    docker build -t buildnginx .              # 현재 디렉터리 Dockerfile로 빌드
    docker run --name mynginx -d -p 5555:80 buildnginx

    MySQL Dockerfile (별도 파일 지정)

    파일명: MySQLDockerfile

    FROM mysql
    ENV MYSQL_ROOT_PASSWORD=1234
    ENV MYSQL_DATABASE=mydb
    docker build -f MySQLDockerfile -t buildmysql .   # -f 로 파일명 지정
    docker run -d --name mysql-container -p 3306:3306 buildmysql

    docker build 핵심 옵션

    옵션 의미
    -t 이름:태그 빌드할 이미지 이름/태그 지정
    -f 파일명 기본 Dockerfile 대신 다른 파일 사용
    . 빌드 컨텍스트 (현재 디렉터리)

    더 알아볼 것

    • @ManyToMany를 지양하고 중간 엔티티로 풀어야 하는 이유
    • FetchType.LAZY vs EAGER — N+1 문제 발생 시나리오
    • Dockerfile COPY vs ADD 차이
    • .dockerignore 파일로 빌드 컨텍스트 최적화
    • docker inspect 이미지명으로 레이어 구조 확인