목차

    불편함을 코드로 지웁니다.

    개발 공부 노트, 개발 도구와 문제를 해결한 과정, AI 프롬프트와 Obsidian 활용법을 정리합니다.

      ⏳ Time Log/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 이미지명으로 레이어 구조 확인