# Frontend 표준 개발자 매뉴얼

# 표준 쿼리 업데이트 서버 반영 방법



# main_api 계정 사용 방법

<details id="bkmrk-..%2Fussh-dbr02-main_a"><summary>\[참고자료\]</summary>

1. [ussh를 통한 서버 접근](https://manual.dabory.com/books/quick-start/page/dabory-linux-ssh)

</details>**1) Front 개발자들이 query를 추가 및 수정하여 반영해야 할 경우   
2\) 혹은 특정한 이유로 weberp-go API 를 재시동해야 할 경우에**

**아래와 같이 조치하여 반영할 수 있습니다.  
<span style="color: rgb(241, 196, 15);">\*\* 특히 1)의 경우 query를 잘못 수정하면 전체 시스템이 다운될 수 도 있으므로 극히 주의하여야 합니다.</span>**

```bash
(1)맥북이나 git bash(윈도우)에서 해당서버의 main_api 계정으로 로그인 (ussh 사용법은 위 참고자료를 참조)
./ussh dbr02 main_api

(2)로그인후 실행 command mode에서 shell script실행
main_api-query-gitpp-weberp-go-run
```

위 명령어 실행시

- 해당 서버의 표준 query 폴더인 main\_api/weberp-queries를 gitpp해줍니다.
- Redis Memory DB를 완전히 Flush하여 초기화합니다.
- port-grab-killer 18080 명령어를 실행하여 18080 포트를 사용 중인 기존의 weberp-go 프로세스를 종료시킵니다.
- weberp-go 실행 파일을 백그라운드에서 다시 실행하여 weberp-go API를 재시작합니다.

현재 개발서버가 아닌 운영서버인 경우 query의 첫번째 실행시에만 redis의 memory cache에 넣고 실행하고 이후 실행부터는 file을 읽어내지 않도록 속도를 개선하도록 되어있습니다.

# 게시판의 사용과 커스터마이징



# 게시판의 종류와 사용방법

### <span style="color: rgb(241, 196, 15);">게시판의 종류</span>

##### **1. 표준 게시판**

- 공지형 게시판 
    - 공지사항
    - 이벤트
    - 영업문의
    - 영업문의
    - 배너/팝업
    - FAQ(자주하는질문)
    - 이용약관
    - 개인정보 보호정책
    - 마케팅 수신 동의
    - 전자금융 이용약관
    - 교환환불 정책
- 소개형 게시판 
    - 회사소개
    - 제품소개
    - 특허/인증허
    - 포트폴리오
    - 뉴스
- 문의형 게시판 
    - 티켓-1대1문의
    - 공개질문
    - 1대1문의

---

### **게시판 관리**

##### **- 게시판 구분(공지/소개/문의)**

**[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-06/scaled-1680-/o2Dimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-06/o2Dimage.png)**

모든 게시판에 대한 정보를 불러옵니다.

구분코드, PostCode, 상태, 종류설명, 카테고리 등이 포함되어 있습니다.

모든 게시판들은 psot\_type\_id를 통해 구분됩니다.

##### **- 공지형 게시판**

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-06/scaled-1680-/U6Himage.png)](https://manual.dabory.com/uploads/images/gallery/2024-06/U6Himage.png)

공지형 게시판의 자식 메뉴들이 노출됩니다.

각 메뉴에서는 해당되는 게시글들을 수정 /삭제 /복사 등 게시글 관리가 가능합니다.

공지형 게시판의 para\_name은 다음과 같습니다.

<table border="1" id="bkmrk-%EB%B6%84%EB%A5%98-para_name%28%EC%A1%B0%ED%9A%8C%29-par" style="border-collapse: collapse; width: 57.1605%; height: 267.315px;"><colgroup><col style="width: 39.17%;"></col><col style="width: 30.2973%;"></col><col style="width: 30.5137%;"></col></colgroup><tbody><tr style="height: 29.7017px;"><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">분류</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name(조회)</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name(등록)</span></td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">공지사항</td><td style="height: 29.7017px;">notice-input</td><td style="height: 29.7017px;">notice</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">이벤트</td><td style="height: 29.7017px;">event-input</td><td style="height: 29.7017px;">event</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">배너/팝업</td><td style="height: 29.7017px;"><div><div>banner-input</div></div></td><td style="height: 29.7017px;">banner</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">자주묻는 질문(FAQ)</td><td style="height: 29.7017px;">faq-input</td><td style="height: 29.7017px;">faq</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">이용약관</td><td style="height: 29.7017px;">policy-input</td><td style="height: 29.7017px;">policy</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">개인정보 보호정책</td><td style="height: 29.7017px;">privacy-input</td><td style="height: 29.7017px;">privacy</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">전자금육 이용약관</td><td style="height: 29.7017px;">e-finance-input</td><td style="height: 29.7017px;">e-finance</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">교환환불 정책</td><td style="height: 29.7017px;">refund-input</td><td style="height: 29.7017px;">refund</td></tr></tbody></table>


##### **- 소개형 게시판**

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-06/scaled-1680-/XXtimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-06/XXtimage.png)

