기타

모듈 보일러플레이트

추천 수 2 댓글 8
Extra Form
자료 소개 라이믹스 모듈 제작을 위한 보일러플레이트 입니다.
설치 경로 설치자료 아님
테스트 환경 Rhymix 2.0
라이선스 GPL v2
Github https://github.com/rx-apps/boilerplate
이름 버전 날짜 다운수
boilerplate-fb50f83.zip - 2022-09-02 12

Boilerplate

GitHub

라이믹스 모듈의 보일러플레이트 입니다.

작성 지침

명명

  • 모듈 이름은 기능을 잘 설명할 수 있는 이름으로 작성합니다. 독특한 이름을 사용하지 않도록 하고, 그러한 이름이 필요한 경우 모듈 설정을 통해 사용자가 직접 지정할 수 있도록 합니다.
  • 모듈 클래스 이름은 언더바(_) 를 최대한 적게 사용하되, 언더바 사용을 줄이기 위해 단어를 구분하지 않는 등 가독성을 해치는 행위는 비권장합니다.
  • DB 테이블 (스키마) 이름은 복수형으로 합니다.
  • DB 쿼리 이름은 getTable, getManyTables, getManyTablesWithPagination, insertTable, updateTable, upsertTable, deleteTable 으로 합니다.

타입 지정

  • 모든 메서드는 파라미터 타입과 리턴 타입을 명시해야 합니다. 단, PHP 7.0 에서 지원하지 않는 타입의 경우 생략합니다.
  • getModel, getController 와 같이 IDE가 추적하기 힘든 함수를 통해 타 모듈 클래스를 참조할 경우, 주석을 통해 타입을 명시해야 합니다.
  • 모듈 내부에서 본인 모듈의 타 클래스틑 참고할 경우 $this->getModel() 과 같은 메서드로 주석 작성 없이 이용할 수 있습니다.

트리거

  • 트리거는 전부 controller 에 등록됩니다.
  • 깔끔한 관리를 위해 트리거를 처리하는 메소드의 이름에 trigger 접두사를 붙이는 것을 권장합니다.

stdClass

  • stdClass 를 이용해야 하는 경우, new stdClass() 보다는 (object) [] 를 권장합니다.

쿼리

  • executeQuery, executeQueryArray 의 결과값에 오류가 있다면, \Rhymix\Framework\Exceptions\DBError 예외를 던지도록 합니다.
  • 오류가 없을 경우 WithPagination 쿼리인 경우, datapage_navigation 이 포함된 객체를, 그렇지 않은 경우 data 값만을 반환하도록 합니다.
  • upsert 쿼리를 사용할 경우, upsert 이외의 사용처가 없더라도 insert, update 쿼리를 함께 생성해 두는 것을 권장합니다.

