결제 관련 생성

2025. 3. 4. 22:03·뚜띠

[Payment Entity]

@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "payment")
public class Payment extends BaseEntity {

    @Column(nullable = false)
    private String orderName;

    @Column(nullable = false)
    private BigDecimal amount;

    //TODO:  enum테이블 정의하기
//    @Column(nullable = false)
//    private PaymentStatus status;

    private BigDecimal discountAmount;

    @Column(nullable = false)
    private BigDecimal paidAmount;

    private LocalDateTime completed_at;

    @Column(nullable = false)
    private String tossPaymentKey;

    @OneToMany(mappedBy = "payment", cascade = CascadeType.ALL)
    private List<PaymentHistory> paymentHistoryList = new ArrayList<>(); // 결제 이력


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id", nullable = false)
    private Member member; // 회원 id


    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id", nullable = false)
    private Order order; // 주문 id
}

 

[PaymentHistory Entity]

@Getter
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "payment_history")
public class PaymentHistory {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long paymentHistoryId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "payment_id", nullable = false)
    private Payment payment;

    //TODO: enum으로 교체하기
//    private String afterStatus;

    private Boolean latestStatus;

    private LocalDateTime statusUpdatedAt; // 결제 상태 변경 일시
}

[PaymentMethod Entity]

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PaymentMethod extends BaseEntity {

    //TODO: 머지했을 떄 충돌 여부 확인
//    @ManyToOne(fetch = FetchType.LAZY)
//    @JoinColumn(name = "payment_id", nullable = false)
//    private Member member;

    @Column(nullable = false, length = 100)
    private String methodType;

    @Column(nullable = false)
    private String provider;

    @Column(nullable = false)
    private Boolean isDefault;

    //TODO: enum으로 교체하기
//    @Column(nullable = false, length = 50)
//    private String status;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "payment_id", nullable = false)
    private Payment payment;
}

 

 

📌 @Builder, @NoArgsConstructor, @AllArgsConstructor 조합의 필요성과 장점

 

Spring Boot + JPA를 사용할 때, 엔티티 클래스에서 @Builder, @NoArgsConstructor, @AllArgsConstructor를 함께 사용하는 경우가 많습니다.

이 글에서는 각각의 역할과 한계를 분석하고, 왜 함께 사용하는 것이 좋은지 알아보겠습니다.

1️⃣ @Builder의 역할과 한계

 

🔹 빌더 패턴 적용 (@Builder)

 

@Builder는 객체를 생성하는 데 있어서 빌더 패턴(Builder Pattern)을 적용합니다.

빌더 패턴은 객체를 유연하고 가독성 높게 생성할 수 있도록 도와줍니다.

 

✅ @Builder의 장점

 

✔️ 객체 생성의 유연성

• @Builder를 사용하면 필요한 필드만 선택적으로 설정하여 객체를 생성할 수 있습니다.

• 필드가 많아질수록 생성자의 파라미터 순서를 외울 필요 없이 유연하게 사용할 수 있습니다.

 

✔️ 가독성 향상

• @Builder를 사용하면 new 키워드 없이 더 명확하고 직관적인 코드로 객체를 생성할 수 있습니다.

 

❌ @Builder의 한계

 

⚠️ 기본 생성자가 자동으로 생성되지 않음

• @Builder만 사용하면 기본 생성자(@NoArgsConstructor)가 자동으로 생성되지 않습니다.

• 기본 생성자가 없으면 JPA에서 엔티티를 생성할 수 없으므로, 추가적으로 @NoArgsConstructor를 함께 사용해야 합니다.

 

⚠️ 모든 필드를 받는 생성자가 자동 생성되지 않음

• @Builder를 사용하면, 객체를 개별 필드에 대해 설정할 수 있지만,

모든 필드를 한 번에 받는 생성자는 자동 생성되지 않습니다.

• 따라서, 테스트 코드 작성 시 @AllArgsConstructor를 함께 사용하면 더 편리합니다.

2️⃣ @NoArgsConstructor와 @AllArgsConstructor가 필요한 이유

 

🔹 JPA/Hibernate에서 기본 생성자가 필요한 이유 (@NoArgsConstructor)

 

JPA(Java Persistence API)와 Hibernate는 엔티티를 관리할 때 기본 생성자(No-args Constructor) 가 필요합니다.

이는 다음과 같은 이유 때문입니다.

 

✔️ JPA가 리플렉션(Reflection)으로 엔티티를 생성하기 때문

• JPA는 데이터베이스에서 엔티티를 조회할 때 리플렉션을 이용하여 객체를 생성합니다.

• 이 과정에서 기본 생성자가 없으면 엔티티를 생성할 수 없습니다.

 

✔️ 기본 생성자를 protected로 제한하는 것이 권장됨

• 엔티티는 임의로 new 연산자로 생성하기보다는 JPA를 통해 관리하는 것이 일반적입니다.