소개형 게시판의 자식 메뉴들이 노출됩니다.

기능적인 부분은 위와 같습니다.

<table border="1" id="bkmrk-%EB%B6%84%EB%A5%98-para_name-%28%EC%A1%B0%ED%9A%8C%29-pa" style="border-collapse: collapse; width: 57.1605%; height: 178.21px;"><colgroup><col style="width: 39.17%;"></col><col style="width: 30.2973%;"></col><col style="width: 30.5137%;"></col></colgroup><tbody><tr style="height: 29.7017px;"><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">분류</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name (조회)</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name (등록)</span></td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">회사소개</td><td style="height: 29.7017px;">intro-input</td><td style="height: 29.7017px;">intro</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">제품소개</td><td style="height: 29.7017px;">production-input</td><td style="height: 29.7017px;">production</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">특허/인증서</td><td style="height: 29.7017px;"><div><div>certificatate-input</div></div></td><td style="height: 29.7017px;">certificatate</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">포트폴리오</td><td style="height: 29.7017px;">portfolio-input</td><td style="height: 29.7017px;">portfolio</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">뉴스</td><td style="height: 29.7017px;">news-input</td><td style="height: 29.7017px;">news</td></tr></tbody></table>

##### **- 문의형 게시판**

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-06/scaled-1680-/ee2image.png)](https://manual.dabory.com/uploads/images/gallery/2024-06/ee2image.png)

para\_name

<table border="1" id="bkmrk-%EB%B6%84%EB%A5%98-para_name-%28%EC%A1%B0%ED%9A%8C%29-pa-1" style="border-collapse: collapse; width: 57.1605%; height: 148.508px;"><colgroup><col style="width: 39.17%;"></col><col style="width: 30.2973%;"></col><col style="width: 30.5137%;"></col></colgroup><tbody><tr style="height: 29.7017px;"><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">분류</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name (조회)</span></td><td style="height: 29.7017px;"><span style="color: rgb(241, 196, 15);">para\_name (등록)</span></td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">상품문의</td><td style="height: 29.7017px;"><div><div>item-inquiry-input</div></div></td><td style="height: 29.7017px;">item-inquiry</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">상담 신청</td><td style="height: 29.7017px;"><div><div>contactus-input</div></div></td><td style="height: 29.7017px;">contactus</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">1대1 문의</td><td style="height: 29.7017px;"><div><div>1to1-input</div></div></td><td style="height: 29.7017px;">1to1</td></tr><tr style="height: 29.7017px;"><td style="height: 29.7017px;">공개 질문</td><td style="height: 29.7017px;"><div><div>standard-input</div></div></td><td style="height: 29.7017px;">standard</td></tr></tbody></table>

각 페이지에서 등록된 게시판들이 pro 페이지의 게시글로 노출됩니다.

# 게시판을 Pro Page에 적용하는 방법

<p class="callout info">1대1문의 (문의형 게시판)을 pro page에 적용하기</p>

##### **\[문의형 게시판 - 1대1 문의 적용하기 예제\]**

#### **1. Controller 구성**

`pro` 테마에 `Controller`를 구성합니다. `dabory/themes/pro/app/Http/Controller/etc` 디렉토리에 `OneToOneController.php`를 생성하고 메서드를 작성합니다.

#### **- 외부 API 호출 설정**

백엔드 API를 호출하고 결과를 처리하기 위해 `App\Services\CallApiService`를 사용합니다.

```
class OneToOneController extends Controller
{
    private $callApiService;


    public function __construct(CallApiService $callApiService)
    {
        $this->callApiService = $callApiService;
    }


    public function list()
    {
        $limit = (int)request('limit', 12);
        $page = (int)request('page', 1);

        $oneToOnePage = $this->callApiService->callApi([
            'url' => 'list-type1-page',    // api에 요청할 url 주소
            'data' => [                    // list-type1-page로 요청할 data
                'QueryVars' => [           // api 서버에서 Query를 식별할 수 있도록 구성한 요소들
                    'QueryName' => 'pro:my-page/post-list',   // pro/.../my-page/post-list/ 디렉토리 안의 쿼리 파일을 찾는다.
                    'SimpleFilter' => "post_code='1to1'",     // where 절에 추가
                    'SubSimpleFilter' => "image_type = 'thumb'", 
                    'IsntPagination' => false     // pagination 여부
                ],
                'ListType1Vars' => [
                    'OrderBy' => request('sort', 'mx.created_on desc')
                ],
                'PageVars' => [
                    'Limit' => $limit,
                    'Offset' => ($page - 1) * $limit
                ]
            ]
        ]);


    //    dump($oneToOnePage);


        $oneToOnePage['Page'] = new LengthAwarePaginator($oneToOnePage['Page'], $oneToOnePage['PageVars']['QueryCnt'],
            $limit, $page, ['path' => request()->url()]);
        // dump($oneToOnePage);
        return view('views.etc.1to1-list', compact('oneToOnePage'));
    }


    public function store()
    {
        $validator = Validator::make(request()->all(), [
            'post_title' => 'required',
            'post_contents' => 'required',
            'pc1' => 'required',
            'pc2' => 'required|email'
        ]);


        if ($validator->fails()) {
            notify()->error(_e('Action failed'), 'Error', 'bottomRight');
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }


        $response =  $this->callApiService->callApi([
            'url' => 'post-act',
            'data' => [
                'Page' => [
                    [
                        'Id' => 0,
                        'PostTitle' => request('post_title'),
                        'PostContents' => request('post_contents'),
                        'PostTypeId' => 6,
                        'Pc1' => request('pc1'),
                        'Pc2' => request('pc2'),
                        'Status' => '2',
                        'MemberId' => session('member')['MemberId'],
                    ]
                ]
            ],
        ]);


        if ($this->callApiService->verifyApiError($response)) {
            notify()->error($response['body'], 'Error', 'bottomRight');
            return redirect()->back();
        }


//        notify()->success(_e('Action completed'), 'Success', 'bottomRight');
        return redirect()->route('1to1.list');
    }


    public function show($id)
    {
        $listType1Book = $this->callApiService->callApi([
            'url' => 'list-type1-book',
            'data' => [
                'Book' => [
                    [
                        'QueryVars' => [
                            'QueryName' => 'pro:my-page/post-details',
                            'SimpleFilter' => "post_code='1to1' and mx.id = $id",
                            'IsntPagination' => true,
                        ],
                        'PageVars' => [
                            'Limit' => 1
                        ]
                    ],
                    [
                        'QueryVars' => [
                            'QueryName' => 'pro:my-page/post-details-prenext',
                            'SimpleFilter' => "mx.id = (select max(id) from pro_post where id < ${id} and post_type_id = 6)",
                            'SubSimpleFilter' => "",
                            'IsntPagination' => true,
                        ],
                        'PageVars' => [
                            'Limit' => 1
                        ]
                    ],
                    [
                        'QueryVars' => [
                            'QueryName' => 'pro:my-page/post-details-prenext',
                            'SimpleFilter' => "mx.id = (select min(id) from pro_post where id > ${id} and post_type_id = 6)",
                            'SubSimpleFilter' => "",
                            'IsntPagination' => true,
                        ],
                        'PageVars' => [
                            'Limit' => 1
                        ]
                    ],
                ]
            ]
        ]);


    //    dd($listType1Book);
        if ($this->callApiService->verifyApiError($listType1Book)) {
            notify()->error($listType1Book['body'], 'Error', 'bottomRight');
            return redirect()->back();
        }


//        dump($listType1Book);
        return view('views.etc.1to1-details', compact('listType1Book'));
    }
}
```

<div id="bkmrk-1%EB%8C%801%EB%AC%B8%EC%9D%98-%EA%B5%AC%ED%98%84%EC%9D%84-%EC%9C%84%ED%95%9C-control">1대1문의 구현을 위한 Controller 예시</div><div id="bkmrk-"></div><div id="bkmrk--1">  
</div><div id="bkmrk-%EC%9D%B4-%EA%B5%AC%EC%84%B1%EC%9C%BC%EB%A1%9C-list-type1-pa">이 구성으로 `list-type1-page` URL로 data가 요청되면, api 서버는 `weberp-queries`에서 해당 URL의 QueryVars에 작성해준 조건에 해당하는 SQL 파일을 찾고, 데이터로 쿼리 조건절을 구성하여 호출하고 반환합니다.</div><div id="bkmrk--2"></div>#### **응답 처리 및 View 반환**

API로부터 응답을 받아 변수에 담고, View 페이지에서 필요한 데이터를 가공하거나 변환하여 반환합니다. View 페이지에서는 반환받은 배열 데이터를 통해 페이지 작업을 수행할 수 있습니다.

#### **TEST**

Controller와 view 페이지 작업이 완료되었다면 erp/pro 각각의 페이지에서 테스트를 진행합니다.

예제에서 진행했던 1대1문의 게시판을 확인해보겠습니다.

pro 페이지에 만들어준 문의하기 게시판에서 문의글을 작성한 뒤

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/aHOimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/aHOimage.png)

