처음에는 아무 생각 없이 트리거 쿼리문을 작성하였고 작성하다 보니 만약 트리거를 수정하거나 변수처럼 쓰고 싶은 값이 생긴다면 어떡하지? 라는 의문이 들었다.
트리거 쿼리문을 db에 작성하는 것보다 server 코드 단에서 처리하는 것이 유지보수 측면에서 더 좋다고 생각을 했고
그래서 Spring Boot에서 트리거와 같은 기능을 수행할 수 있는 방법을 찾아본 결과 @EntityListener가 있었다. EntityListener는 jpa 컨텍스트 내에서 데이터의 변화가 발생할 때 동작한다 라는 것을 모두 구현을 해놓고 테스트 하는 과정에서 알게 되었다. 현재 설계에서 메시지를 보낼 때 일어나는 데이터의 변화는 spring application이 아니라 외부 java application과 php에서 일어나고 있기 때문에 EntityListener를 사용할 수 없는 환경이었다.
무작정 기술을 사용하는 것보다 공부하고 사용해야 하는 이유이다..
그래서 어쩔 수 없이 트리거 쿼리문을 mysql 서버에 create 하는 방식으로 사용할 수 밖에 없었다.
따라서 g5_shop_order 테이블에서 insert 이벤트가 발생했을 때 telegram_msg 테이블에 이와 관련된 데이터를 넣고 spring boot 애플리케이션에서는 @Scheduled 어노테이션을 활용해 1초에 한번씩 이 테이블을 확인하면 is_uploaded 가 false인 데이터를 찾아 메시지를 전송하도록 하였다.
트리거 예제
DELIMITER //
CREATE TRIGGER after_insert_g5_shop_order_ordered
AFTER INSERT ON g5_shop_order
FOR EACH ROW
BEGIN
INSERT INTO telegram_msg (`key`, msg_info, is_updated)
VALUES (
'ordered',
JSON_OBJECT(
'amount', (NEW.od_card_amount + NEW.od_cash_amount),
'orderer', NEW.od_name,
'od_id', NEW.od_id
),
0
);
END //
DELIMITER ;
이 과정에서 원격 db 서버를 사용하다 보니 현재 로그인된 계정으로는 trigger 를 설정 할 수 없는 문제가 있었다.
이는 log_bin_trust_function_creators 가 비활성화 되어 function이나 trigger 생성에 대한 제약을 강제하기 때문에 오류가 발생했었다. 그래서 root 계정을 가지고 있는 관리자분께
SET GlOBAL log_bin_trust_function_creators = 1;
명령어를 통해 on 으로 변경을 요청드렸고 trigger를 정상적으로 등록할 수 있었다.
- 함수를 생성할 때는 함수의 특성을 명시해야 하는데, 이 중에서 DETERMINISTIC, NO SQL, 또는 READS SQL DATA 중 어떤 것도 선언에 포함되지 않았기 때문에 오류가 발생.
- MySQL은 함수의 실행 방식을 판단할 수 없어서 보안상의 이유로 해당 함수의 생성을 막는 것.
- log_bin_trust_function_creators는 MySQL 설정 중 하나로, 바이너리 로깅( MySQL 서버에서 변경된 데이터베이스 내용을 기록하는 메커니즘입니다)과 관련된 옵션.
- log_bin_trust_function_creators = 0: (기본값) 이 설정을 사용하면 MySQL에서 DETERMINISTIC, NO SQL, 또는 READS SQL DATA 선언 없이 함수를 생성할 수 없다. 이렇게 설정되어 있을 때, 보안상의 이유로 해당 함수의 생성이 제한.
- 위 값을 1로 바꾸면 새로 등록한 함수가 바이너리 로그에 기록되기 때문에, 보안 측면에서 주의가 필요. 따라서 먼저 함수에 DETERMINISTIC, NO SQL, 또는 READS SQL DATA와 같은 옵션을 추가하는걸 권장한다.