엄마한테 빌려준 돈 못 받고 울분에 차서 잠자리를 뒤척이다가 생각난 것을 글로 써봅니다.

 

다음의 기능이 필요하다고 가정하겠습니다.

 

- 라이믹스 게시판의 글 목록에 관여하는 기능이 필요합니다. (상점: 공지 설정, 글 제목 색상 지정, 내용 치환 등)

- 퀴즈: 님이 개발자라면 이 기능을 개발할 때 게시판에 어떻게 간섭 하겠습니까?

 

object cache 이야기 하지 않고 php opcache (=include) 접근만 하겠습니다.

  1. 애드온을 제작하고 관리자 설정에서 작동 범위를 대상 게시판으로 설정한다.
  2. 전역 트리거를 집어넣는다: moduleHandler.init 또는 moduleHandler.proc
  3. 게시판 트리거를 넣는다: act:board.dispBoardContent

답을 생각하셨다면 스크롤을 내려주세요.

-

답 그런거 없고요, 그냥 하고 싶은대로 하면 됩니다. 성능 차이는 어차피 미미하거든요.

 

하지만 님이 변태스러운 코딩 쉽덕후라면? 고민이 필요할지 모릅니다.

 

이렇게 설계하면 어떨까요?

  • module.xml / update / install 시점의 트리거는 없습니다.
  • 유저가 구매한 아이템(예: 공지 설정, 글 제목 색 지정, 내용 치환 등)을 활성화하면 act:board.dispBoardContent 트리거가 켜지고 관련 메소드가 연결됩니다.
  • 연결된 그 메소드는 활성화된 아이템이 없을 때 트리거를 끕니다.

include 하는 꼼수도 있겠지만, RXE에서 지향하는 범용적인 단독 모듈이라면 이 방법 괜찮다는 생각이 듭니다.

 