erp 페이지로 이동하여 1대1문의 게시판을 확인합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/z5Iimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/z5Iimage.png)

위와같이 문의내용이 잘 들어왔습니다.

<details id="bkmrk-%EC%B0%B8%EA%B3%A0%EC%82%AC%ED%95%ADerp%EC%97%90-%EA%B2%8C%EC%8B%9C%ED%8C%90-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0"><summary>참고사항</summary>

erp에 게시판 설치하기

[erp 게시판 커스터마이징](https://manual.dabory.com/books/frontend/page/01386)

</details><div id="bkmrk-%27url%27-%3D%3E-%27list-type1"></div><div id="bkmrk-%EC%9D%B4%EC%A0%9C-%EB%B0%9B%EC%95%84%EC%98%A8-%EC%9D%91%EB%8B%B5%EC%9D%84-%EB%B3%80%EC%88%98%EC%97%90-%EB%8B%B4%EA%B3%A0%C2%A0-v"></div>

# 문의형 게시판 커스터마이징하기



# 공지형 게시판 커스터마이징하기



# 소개형 게시판 커스터마이징하기



# 게시판 커스터마이징 방법

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/lZfimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/lZfimage.png)

게시판을 커스터마징 하기 위해서는

erp 게시판 구분 메뉴에서 게시판 구분 등록을 통해 새로운 커스터마징 게시판을 등록해야합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/7jcimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/7jcimage.png)