• 따라서, 기본 생성자를 public으로 두기보다는, protected로 설정하여 외부에서 직접 생성하지 못하도록 막는 것이 좋습니다.

 

💡 📌 해결 방법 (권장)

@NoArgsConstructor(access = AccessLevel.PROTECTED)

위와 같이 설정하면 JPA에서는 엔티티를 생성할 수 있지만, 외부에서 new 키워드로 생성하는 것은 막을 수 있습니다.

🔹 모든 필드를 포함한 생성자가 필요한 이유 (@AllArgsConstructor)

 

✔️ 데이터 복제 및 복사 가능

• JPA를 사용하지 않고도, 모든 필드를 갖는 객체를 쉽게 복제할 수 있습니다.

• new 키워드를 사용하여 새로운 객체를 만들 때 유용합니다.

 

✔️ 테스트 코드 작성의 편의성

• @Builder만 사용할 경우 각 필드를 하나씩 설정해야 하므로 테스트 코드에서 불편할 수 있습니다.

• @AllArgsConstructor를 사용하면, 모든 필드를 한 번에 넣어 빠르게 객체를 생성할 수 있습니다.

 

💡 📌 해결 방법

@AllArgsConstructor

위와 같이 설정하면 모든 필드를 받는 생성자가 자동으로 생성됩니다.

3️⃣ @Builder, @NoArgsConstructor, @AllArgsConstructor 조합의 장점

 

세 개의 어노테이션을 조합하면 다음과 같은 장점을 얻을 수 있습니다.

어노테이션역할필요성

@Builder 빌더 패턴 적용 선택적 필드 설정 가능, 가독성 증가
@NoArgsConstructor(access = AccessLevel.PROTECTED) 기본 생성자 제공 JPA 엔티티 생성을 위해 필수
@AllArgsConstructor 모든 필드를 포함한 생성자 제공 테스트 코드 작성 및 복제/복사 편의성 증가

 

📌 결론

@Builder, @NoArgsConstructor, @AllArgsConstructor를 함께 사용하면 JPA 호환성을 유지하면서 객체 생성의 유연성을 극대화할 수 있습니다.

 

✅ JPA 엔티티 생성 가능 (@NoArgsConstructor)

✅ 빌더 패턴 적용하여 가독성 향상 (@Builder)

✅ 테스트 코드에서 빠르게 객체 생성 가능 (@AllArgsConstructor)

 

📌 💡 엔티티 클래스 적용 예시

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Table(name = "payment_history")
public class PaymentHistory {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long paymentHistoryId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "payment_id", nullable = false)
    private Payment payment;

    private String afterStatus;
    private Boolean latestStatus;
    private LocalDateTime statusUpdatedAt; // 결제 상태 변경 일시
}

위와 같은 조합을 사용하면 JPA 호환성을 유지하면서도, 가독성이 높고 유연한 객체 생성이 가능하다.

 

 

'뚜띠' 카테고리의 다른 글

예외처리 효과적으로 관리하는법  (0) 2025.03.13
ERD 최종 점검  (0) 2025.02.26
'뚜띠' 카테고리의 다른 글
  • 예외처리 효과적으로 관리하는법
  • ERD 최종 점검
신댕인생
신댕인생
안녕하세요!! 예비개발자 신댕입니다. 개발자를 준비하고 있는 신댕인생의 하루하루를 정리하고 있어요. 파이팅!
  • 신댕인생
    신댕인생
    신댕인생
  • 전체
    오늘
    어제
    • 분류 전체보기 (127)
      • 다시 준비 (0)
        • 계획(ISTJ) (0)
        • 정보처리기사 (0)
        • SQLD (0)
        • Toeic Speaking (0)
        • 일일 회고 (0)
      • 데브캠프 일지 (52)
        • 예제 (6)
        • 연습문제 (12)
        • 과제 (2)
        • 칠판 정리 (1)
        • 숙지용 필기 (11)
      • 책 (12)
        • Clean Architecture (2)
        • 개발자도 궁금한 IT 인프라 (1)
        • JVM 밑바닥까지 파헤치기 (9)
      • DB (23)
        • 숙지용 필기 (12)
        • SQL 쿼리 실습 (7)
        • 극장 시스템 모델링 (3)
      • 토이 프로젝트 2 (7)
      • 토이 프로젝트 3 (0)
      • 뚜띠 (3)
      • 회고 (0)
        • 주간 회고 (0)
        • 월간 회고 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    ERD
    백엔드 부트캠프
    spring
    연습문제
    패스트캠퍼스
    머신러닝 교과서
    쿼리 실습
    SQL
    패스트캠퍼스 부트캠프
    패스트캠퍼스 데브캠프
    지네릭스
    jvm
    JPA
    자바의 정석
    spring의 정석
    패스트 캠퍼스
    부트캠프
    남궁성
    데브캠프
    sql의 정석
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
신댕인생
결제 관련 생성
상단으로

티스토리툴바