코어에서 조건부 트리거를 지원해주면 환상적이겠지만,, 안 될거야 이건 아마..

  • profile

    필요할 때만 addTriggerFunction() 하면 그게 조건부 트리거죠.

    물론 이 트리거를 넣을지 뺄지 결정하기 위한 최초 1회의 트리거는 미리 등록되어 있어야 합니다. 현재 접속한 유저가 특정 아이템을 구매했는지 여부에 따라 공용으로 사용하는 트리거 DB에서 계속 insert/delete하는 것은 더 비효율적이니까요.

    정답은 없지만 오답은 있습니다. act가 dispBoardContent일 때만 실행하도록 한다면, 게시판이 아닌 곳(예: 메인화면 위젯, 사이드바 위젯, 작성 글 보기, 서드파티 자료가 제공하는 개인 프로필 화면 등)에서 글 목록을 불러올 때는 작동하지 않겠지요. 예외가 발견되거나 새 자료가 출시될 때마다 일일이 땜빵하는 불상사를 피하려면, document.getDocumentList처럼 act와 무관하게 공통적으로 사용하는 경로에 트리거를 걸어두는 것을 추천합니다.

  • profile ?
    제 표현력이 부족한거 같습니다.
    게시판 위주 커뮤니티라 가정하면 dispboardcontent 에 걸든 getdocumentlist 에 걸든 전역에 걸든 애드온에 걸든 결국 어디든 걸리긴 걸립니다.
    기능을 조금 틀어서 공지 영역에 나올 “인기글”을 가정해보죠.
    인기글이 없다면 view 트리거를 지웁니다.
    (추천 등의 시점에) 인기글이 생겼다면 view 트리거를 생성합니다.
    php-fpm 자원을 고려한 고급 기법이라 생각됩니다.
    트리거를 걸지 않으므로 마치 img[loading=lazy] 기법을 php 에 사용하기 때문입니다.

    제 취지를 이해하셨다면 이 기법은 db trigger 의해서만 구현 가능합니다. 그리고 지적해주신 오답도 제 글을 잘 이해한 개발자에겐 별로 중요한 부분은 아닐거라 생각됩니다.
  • ? profile

    고급 기법이라기보다는, opcache가 존재하지 않던 시절에 만들어진 micro-optimization인 것 같습니다.

    트리거 호출을 위한 클래스를 인클루드할 때 php-fpm에 더해지는 부하는 0이라고 가정해도 무방합니다. 해당 클래스는 이미 opcode로 컴파일하여 메모리에 적재되어 있고, 해당 주소로 포인터만 연결해 주면 되기 때문입니다. 반면, DB에서 뭔 짓을 해도 부하가 0이라고 가정하기는 힘들죠. 만약 동일한 부하가 발생하더라도 WAS를 증설하는 것이 DB를 증설하는 것보다 훨씬 쉽고요.

    라이믹스 최신 버전에 포함된 주요 모듈들을 기준으로, 구 트리거(현 이벤트 핸들러)는 모듈 install/update 메소드에서 DB에 하나씩 등록하지 않고, module.xml에서 선언합니다. 명령형에서 선언형으로 패러다임을 바꿔 버린 거죠. 유저가 micro-optimization에 신경쓸 필요 없도록 하고, 코어 개발팀의 필요에 따라 내부 구조를 마음대로 갈아엎을 자유를 얻기 위해서입니다. 엘카님이 사용을 제안하시는 레거시 DB 트리거 등록/삭제 API는 하위호환성 보장을 위한 최소한의 껍데기만 남게 될 가능성도 있다는 뜻입니다.^^

  • profile ?

    시간 들여 답변 주셔서 고맙습니다.
    제 고민의 핵심은 전역(또는 전역에 가까운 dispboardcontent, getdocumentlist) 트리거가 누적되면서 사이트 성능이 점점 감소되는 현상을 어떻게 완화할지 그 방법을 생각하고 있었습니다.
    그 맥락에서 최초 1회 트리거 조차 걸리지 않고 필요한 때만 걸리는 방법을 고민 했습니다.
    "최초 1회의 트리거는 미리 등록"하더라도 다수 php-fpm 운용되는 환경에서 메소드가(=트리거가) 연결되면 object cache(=memcached) 의해 데이터를 확인하는 내부 망 요청이 발생하는데 이 부하는 0은 아니며 모듈이 누적될 수록 부하는 증가만 하고 나아지지 않습니다.
    고성능 라우터, 고성능 memcached 를 "돈으로 땜빵"하는 것이 간단하고 인건비보다 저렴하지만 그건 그거고 저 같은 쉽덕후는 그것만으로 만족하지 않을 수 있거든요.
    그러나 제가 고민했던 - 트리거가 필요한 시점에 켜지고 필요 없는 시점에 꺼지는 - 답이 적절치 않은 점을 포함해서 말씀 주신 내용 모두 공감하고 동의합니다.
    결론적으로 제가 고민한 답은 틀렸습니다, 그러나 제 고민에 대한 답을 얻지는 못했네요.
    생각을 깨워주신데 감사 드립니다.

  • ? profile
    다른 것들 다 제쳐두고 include 의 부하만 따져본다고 해도,
    조건이 활성화 된 상황에서만 트리거를 추가하는 것이 문제를 해결해 줄 수 있는건가요?

    0에 수렴하는 include 에 따른 부하를 신경써야 할 정도의 상황이라면,
    "조건과 무관하게 활성화되는 트리거"가 문제가 아니라 "트리거 그 자체"가 문제가 되지 않을까요?

    그 정도로 빡빡하게 최적화 해야 하는 상황이라면,
    웬만한 것들은 백엔드 단에서 처리할 게 아니라 프론트 단에서 처리할 수 있는 만큼 처리하는게 맞다고 보고,
    더 나아가서는 라이믹스, PHP를 사용하지 않아야ㅠ 하는게 아닐까 싶습니다..
  • profile ?
    말씀하신 대로 include 는 opcache 에서 잘 처리해주며 0 에 수렴하고 게다가 php-fpm 별로 분산처리가 가능합니다.
    include 이후 get object cache 작동이 들어갈텐데 그건 제가 바라는게 아닙니다.
    get object cache 자원이 (memcached 서버의 cpu,memory,lan) 고갈되지 않는 99.9% 이상 사이트는 object cache 로컬에서 사용하므로 제 말은 99.9% 이상 무의미합니다.
    "그냥 하고 싶은대로 하면 됩니다. 성능 차이는 어차피 미미하거든요."
    말장난 된 거 같아 죄송합니다, 다음에는 신중하게 글을 쓰겠습니다.