게시판 구분 등록 예시

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/ogeimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/ogeimage.png)

게시판이 생성된 것을 확인합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/Espimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/Espimage.png)

생성해준 게시판을 사용자 메뉴에 따로 만들어주기 위해서

메뉴 확장과 API 관리 - 사용자 메뉴로 이동합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/pZIimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/pZIimage.png)

추가 버튼을 눌러 사용자 메뉴를 추가해줍니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/nvoimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/nvoimage.png)

전체 캐시삭제를 해줘야 사용자 메뉴에 반영이 됩니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-07/scaled-1680-/JFOimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-07/JFOimage.png)

새로운 사용자 메뉴가 추가됐습니다.

이제 상담내역 게시판의 crud를 구현해주기 위해서

erp의 파라메터를 만들어줍니다. 파라메터는 사용자 메뉴를 추가할때 입력했던 위치에 만들어줘야 합니다.

해당 위치로 이동하여 디렉토리를 생성하고 contatctus-custom-input.json 이라는 파라메터 파일을 생성해줍니다.

내용은 아래와 같습니다.

```
{
    "//list-type-1": "simple and plain list by query of table join",


    "General": {
        "Title": "상담내역 관리",
        "PageApi": "list-type1-page",
        "ActApi": "post-act"
    },


    "QueryVars": {
        "QueryName": "kbgolf::post/contactus-custom-input",
        "FilterName": "",
        "FilterValue": "",
        "FilterDate": "mx.official_date",
        "SimpleFilter": "pt.post_code = 'contactus-custom'"
    },


    "HeadSelectOptions": [
        {
            "Value": "xls-report",
            "Caption": "(기존)엑셀 다운로드"
        },
        {
            "Value": "custom-xls-report",
            "Caption": "엑셀 다운로드",
            "Component": "dummy",
            "Parameter": "/list/list-type1/download/contactus-custom",
            "ThemeDir": "/kbgolf/erp"
        },
        {
            "Value": "new",
            "Caption": "상담신청 등록"
        },
        {
            "Value": "multi-delete",
            "Caption": "상담신청 일괄 삭제"
        }
    ],


    "//FormVars": "FormVars[0]-caption, FormVars[1]-searchPopup",
    "FormVars": [
        {
            "ListButton": "조회",
            "DateRange": "",
            "DateNavi": "이전 | (오늘지정) | 이후",
            "Date": "자료 등록일",
            "From": "부터",
            "To": "까지",
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": "",
            "AddTotalLine": "",
            "SelectPopup": "팝업 선택(라디오 버튼)",
            "MultiPopup": "",
            "ChartPopup": "",
            "DownloadList": "",
            "ShowOnlyClosed": "",
            "Balance": "",
            "OrderBy": "표시 순서",
            "FilterOption": "검색 조건",
            "SimpleOption": "상태별 검색"
        }
    ],


    "FilterSelectOptions": [
        {
            "Value": "",
            "Caption": "=검색 조건="
        },
        {
            "Value": "mx.pc1",
            "Caption": "신청자"
        },
        {
            "Value": "mx.pc5",
            "Caption": "회원권명"
        },
        {
            "Value": "mx.pc3",
            "Caption": "거래 구분"
        },
        {
            "Value": "mx.pc4",
            "Caption": "회원권 구분"
        }
    ],


    "SimpleSelectOptions": [
        {
            "Value": "",
            "Caption": "전체"
        },
        {
            "Value": "mx.pc7='상담접수'",
            "Caption": "상담접수"
        },
        {
            "Value": "mx.pc7='상담완료'",
            "Caption": "상담완료"
        }
    ],
    "//ListType1RangeVars": "[0]-filter, [1]-component, [2]-parameter",
    "ListType1RangeVars": [
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        },
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        },
        {
            "FirstRange": "",
            "SecondRange": "",
            "ThirdRange": "",
            "FourthRange": ""
        }
    ],


    "DateNaviOptions": [
        {
            "Value": "day",
            "Caption": "일"
        },
        {
            "Value": "week",
            "Caption": "주"
        },
        {
            "Value": "month",
            "Caption": "월"
        },
        {
            "Value": "quarterly",
            "Caption": "분기"
        },
        {
            "Value": "semiannual",
            "Caption": "반기"
        },
        {
            "Value": "year",
            "Caption": "년"
        },
        {
            "Value": "all",
            "Caption": "전체"
        }
    ],


    "SelectPopupOptions": [
        {
            "Caption": "상담신청 관리",
            "Component": "kbgolf::popup.popup-form1.form-a.post.contactus-custom-form",
            "Parameter": "kbgolf::/popup/popup-form1/form-a/post/contactus-custom"
        }
    ],


    "// OrderByOptions": "OrderBy Options//첫번째 Value가 Default",
    "OrderByOptions": [
        {
            "Value": "mx.created_on desc",
            "Caption": "문의일자 역순"
        },
        {
            "Value": "mx.created_on asc",
            "Caption": "문의일자 순서"
        }
    ],


    "//BalanceOptions": "Show OnlyBalaceRemained or All",
    "BalanceOptions": [
        {
            "Value": "",
            "Caption": "전체 보기"
        },
        {
            "Value": "c10 > 0",
            "Caption": "잔량있는 것만"
        }
    ],


    "DisplayVars": {
        "IsListFirst": true,
        "IsExcelColumn": true,
        "IsSelectPopupHidden": true,
        "IsC1Popup": "1",
        "InitLines": 10,
        "HeadHeight": "140",
        "BodyHeight": "570"
    },


    "ThumbContainerVars": {
        "ListWidth": 60,
        "ListHeight": 50
    },


    "// ListVars": "ListVars[0]-caption, ListVars[1]-size(px), ListVars[2]-align->right(number) left(left)",
    "ListVars": [
        {
            "$Radio": "$Radio",
            "$Check": "$Check",
            "No": "번호",
            "C1": "신청자",
            "C2": "연락처",
            "C3": "거래구분",
            "C4": "회원권 구분",
            "C5": "회원권명",
            "C6": "희망가격",
            "C7": "요청사항",
            "C8": "상태"
        },
        {
            "$Radio": "2",
            "$Check": "2",
            "No": "2",
            "C1": "5",
            "C2": "4",
            "C3": "4",
            "C4": "5",
            "C5": "5",
            "C6": "5",
            "C7": "7",
            "C8": "4"
        },
        {
            "$Radio": "center",
            "$Check": "center",
            "No": "center",
            "C1": "center",
            "C2": "center",
            "C3": "center",
            "C4": "center",
            "C5": "center",
            "C6": "center",
            "C7": "center",
            "C8": "center"
        }
    ]
}
```

