문제 상황
현재 프로젝트에서 환불처리가 되지 않았다.
환불처리의 로직은 외부 API를 통해 환불을 요청하며 그 후에 DB에 데이터를 환불 상태로 변경하는 로직이다. 하지만 Front를 통하여 서버로 API 요청을 해보니 카드 취소 메시지는 정상적으로 왔으며, (환불 API는 정상적으로 요청이 되었으나 ) DB에 데이터를 환불 상태로 변경하는 부분에서 에러가 발생하여 서버에서는 500에러를 발생하였다.
분명 로컬에서 환불 테스트를 하고 merge를 시켰으며 코드 자체는 데이터의 상태 변경 코드이기 때문에 비교적 쉬운 코드라 이해하지 못한 부분도 없으며, 코드를 다시 확인해 보아도 잘못한 부분이 없었다.
에러 메시지는 아래와 같이 출력되었다.
2024-04-02T21:44:07.989+09:00 WARN 1 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1265, SQLState: 01000
2024-04-02T21:44:07.989+09:00 ERROR 1 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : Data truncated for column 'status' at row 1
문제 정의 & 해결 방법
해당 에러는 등록된 자료형의 범위를 벗어난 큰 데이터를 넣으면 발생하는 에러이다.
예를들어 int 자료형에 varchar이 들어가는 경우이다.
insert문이 잘리긴 했지만 데이터가 정상적으로 들어가려다가 롤백된것으로 확인이 된다.
enum 클래스 @Enumerated(EnumType.STRING)로 정의하였기 때문에 데이터의 범위가 초과된다는게 조금 이상하였다.
그래서 로컬을 통하여 create DDL을 확인해보았다.
아래는 enum class를 통한 jpa의 create ddl 예시문이다.
create table `payment` (`payment_id` bigint not null, `status` enum ('OK','READY','CANCEL','REFUND'), primary key (`payment_id`))
이것을 코드와 주석으로 설명하면 아래와 같다.
PaymentStatus.enum
public enum PaymentStatus {
OK, // 결제 완료 : 0
READY, // 결제 대기 : 1
CANCEL // 결제 취소 : 2
}
Payment.java (Entity Class)
@Enumerated(EnumType.STRING)
private PaymentStatus status;
// `status` enum ('OK','READY','CANCEL','REFUND')
private PaymentStatus status;
// `status` tinyint check (`status` between 0 and 2)
이전의 나는 결제 취소와 환불이 같다고 생각하고 이전에 이런식으로 작성을 했다.
public enum PaymentStatus {
OK, // 결제 완료
READY, // 결제 대기
CANCEL // 결제 취소
}
하지만 결제 취소와 환불은 다르다고 생각했다. 결제 취소는 결제 도중에 이탈한 것으로 보고 ( 이는 주문 시간을 설정하여 주문 시간이 초과하면 결제 취소로 판단한다. ) 결제 환불은 결제를 정상적으로 완료하였지만 고객의 변심이나 서비스에 대해 만족을 느끼지 못하고 결제를 취소하는 것이라고 정의했다.
public enum PaymentStatus {
OK, // 결제 완료
READY, // 결제 대기
CANCEL, // 결제 취소
REFUND // 결제 환불 + 추가
}
여기서 enume 칼럼에 대한 ddl 문이 변경이 되지 않아서 현재의 MySql의 enum 데이터 타입 칼럼 크기가 ENUM('OK', 'READY', 'CANCEL') -> ENUM('OK', 'READY', 'CANCEL', 'REFUND')으로 변경이 되지 않아서 3번째 enum 요소가 존재 하지 않아서 SQL Error: 1265, SQLState: 01000 에러를 발생한 문제라고 정의하였다.
참고로 현재의 spring application.yml 파일의 DDL 설정은 update이며 update는 엔티티 클래스에 새로 추가된 필드에 대해서는 ddl 문이 새로 생성이 되지만 주의할 점이 있다는 것을 알게 되었다.
1. 기존 엔티티 클래스의 필드에 대한 DDL 문은 지원을 하지 않는다.
이는 내가 기대했던 것이 enum 클래스를 수정하면서 enum 칼럼 크기에 대한 설정이 변경될 것으로 기대하였지만 크기에 대한 설정이 변경되지 않은것을 말한다.
2. 기존 엔티티 클래스의 필드가 삭제되어도 테이블의 데이터는 삭제되지 않는다.
이는 JPA를 설계할 때부터 데이터의 안정성을 위해서 이렇게 설계한 것이라고 생각하면 된다.
참고로 현업에서는 DDL 설정을 vaildate, none를 사용한다.
그래서 직접 칼럼을 수정해주었다.
나의 경우에는 이런식으로 작성해주었다.
ALTER TABLE payment
MODIFY COLUMN status ENUM('OK', 'READY', 'CANCEL', 'REFUND');
결과적으로 프로젝트 에러가 해결이 잘 되었다.
글을 마무리 하며
찾아보아도 자료가 많이 없어서 바로 해결하진 못하였지만 enum entity에 대한 기본이 잡혀있어서 잘 생각해서 풀어낸 것 같다.
해당 에러에 대한 포스팅이기보다는 해당 에러와 enum 클래스 그리고 spring ddl과 관련된 복합적인 에러라는 생각이 든다.
테스트 서버에서 배포 시에 나와 똑같은 에러가 발생했다면 해당 포스팅을 보고 부디 잘 해결하셨으면 좋겠다.
'JAVA & Spring > Error' 카테고리의 다른 글
[Spring] java.lang.IllegalArgumentException: Name for argument of type 에러 해결 방법 (0) | 2024.04.10 |
---|---|
[Spring] Could not find build 에러 해결 방법 (0) | 2024.04.10 |
[QueryDSL][Spring] Unable to load class 'javax.persistence.Entity' 에러 해결 방법 (0) | 2024.03.04 |
[Spring][Postman] 400 Bad Request 오류 해결 방법 (0) | 2023.09.05 |
[Spring][Postman] Could not send request 오류 해결 방법 (0) | 2023.08.24 |
댓글