템플릿 사용

  • loop, cond 등 HTML 속성으로 적용되는 템플릿 문법은 사용하지 않는 것을 원칙으로 합니다. 단, 속성에 조건문을 설정하는 attr|cond 형태는 허용합니다.
  • {@ // <!--suppress CheckEmptyScriptTag, HtmlUnknownTag, HtmlUnknownAttribute --> } 를 파일 상단에 추가합니다.
  • 주석을 작성할 경우, HTML 기본 주석보다 {@ // <!-- document --> } 형태로 작성하는 것을 권장합니다.

언어파일 작성 지침

전역 지침

  • $lang->module_name_foobar: 모든 항목에 module_name_접두사를 붙입니다.
  • $lang->module_name_txt_foobar: 일반 텍스트는 txt_ 접두사를 붙입니다.
  • $lang->module_name_tit_foobar: 제목(보편적으로 hn 태그)에 사용되는 텍스트는 tit_ 접두사를 붙입니다.
  • $lang->module_name_btn_foobar: 버튼에 사용되는 텍스트는 btn_ 접두사를 붙입니다.
  • $lang->module_name_lbl_foobar: 입력값의 라벨으로 사용되는 텍스트는 lbl_을 붙입니다. 입력값의 라벨이 아니더라도 주변 요소들과의 통일을 위해 붙일 수 있습니다.

기본 정보

  • $lang->module_name_title: 모듈의 이름을 작성합니다.
  • $lang->module_name_description: 모듈의 설명을 작성합니다. 사용하지 않을 경우 작성하지 않아도 무방합니다.

관리자 페이지

  • $lang->module_name_admin_foobar: 관리자 페이지에서 사용되는 모든 항목에 admin_접두사를 붙입니다.
  • $lang->module_name_admin_menu_foobar: 관리자 페이지 상단에 출력되는 메뉴들의 이름은 menu_ 접두사를 붙입니다.

라이선스

  • GPLv2 라이선스를 따릅니다. 누구든지 포크할 수 있으며, 자유롭게 이용할 수 있습니다.
  • 단, rx-apps 의 공식 자료가 아닌 경우, 관리자 페이지의 대시보드에 포함된 (광고) 항목을 제거하고 이용하세요.
  • profile
    {@ // <!--suppress CheckEmptyScriptTag, HtmlUnknownTag, HtmlUnknownAttribute --> }

    를 붙이는 이유가 뭔가요?

     

    그리고

    new stdClass() 보다는 (object) [] 를 권장하시는 이유가 있나요?

  • profile ?

    Jetbrains IDE가 쓸데없는? 경고를 띄우지 않게 하려고 사용합니다.
    파일 내 suppress 주석을 넣어주면 IDE에서 제공하는 경고 항목을 숨김처리 할 수 있어요.

     

    load, include, block 과 같은 XE용 태그나, loop, cond 같은 속성 때문에...

     

    스크린샷 2022-09-04 오전 1.19.36.png

     

    화면이 안이쁩니다 (?)

     

     

    ---

    (object) [] 를 권장한 이유는 가독성 때문입니다.

     

    $obj = new stdClass();

    $obj->a = 1;

    $obj->b = 2;

    $obj->c = 3;

    $obj->d = 4;

    $obj->e = 5;

     

    보다는

     

    $obj = (object) [

      'a' => 1,

      'b' => 2,

      'c' => 3,

      'd' => 4,

      'e' => 5

    ];

     

    가 쓰기도 편하고, 읽기도 편하죠.

    필요에 따라 $obj = (object) [ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 ]; 로 한줄에 집어넣어도 가독성을 크게 해치지 않구요.

    캐스트에 들어가는 비용보다 읽고 쓰기 편함에서 오는 장점이 크다고 판단했습니다.

  • ? profile
    new stdClass부분은 유저들이 편한 방법은 다 따로 있습니다.

    저도 애초에 $args->module_srl 이렇게 치는게 더 편하지 특수문자 많이 눌러야 하는 array문법을 쓰기엔 너무 지쳐요.

    ' 따옴표도 많이 들어가고,

    그리고... 애초에 array그대로 넘겨두 되는데 object화 시키는 거라면, 굳이 그렇게 제한하면서 쓰고싶진 않을 것 같아요 ㅎㅎ;;

    예시를 알려주는 것이지만.. 표준에 맞춘다면 코딩스탠다드로 하나로 제한하는 것보다 풀어주는 것이 맞을 것 같아요.

    이미 라이믹스 신기능 추가할때도 new stdClass를 사용하는 경우도 많답니다..ㅎㅎ
  • profile ?
    저는 애초에 stdClass 를 좋아하지 않는 편입니다.
    객체로 사용하려면 그 구조를 클래스, 인터페이스, 주석 등등.. 어떠한 방식으로든 명시하는게 옳다고 생각합니다.

    또, 아직은 작성하지 않았지만 추후 이와 연관된 내용을 적용하기 위한 지침이기도 합니다.
    라이믹스에서 네임스페이스가 도입되었으니, 정말 객체로 사용해야 할 친구들은 별도 클래스를 선언하도록 할 예정입니다.
    특히 함수 파라미터로 받아들이는 객체|배열 형태의 변수들에 적극 활용할 예정이구요.

    특수문자를 입력하느냐, 변수명을 입력하느냐 정도는 개인 취향이고, 선악이 없는 이야기지만...
    (사실 따옴표 두번이냐 달러 한번이냐 차이고, IDE 자동완성까지 고려하면 배열이 입력량이 더 적습니다.)

    타입스크립트의 any 는 언젠간 정확하게 명시해야할 대상이고, any 만으로 떡칠해두면 그건 악이라고 봐도 무방하겠지요.
    PHP의 stdClass 도 동일하다고 생각합니다. 급하게 stdClass 를 쓸 수는 있지만 결국 정형화해야 하는 대상이고,
    정형화하지 못하는 자유분방한 데이터는 애초에 배열로 사용하는게 바람직할 것입니다.

    물론 '권장사항' 이지, 지키지 않는다고 해서 제재를 당하는 것도 아닐거구요.
    제가 아닌 다른 사람이 사용하게 된다면 권장사항을 무시해도 누가 뭐라 하겠습니까.
    애초에 "내가 이걸 지켜가며 만들거니 잊지 말자!" 의 목적이 더 큰 것 같습니다. 겸사겸사 몇가지 유틸리티 메서드가 들어가 있으니 공유도 해보는거구용..ㅎㅎ
  • ? profile

    네네 근데 배열을 다시 (object)으로 넘겨주고 있어서 그 부분의 의아한거라 말씀드린것이였어요.

    라이믹스용이라면 굳이 object으로 넘겨줄 이유도 없고 array으로 넘겨주면 되거든요 ㅎㅎ

    어차피... (object)으로 변환한건 결국은 stdClass으로 만든거랑 같은 이치라서... 그래서 의문을 품었던 것이예요.

     

    말씀주신대로 정량화를 하기위해서는 사실은 object class 를 새로 생성하여 response 를 담당하도록 하는 것이 맞는거죠 ㅎㅎ

     

    그런 의문이 있어서 말씀드린 것이였고 말씀주신 부분에 대해서 저도 동의하는 바 입니다 ㅎ

     

    권고사항을 좀 더 주의를 주는 부분으로 착각하여 반론을 제기했었는데 잘못 알아보고 말씀드려서 죄송해요!

  • profile

    수고하셨습니다.^^


    이걸 표준으로 삼기를 원하신다면 몇 가지만 보완 요청드려도 될까요?

    • 라이믹스 2.0 기준으로 getModel(), getController() 함수는 아예 사용하지 않는 것을 추천합니다. ModuleModel::getInstance() 처럼 클래스명을 직접 참조하여 싱글턴을 받아 쓰는 문법이 가독성도 훨씬 좋고, IDE에서 반환 타입도 잘 인식합니다. 단, new ModuleModel() 이렇게 생성자를 직접 호출하면 안 됩니다.
    • 라이믹스 2.0 기준으로 model 클래스의 메소드는 대부분 static으로 선언하는 것을 추천합니다. 굳이 인스턴스를 생성할 필요가 없는 유틸리티 메소드가 많기 때문입니다. $oMemberModel 이런 임시 변수를 할당하는 것보다 그냥 MemberModel::getMemberInfo($member_srl) 이게 더 간결하고 좋잖아요.
    • 라이믹스 2.0 기준으로 쿼리할 때 stdClass 대신 연관배열을 그대로 넘겨주어도 됩니다. 굳이 (object)로 바꿀 필요가 없어요. 오브젝트를 넘기면 연관배열로 다시 바꿔서 쓰기 때문에 오히려 비효율적입니다...
    • 라이믹스/XE 템플릿 문법에서 실제로 출력되지 않는 주석을 작성하는 가장 간결한 방법은 <!--// 주석 --> 입니다. HTML 주석 안에 PHP 주석을 넣으면 알아서 삭제해 줍니다.
    • module.xml 작성시 주의해야 할 점이나 일반적인 관례를 안내해 주신다면 많은 도움이 될 것 같습니다. 모듈명 부분 중간에 대문자가 들어가면 안 된다거나, standalone 속성 등 XE 때부터 헷갈리는 부분이 많거든요.
    • 보안을 위해 모든 템플릿 상단에 <config autoescape="on" /> 을 넣는 것을 추천합니다. 이 기능은 라이믹스뿐 아니라 XE 1.11에서도 호환됩니다.
  • profile ?
    static::getInstance() 너무 좋습니다ㅠㅠ 연관배열도 너무 좋아요... 언제 그렇게 바뀌었대요...ㅎㅎ

    모델 클래스의 메서드를 static 으로 선언하는건 조금 고민이 되네요...
    만약 그렇게 선언한다고 해도, 모듈 내에서는 인스턴스를 생성하는 방향으로 처리할 것 같습니다.
    거의 대다수의 타 모듈들이 static 호출을 지원하지 않는 상황이라,
    결국 스태틱/인스턴스 를 모듈에 따라 달리 선택해 사용해야 하는데, 이러면 가독성의 문제가 있을것 같아요.
  • ? profile

    코어에 포함된 model 클래스들 중 문서, 댓글, 파일, 회원 등 흔히 쓰는 기능들은 이미 대부분 static으로 선언되어 있고, 관련 소스를 손댈 일이 있을 때마다 점점 더 많이 바꾸고 있습니다. 서드파티 모듈이 다른 서드파티 모듈을 호출할 일은 많지 않을 테니, 모듈 내에서 호출하거나 코어의 기능을 호출할 때만이라도 마음껏 쓰시면 좋겠네요.

     

    그 밖에

    • Context::get('logged_info') 대신 $this->user (모듈 클래스 및 템플릿에서)
    • $this->user->isAdmin()
    • $this->user->isModuleAdmin($module_srl)
    • executeQueryArray('모듈명.쿼리명', $args, [], '결과를 받을 item 클래스명')
    • lang('모듈명.언어코드명')

    등, 편리하게 사용하시라고 만들어 놓았는데 인지도가 낮은 기능이 은근히 많아요. 예전에는 XE 호환성 때문에 기존 방식을 쓰시겠거니 했지만 이제는 그런 핑계를 댈 이유도 없게 되었지요.