<div id="bkmrk--7"><div>  
</div>  
이제 pro 페이지와 연동하여 상담내역을 관리할 수 있는 게시판이 구성됐습니다.</div><div id="bkmrk-pro-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%81%EC%9A%A9%EC%9D%80-%EC%95%84%EB%9E%98-%EB%A7%81%ED%81%AC%EB%A5%BC-%ED%86%B5">pro 페이지 적용은 아래 링크를 통해 체크할 수 있습니다.</div><div id="bkmrk--8"></div><details id="bkmrk-%EC%B0%B8%EA%B3%A0%EC%82%AC%ED%95%ADpro-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%81%EC%9A%A9%EB%B0%A9%EB%B2%95"><summary>참고사항</summary>

[pro 페이지 적용방법](https://manual.dabory.com/books/frontend/page/pro-page)

</details>

# Api23KeyPair를 통한 양방향 통신방법



# [JavaScript] Api23KeyPair를 통한 통신방법

####  **Api23KeyPair란?**

##### **Api23KeyPair**는 HOST(GUEST로부터 API 요청을 받는 사이트)와 **GUEST(HOST의 API를**

##### **사용하는 사이트)** 간의 **안전한 데이터 통신을 위해 생성되는 암호화 키 쌍**입니다.

##### 이 키는 HOST와 GUEST 간의 통신에서 인증 및 권한 확인 역할을 하며, 민감한 데이터를 교환할 때 이를 안전하게 보호합니다.


####  **API23JS란?**

##### **API23JS**는 **GUEST 사이트의 JavaScript**에서 **HOST 사이트의 API**를 사용하기 위한 권한 키입니다. 여기서 **HOST**는 데이터를 요청받아 처리하고 반환하는 **부모 사이트**이며,  
**GUEST**는 데이터를 요청하는 **자식 사이트라고 하겠습니다.**

##### 예를 들어 예시에서는 아래와 같이 정해놓고 진행하겠습니다.

- ##### **HOST**: `opticalpos`
- ##### **GUEST**: `eyemsg`

####  **HOST 설정방법**

1\. HOST가 될 사이트의 통합설정으로 이동합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/YQLimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/YQLimage.png)

<span style="color: rgb(241, 196, 15);">\* 사이트별로 메뉴명이 상이할 수 있습니다.</span>

2\. Api23 KeyPair Encrypted 메뉴를 클릭합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/V23image.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/V23image.png)

3\. ①, ②를 순서대로 클릭하여 Api23eKeyPair를 생성합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/9edimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/9edimage.png)

4\. 편집기를 실행하여 HOST(예시에서는 opticalpos)의 .env파일로 이동합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/kdBimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/kdBimage.png)

4-1. 혹은 command에서 vi 편집기를 통해 .env 파일을 열어줍니다.

5\. env파일에 API23E\_KEY\_PAIR 변수안에 Api23 KeyPair Encrypted 메뉴에서 생성한 Api23eKeyPair 값을 추가해줍니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/aXtimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/aXtimage.png)

6\. [링크](https://opticalpos.daboryhost.com/dabory/myapp/list-type/type1?bpa=eyJtZW51X25hbWUiOiJBUEkyMy1BcHAiLCJtZW51X2NvZGUiOiI2MDAwMDAiLCJkaXNhYmxlX2xfbWVudSI6IjAiLCJlbmFibGVfcl9tZW51IjoiMCIsInBlcm1pc3Npb24iOnsiaXNfbXltZW51IjoiMCIsImlzX2xpc3QiOiIxIiwiaXNfcmVhZCI6IjEiLCJpc19jcmVhdGUiOiIxIiwiaXNfdXBkYXRlIjoiMSIsImlzX2RlbGV0ZSI6IjEiLCJpc19uZXd0YWIiOiIwIn0sInBhZ2VfdXJpIjoiXC9kYWJvcnlcL215YXBwXC9saXN0LXR5cGVcL3R5cGUxIiwicGFyYV9uYW1lIjoiXC9saXN0XC9saXN0LXR5cGUxXC9hcGkyMy1hcHAtaW5wdXQiLCJ0aGVtZV9kaXIiOiIiLCJtYWluX2FwcF9pZCI6MCwiZ3Vlc3RfYXBwX2lkIjowLCJjdXN0b21fdmFyIjoiIn0=)를 클릭하여 myapp API23-Apps로 이동합니다.

7\. 아래와 같이 차례대로 버튼을 클릭합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/iW2image.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/iW2image.png)

8\. 아래와 같이 SSO App의 Api23 Keys를 생성할 수 있는 모달창이 열립니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/Sclimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/Sclimage.png)

App Type : App의 타입을 지정합니다. js를 통해 함수를 사용하여 통신할 것 이기 때문에 js로 하겠습니다.

Sort : 앱의 종료에 대해서 선택합니다. CRM을 기준하로 하기 때문에 표준 CRM인 KingkongCrm을 선택하겠습니다.

OriginUrl : geust로 사용할 url을 입력합니다.

9\. Generate New Api23 Keys 버튼을 클릭하여<span style="color: rgb(224, 62, 45);"> Api23Key</span>를 <span style="color: rgb(224, 62, 45);">생성</span>후 <span style="color: rgb(224, 62, 45);">값을 복사하여 메모장에 붙여넣습니다.</span> (추후 HOST Api를 사용하기 위해서 필요합니다.)

10\. Save 버튼을 통하여 입력한 값들을 반드시 저장합니다.

####  **GUEST 설정방법**

1\. <span style="color: rgb(224, 62, 45);"> **HOST 생성방법**</span> 3번에서 생성해준 <span style="color: rgb(224, 62, 45);">API23eKeyPair</span> 값을 HOST와 동일하게 GUEST의 프로젝트 <span style="color: rgb(224, 62, 45);">.env</span> 파일에도 동일하게 넣어주겠습니다.

<span style="color: rgb(241, 196, 15);">\* 'api23key'키가 아니라 'API23eKeyPair'키를 넣어야합니다.</span>

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-11/scaled-1680-/JzEimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-11/JzEimage.png)

2\. 편집기를 열고 <span style="color: #e03e2d;">**GUEST**</span> 사이트의 FrontEnd(dbrerp)에서 HOST의 API를 사용하려는 view 페이지로 이동합니다.

예시에서는 eyemsg의 right.blade.php 파일에 아래와 같이 script를 추가하겠습니다.

```javascript
<script src="/js/dabory.data-linker.js?serverUrl=https://opticalpos.daboryhost.com&api23Key=Nx4QebHKTssjDuP0AKude0IMZWnak0O0hb1SJ5C3PCUuPK0oRxAVAclS5/I6Zs4cO1Czr8DDrR2LNw/uJpwmzibLTYvsH54ThO5lVLs8ifHllF0fenDeHGL1R6Tuv+KJMQGQGt//HhRLrNKRyrXsx2wN1ZSUtPrpkvEQLC+DE/O0xPxYqBXqM80EaRJ+K1qrTQFkVKMwcTEv"></script>
```

<div id="bkmrk-%EC%9C%84-script%EC%9D%98-src-%EC%86%8D%EC%84%B1%EC%97%90%EC%84%9C-d">위 script의 src 속성에서 dabory.data-linker.js에 ServerUrl에 HOST 사이트인 opticalpos url을 넣고 api23Key에 <span style="color: rgb(224, 62, 45);">**HOST 생성방법**</span> 9번에서 생성해준 <span style="color: rgb(224, 62, 45);">Api23Key</span>를 파라미터로 넣습니다.</div><div id="bkmrk--11"></div><div id="bkmrk-%2A-dabory.data-linker"><span style="color: rgb(241, 196, 15);">\* dabory.data-linker.js는 GUEST에서 HOST와 통신할 수 있도록 구현된 함수를 모아둔 파일입니다.</span></div><div id="bkmrk--12"></div><div id="bkmrk--13"></div>####  **dabory.data-linker.js 사용방법**

<div id="bkmrk--14"></div>```javascript
<script src="/js/dabory.data-linker.js?serverUrl=https://opticalpos.daboryhost.com&api23Key=Nx4QebHKTssjDuP0AKude0IMZWnak0O0hb1SJ5C3PCUuPK0oRxAVAclS5/I6Zs4cO1Czr8DDrR2LNw/uJpwmzibLTYvsH54ThO5lVLs8ifHllF0fenDeHGL1R6Tuv+KJMQGQGt//HhRLrNKRyrXsx2wN1ZSUtPrpkvEQLC+DE/O0xPxYqBXqM80EaRJ+K1qrTQFkVKMwcTEv"></script>
    <script>
        $('#open-signup-popup').on('click', function () {
            if (! window.passwdPolicy) {
                $.fn.dataLinker.api23Js('setup-get', {
                    'SetupCode': 'passwd-policy',
                    'BrandCode': 'member'
                }, function (response) {
                    window.passwdPolicy = response
                    $('#policy-desc-em').text(window.passwdPolicy['PolicyDesc'])
                    // console.log(window.passwdPolicy)
                    $('#join').modal('show');
                })
            } else {
                $('#join').modal('show');
            }
        });
    </script>
```

<div id="bkmrk-1%EB%B2%88-%EC%A4%84-%3A">1번 줄 :</div><div id="bkmrk---dabory.data-linker">- `dabory.data-linker.js` 스크립트를 로드합니다. 이 스크립트는 `serverUrl`과 `api23Key` 파라미터를 통해 API 호출을 처리할 서버와 인증 키를 설정합니다.</div><div id="bkmrk--15"></div>5번줄 :

- window.passwdPolicy가 존재하는지 확인후 없을 경우 `dabory.data-linker.js`에서 제공하는 `api23Js` 메서드를 사용해 `setup-get` HOST의 API를 호출합니다.
- 호출 시, 요청 데이터(`SetupCode`와 `BrandCode`)를 GUEST로 전송하여 API에서 필요한 비밀번호 정책 정보를 가져옵니다.

이렇게 API23JS는 HOST와 GUEST간의 안전한 데이터 통신을 가능하게 합니다.

- **HOST는 API23E\_KEY\_PAIR를 생성하고 API23\_KEY를 발급**하여 GUEST에게 제공합니다.
- GUEST는 **API23\_KEY를 사용해 HOST API를 호출**하여 필요한 데이터를 가져옵니다.  
    이를 통해 HOST의 API 데이터를 GUEST 사이트에서 효율적으로 사용할 수 있습니다.

# [WEB] Api23KeyPair를 통한 통신방법

#### **Api23KeyPair란?**

##### **Api23KeyPair**는 HOST(GUEST로부터 API 요청을 받는 사이트)와 **GUEST(HOST의 API를**

##### **사용하는 사이트)** 간의 **안전한 데이터 통신을 위해 생성되는 암호화 키 쌍**입니다.

##### 이 키는 HOST와 GUEST 간의 통신에서 인증 및 권한 확인 역할을 하며, 민감한 데이터를 교환할 때 이를 안전하게 보호합니다.

# [Native-App] Api23KeyPair를 통한 통신방법

#### **Api23KeyPair란?**

##### **Api23KeyPair**는 HOST(GUEST로부터 API 요청을 받는 사이트)와 **GUEST(HOST의 API를**

##### **사용하는 사이트)** 간의 **안전한 데이터 통신을 위해 생성되는 암호화 키 쌍**입니다.

##### 이 키는 HOST와 GUEST 간의 통신에서 인증 및 권한 확인 역할을 하며, 민감한 데이터를 교환할 때 이를 안전하게 보호합니다.

# [JavaSript] OwnerKey 사용하기

1\.

# 백엔드 설치 방법

> ## <span class="notion-enable-hover" data-token-index="0">설치전 준비사항</span>

- <span class="notion-enable-hover" data-token-index="0">다보리 Git Server 사용자 등록 ([다보리 깃 서버 바로가기](http://git.daboryhost.com:10880/))</span>

---

> ## 웹서버에 백엔드(main\_api) 설치하기

1\. 서버에 로그인합니다.

2\. home 디렉토리로 이동하여 백엔드를 설치해줄 디렉토리를 생성합니다.

예제에서는 main\_api로 지정했습니다.

```bash
cd /home
mkdir main_api
```

3\. 생성해준 main\_api 디렉토리로 이동합니다.

```bash
cd main_api
```

4\. 다보리 git server에 mybin 레포지토리로 이동합니다. ([mybin 바로가기](http://git.daboryhost.com:10880/dabory/mybin))

5\. HTTP url을 복사합니다.

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-08/scaled-1680-/ZVYimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-08/ZVYimage.png)

6\. git clone을 통해 mybin을 가져옵니다.

```bash
git clone http://git.daboryhost.com:10880/dabory/mybin.git
```

7\. mybin이 설치되었는지 확인합니다.

8\. 정상적으로 설치되었다면 다음 명령어를 통해 간편하게 설치할 수 있습니다.

```
./init-weberp-go-install-in-main_api
```

위 명령어 실행시 다보리 컴포저블의 백엔드 어플리케이션 패키지를 설치합니다.

\* 만약 스크립트 파일이 실행되지 않는다면 아래 명령어를 통해 실행권한을 부여합니다.

```bash
cd mybin
chmod +x init-weberp-go-install-in-main_api
```

다시 main\_api 디렉토리로 이동하여 명령어를 실행합니다.

```bash
cd ..
./init-weberp-go-install-in-main_api
```

9\. 설치가 완료되었다면 아래 디렉토리들이 존재하는지 확인합니다.

(1). cache-key-pair

(2). weberp-go

(3). weberp-queries

10\. 설치가 완료되었습니다. 백엔드 앱을 실행하겠습니다.

아래 명령어를 통해 실행 스크립트 파일을 실행합니다.

```
./mybin/without-update-weberp-go-run
```

[![image.png](https://manual.dabory.com/uploads/images/gallery/2024-08/scaled-1680-/fFMimage.png)](https://manual.dabory.com/uploads/images/gallery/2024-08/fFMimage.png)

11\. 백엔드 서버가 성공적으로 실행되었습니다.

#####  백엔드 설치항목

- cache-key-pair
- wheberp-go
- weberp-queries
- mybin

#####  참고자료

- [cache-key-pair란?](https://manual.dabory.com/books/frontend/page/cache-key-pair)

# cache-key-pair란?

> ## cache-key-pair

다보리 컴포저블에서는 중요 DB 접속정보는 libsodium 의 PKI 방식으로 암호화하므로 Front/Backend 서버의 어떤 장소든 DB 접속정보를 사람이 확인할 수 있는 없는 방법으로 저장합니다. 강력한 2중 3중의 암호화 장치를 통하여 DB에 대한 강력한 보안이 제공됩니다. 각 단위 DB 정보를 PKI 로 암호화할때 KeyPair 는 일반적으로 DaborySSO에 저장이 되어 있는데 SSO서버에 많은 트래픽이 걸리거나 일반 Backend 서버와 DaborySSO 와의 통신의 장애가 있을 경우 일반 Backend도 다운된 것 처럼 DB 접속을 안되는 경우가 발생할 수 있습니다. 이 상황을 방지하고 서버의 속도를 증가시키기 위해 KeyPair 정보를 한번더 암호화 하여 Backend의 정해진 폴더에 저장하고 통상적인 접속의 경우 DB 접속정보를 다시 복호화 할 수 있도록 합니다.

해당 Backend 서버가 한번이라도 접속했던 DB정보의 libsodium 으로 암호화한 KeyPair 정보를 다시 한번 암호화한 정보를 해쉬화한 화일이름으로 전환하여 저장한 폴더가 cache-key-pair 로서 삭제시 자동으로 DaborySSO 접속하여 해당 내용을 재생성할 수 있도록 구성되어 있습니다.

cache-key-pair 파일에 캐시된 key-pair 값이 저장됩니다. 더 자세한 사항은 아래 참고자료를 참고하시기 바랍니다.

#####  참고자료

- [다보리 rest api의 구성](https://manual.dabory.com/books/quick-start/chapter/2-restfull-api)
-