다보리 API Documents
- 공통 API 가이드
- 다보리 LOGIN-API
- Protocol22-API
- 개요
- Protocol22-API 목록
- Protocol22-API 사용 함수 목록
- [JavaScript] Protocal22-API 사용예제
- [WebApp] Protocal22-API 사용예제 (PHP)
- [WebApp] Protocal22-API 사용예제 (GoLang)
- OwnerKey를 활용한 게시판 연동 예제
- STRONG-API
공통 API 가이드
사전준비 사항
APP 등록하기
다보리 SSO
다보리SSO는 다보리가 제공하는 다보리 계정으로 로그인할 수 있도록 지원하는 OAuth 2.0 기반의 인증 서비스입니다.
APP 등록하기
다보리 API를 사용하하기 위해서는 다보리 APP이 필요합니다. APP은 다보리 API에 등록한 서비스 정보입니다. 각 APP은 다보리 API 요청 허가(Authorization) 여부를 판단하는 데 사용하는 정보인 GateToken을 요청하는데 필요한 고유의 Client ID와 Client Secret을 갖습니다. 다보리SSO에서 APP을 등록하는 방법은 다음과 같습니다.
1. 다보리SSO에서 메뉴에서 My APP 메뉴를 클릭합니다.
2. 좌측 메뉴에서 App Manager를 클릭합니다.
3. 우측 상단의 List 옆 화살표 버튼을 클릭 -> 레코드 추가 버튼을 클릭합니다.
4. 아래 설명을 참고하여 a~h까지 차례대로 입력합니다.
App info and Single-Sign-On
ⓐ App Type : app의 type을 선택합니다.
ⓑ App Name : 등록할 app의 name을 작성합니다.
ⓒ Redirect URI : 등록할 app의 Redirect_URI (account server에서 사용자 인증 이후 callback)
ⓓ Client ID, Client Secret : app별로 생성되는 고유 key 값입니다.
API/DB connection info - generate .env.dabory and Dabory Keypair
ⓔ API Host : 연동할 main api 서버의 host 선택
ⓕ DB Host : 연동할 db 서버의 host
ⓖ DB User : 연동할 db 서버의 username과
ⓗ DB Name : 연동할 db 서버의 dbname
ⓘ DB Password : 연동할 db server의 password
ⓙ Key Pair : key pair는 어떤걸 선택해도 무방합니다.
6. save 버튼을 클릭하면 아래와 같이 설정파일이 생성됩니다.
7. 편집기를 통해 생성된 파일이 열어 내용을 확인합니다. 생성된 변수들은 다음과 같습니다.
MAIN_API_URL=''
MAIN_API_CLIENT_ID=''
MAIN_API_CLIENT_SECRET=''
MAIN_API_BEFORE_BASE64=''
MAIN_API_OWNER_KEY=''
8. FRONTEND에서 config 파일에 위 변수들과 값을 추가합니다.
그 이후의 과정
* 로그인 버튼 클릭시 백엔드에서 account url의 파라미터 url 생성 (
ex : https://accounts.dabory.com/o/oauth2/authorize?client_id=ysTHfKT4noL-xaJkbc&redirect_uri=https://visionnote.eyerecord.co.kr/wp-login.php&response_type=code&scope=all&state=tUhPBnu5RFOpCPm8lRBMayCSe5FKBRuG) 하여 요청
* app 등록시 app_manager에 등록했던 Redirect_URI에서 callback 함수 구현
* 위 변수들을 통해 MAIN_API_URL에 등록된 dabory main_api server에서 token을 발급(token 발급받는 함수 구현)
* 발급받은 token은 인증이 필요한 모든 request의 header에 포함됩니다.
PAP-API
시작하기 전에
이 문서는 다보리 앱에서 개별 Table 단위의 데이터 처리를 위한 API 구조를 정의하는 방법을 설명하고 있습니다. PAP-API의 구조는 기본적으로 아래와 같습니다.
- Pick(단일 데이터 추출)
- Act(데이터의 추가, 수정, 삭제)
- Page(다수의 row 추출)
API URL 네이밍 규칙
PAP-API 호출시 데이터를 사용하려는 해당 테이블명에 -pick, -act, -page를 붙여 공통적으로 api url을 네이밍하고 있습니다.
예를들어
- item 테이블에서 특정 상품 하나의 정보를 불러오고 싶다면 url은 item-pick
- member 테이블에서 특정 회원의 정보를 불러오고 싶다면 url은 member-pick
- item 테이블에 특정 상품을 추가, 삭제, 수정하고 싶다면 url은 item-act
- member 테이블에서 특정한 status(휴면회원)인 회원 page를 불러오고 싶다면 member-page
- member 테이블에 특정회원을 추가하고 싶다면 member-act (Id : 양수)
- member 테이블에 특정회원을 삭제하고 싶다면 member-act (Id : 음수)
pick-api 사용예제
쿼리의 WHERE 절에 유니크한 값인 Id로 조회하여 단일데이터 및 다수의 레코드를 추출할 수 있는 api입니다.
php
$itemPick = $this->callApiService->callApi([
'url' => 'item-pick',
'data' => [
'Page' => [
['UpdatedMd5' => $updatedMd,]
],
],
'headers' => [
'GateToken' => $this->gateToken['main']
]
]);
javascript
const response = await axios.post('/ajax/get-data', {
url: 'item-pick',
data: {
Page: [
{ Id: parseInt(window.User['SgroupId']) }
]
}
});
act-api 사용예제
Insert, Update, Delete와 같은 데이터 작업을 수행합니다. Id의 값에 따라 Insert(0), Update(양수), Delete(음수)로 구분합니다.
만약 Id값이 0보다 큰 양수라면 해당 Id값에 해당하는 데이터를 Update합니다.
Delete는 다른 필드 없이 ID 값만으로 처리할 수 있습니다.
php
// insert
$itemAct = $this->callApiService->callApi([
'url' => 'item-act',
'data' => [
'Page' => [
[
'Id' => 0, // 0 : insert, 양수: update, 음수 : delete
'IgroupId' => 526,
'ItemCode' => Str::limit($linkproMd5, 21, ''),
'ItemSlug' => $linkproMd5,
'ItemName' => $scrap['ItemName'],
'SalesPrc' => (string)$scrap['SalesPrice'],
]
],
],
'headers' => [
'GateToken' => $this->gateToken['main']
]
// update
$itemAct = $this->callApiService->callApi([
'url' => 'item-act',
'data' => [
'Page' => [
[
'Id' => 4, // 0 : insert, 양수: update, 음수 : delete
'IgroupId' => 526,
'ItemCode' => Str::limit($linkproMd5, 21, ''),
'ItemSlug' => $linkproMd5,
'ItemName' => $scrap['ItemName'],
'SalesPrc' => (string)$scrap['SalesPrice'],
]
],
],
'headers' => [
'GateToken' => $this->gateToken['main']
]
// delete
$itemAct = $this->callApiService->callApi([
'url' => 'item-act',
'data' => [
'Page' => [
[ 'Id' => -4 ] // 0 : insert, 양수: update, 음수 : delete
],
],
'headers' => [
'GateToken' => $this->gateToken['main']
]
const response = await axios.post('/ajax/get-data', {
url: 'item-act',
data: {
Id : 0,
ItemCode: $(item_form).find('#item-code-txt').val(),
IgroupId: Number($(item_form).find('#igroup-id-txt').data('id')),
ItemName: $(item_form).find('#item-name-txt').val(),
SubName: $(item_form).find('#sub-name-txt').val(),
ItemSlug: $(item_form).find('#item-slug-txt').val(),
}
});
const response = await axios.post('/ajax/get-data', {
url: 'item-act',
data: {
Id : 3,
ItemCode: $(item_form).find('#item-code-txt').val(),
IgroupId: Number($(item_form).find('#igroup-id-txt').data('id')),
ItemName: $(item_form).find('#item-name-txt').val(),
SubName: $(item_form).find('#sub-name-txt').val(),
ItemSlug: $(item_form).find('#item-slug-txt').val(),
}
});
const response = await axios.post('/ajax/get-data', {
url: 'item-act',
data: {Id : -3}
});
page-api 사용예제
하나의 SELECT 쿼리로 테이블의 레코드를 2차원 리스트 형태로 가져옵니다.
Query, Asc, Desc, Limit, Offset 등의 파라미터를 통해 request할 data의 필터링을 설정합니다.
php
$this->callApiService->callApi([
'url' => 'app-guest-page',
'data' => [
'PageVars' => [
'Query' => "app_name = '$appName' and is_on_use = 1",
'Limit' => 1,
]
],
'headers' => [
'GateToken' => $this->gateToken['main']
]
javascript
let response = await get_api_data('setting-search-page', {
QueryVars: {
QueryName: 'igroup',
FilterName: 'dbr_igroup.id',
},
PageVars: {
Limit: 9999,
Offset: 0,
}
})
// get_api_data(url, data)
다보리 LOGIN-API
개요
개요
다보리 로그인은 OAuth 2.0을 기반으로 한 사용자 인증 서비스로, 외부 애플리케이션에서도 다보리 계정을 활용하여 간편하게 로그인할 수 있도록 지원합니다. 별도의 계정 생성이나 비밀번호 입력 없이 다보리 아이디만으로 빠르고 안전하게 접속할 수 있어, 회원가입 절차가 번거롭거나 기존 계정을 잊어버려 불편을 느끼는 사용자들의 이탈을 방지하는 데 도움이 됩니다. 보다 편리한 사용자 경험을 제공하고 싶다면, 다보리 로그인을 활용해보세요.
로그인 절차
1. Daobry 로그인 버튼 클릭시 Dabory 로그인 페이지로 이동
2. 다음버튼 클릭시 비밀번호 입력 페이지로 이동
3. 다음버튼 클릭시 APP 등록에 입력했던 redirect_url을 호출
4. CallBack 함수에서 로그인절차 실행
5. Dabory 로그인 완료
Protocol22-API
개요
PROTOCOL22-API
PROTOCL22는 다보리SSO에서 OwnerKey를 활용하여 MAIN APP과 GUEST APP간의 API를 공유하여 특정 API에 접근하는 방식입니다.
OwnerKey란?
PROTOCAL22-API를 사용하기 위해서는 OwnerKey 발급이 필요합니다.
여기서 OwnerKey는 APP 등록시 main APP에 등록된 API 서버와 DB 접근 권한이 설정된 암호화 KEY입니다.
발급된 OwnerKey를 guest APP에 저장하여 PROTOCL22-API를 사용할 수 있습니다.
OwnerKey 발급방법
1. main app을 등록한 dabory 계정으로 로그인합니다.
2. guest app 등록을 위해서 My App 메뉴를 클릭합니다.
3. 좌측 메뉴에서 App Manager를 클릭합니다.
4. 등록한 app중 Owner key를 공유할 app을 클릭합니다.
5. GuestApp 탭을 클릭합니다.
6. a부터 c까지 입력 및 선택합니다.
ⓐ Guest App Name : Owner Key의 이름
ⓑ OwnerCode : Owner Key의 제한방식
- owner : 모든 api 허용
- keypair :
- dbupdate :
- limited : 일부 api만 허용
ⓒ AppType : guest app의 type
7. Download .owner-key 버튼을 클릭하여 Owner key를 download 합니다.
8. MainApp 탭을 누른뒤 save 버튼을눌러 저장합니다.
9. 생성된 .owner-key를 확인하고 frontend 소스코드를 open합니다.
10. .env 파일에 MAIN_API_OWNER_KEY 변수를 추가하고 생성된 owner key의 값을 넣어줍니다.
Protocol22-API 종류
1. Javascript (js 방식)
2. GO (webapp 방식)
3. Laravel (webapp 방식)
js방식과 app방식의 차이점
구분 | Javascript | WebApp |
호출 | 프론트엔드(브라우저) | 백엔드(Laravel, Go) |
목적 | Guest APP에서 직접 API 요청 | 서버간 api 요청 (Backend to Backend) |
호출방식 | $.fn.ownerKeyLinker.ownerApp() 호출 | callOwnerApi() 호출 |
OwnerKey 저장 | 스크립트에 직접입력 | 특정 변수에 저장후 session 활용 |
인증방식 | OnwerKey를 직접 포함하여 API 요청 | GateToken을 세션에서 불러와 API 요청 |
보안 | 상대적으로 낮음 (클라이언트에서 호출) | 상대적으로 높음(서버에서 요청) |
사용예제 | <script> 태그로 js 라이브러리 로드후 호출 | Laravel, Go 등의 서버 코드에서 API 호출 |
Protocol22-API 목록
Protocol22-API는 다양한 요청을 처리할 수 있는 API 목록을 제공합니다. 각 요청 URL과 메서드, 응답 형식, 그리고 그에 대한 설명을 아래에 정리하고, 각 요청에 대한 더 자세한 설명을 추가하겠습니다.
요청 URL |
매서드 |
응답 형식 |
설명 |
/printing-curr-price | post | json | |
/printing-curr-price | post | json | |
/projects | get | json | |
/projects | post | json | |
/projects | post | json | |
/projects/{id} | get | json | |
/projects | delete | json | |
/after-base64 | post | json | |
/send-images | post | json | |
/text-send | post | json | |
/gate-token-get | post | json | |
/call-owner-api | post | json | |
/owner-token-get | post | json | |
/auth/send-emailConfirm | post | json | |
/auth/send-smsConfirm | post | json | |
/auth/signup | post | json | |
/item-url-scrap | post | json | |
/gate-token-get-test | post | json | |
/call-api | post | json | |
/send/text | post | json | |
/send-mail | post | json | |
/test-send-mail | post | json | |
/elasticsearch | post | json | |
/elasticsearch-dsl | post | json |
Protocol22-API 사용 함수 목록
Javascript
1. ownerApp
JavaScript에서 API를 호출할 때는 ownerApp() 함수를 사용할 수 있습니다. ajax를 사용하여 API 요청을 보낼 때 사용됩니다.
$.fn.ownerKeyLinker.ownerApp = function (url, request, callback, async = true) {
getParameter();
$.ajax({
// ${$.fn.ownerKeyLinker.serverUrl} : script 파라미터 url에 입력한 serverUrl
url: `${$.fn.ownerKeyLinker.serverUrl}/dabory-app/${url}`, //ex. https://www.daborysso.com/dabory-app/auth/signup
data: JSON.stringify(request),
beforeSend: function (xhr) {
xhr.setRequestHeader('OwnerKey', $.fn.ownerKeyLinker.ownerKey);
},
method: 'POST',
dataType: 'json',
async: async,
})
.done(function (json) {
callback(json);
})
.fail(function (json, textStatus, errorThrown) {
callback(json);
iziToast.error({ title: 'Error', message: 'Dabory Owner App Error' });
});
};
url : main app의 도메인/dabory-app/api url ( ex. www.daborysso.com/dabory-app/auth/signup)
request : 서버로 전송할 요청데이터 (JSON형식)
callback : 응답을 처리할 콜백함수
async : 요청의 동기/비동기 여부 (기본값 true -> 비동기 요청)
beforeSend: 요청 이전에 setRequestHeader를 통해 OwnerKey를 header에 넣음.
2. ownerApi
JavaScript에서 API를 호출할 때는 ownerApi() 함수를 사용할 수 있습니다. ajax를 사용하여 API 요청을 보낼 때 사용됩니다.
$.fn.ownerKeyLinker.ownerApi = function (url, request, callback, async = true) {
getParameter(); // $.fn.ownerKeyLinker.serverUrl과 $.fn.ownerKeyLinker.ownerKey를 추출하는 함수
$.ajax({
url: `${$.fn.ownerKeyLinker.serverUrl}/dabory-app/call-owner-api`,
data: JSON.stringify(request),
beforeSend: function (xhr) {
xhr.setRequestHeader('OwnerKey', $.fn.ownerKeyLinker.ownerKey);
xhr.setRequestHeader('Url', url);
},
method: 'POST',
dataType: 'json',
async: async,
})
.done(function (json) {
callback(json);
})
.fail(function (json, textStatus, errorThrown) {
callback(json);
iziToast.error({ title: 'Error', message: 'Dabory Owner API Error' });
});
};
url : main app의 도메인/dabory-app/call-owner-api ( ex. www.daborysso.com/dabory-app/call-owner-api)
request : 서버로 전송할 요청데이터 (JSON형식)
callback : 응답을 처리할 콜백함수
async : 요청의 동기/비동기 여부 (기본값 true -> 비동기 요청)
beforeSend: 요청 이전에 setRequestHeader를 통해 OwnerKey와 url을 header에 넣습니다.
OwnerApi vs OwnerApp
두 함수는 모두 다보리 API와 통신하는 역할을 하지만 요청을 처리하는 방식과 목적이 다릅니다.
두 함수에서 호출할 수 있는 API 목록은 링크를 참고해주시기 바랍니다.
OwnerApp :
함수의 이름에서 알 수 있듯이 Js를 통한 APP과 APP간의 통신입니다. 예를들어 게스트 앱에서 메인 앱의 휴대폰 인증코드나 이메일 인증코드 발송 API를 호출하여 게스트 앱에서 해당 인증코드를 활용할 때 사용할 수 있습니다.
OwnerApi :
게스트앱에서 메인앱의 API를 호출하여 필요한 데이터를 반환받을 때 활용할 수 있습니다. 예를들면 메인앱에 저장된 비밀번호 정책이나 가입한 회원 목록, 메인앱으로 회원가입 하기, 메인앱에서 회원 중복체크 등등 DB와 직접적으로 연동된 API를 호출할 수 있습니다.
[JavaScript] Protocal22-API 사용예제
시작하기 전에
이 문서는 Dabory Protocol22-API for JavaScript를 사용하여 Main App과 Guest App을 개발할 때 필요한 참고 정보를 제공하며 JavaScript를 활용한 클라이언트 측 API 호출 방식을 설명합니다.
예제실행전에 아래 준비사항들을 반드시 준비해주시기 바랍니다.
- script 다운로드
- app 등록하기
JavaScript 방식의 API 호출 흐름
1. 클라이언트 측 JavaScript에서 OwnerKey 및 MAIN APP의 URL 정보를 설정합니다.
2. JavaScript에서 ownerApp() 함수를 사용하여 API 요청을 보냅니다.
3. API 응답을 받아 클라이언트 측에서 데이터를 처리합니다.
JavaScript 사용예제 (회원가입 구현)
script 선언과 변수설정
javascript 방식에서는 script src 속성의 파라미터 url로 ServerUrl과 OwnerKey를 직접 입력합니다.
<script src="/js/dabory.owner-key-linker.js?serverUrl=https://www.daborysso.com&ownerKey=zEUhgZEpPbFpz/cIghtYCsoFlNi8JX3Lh45ank1s+w2PGuK4phOxmemgKuuIJ/OQZlrpdSzlK03MpBLBSo1o537brbDPKaq9ydK8QK8JgEAYGKSNzD8W6dJhSIjPfxLJu+cma0wcAMDmSV7DMhwwgiwVb2ADWu+QOVKpU+VmIR1TBIfT00EPpuW1Ju+jop8WcBEJRrpEAGLK5jcRnAGSXaDTumqEVsLRSq87hVqRJGImIE7Bf68Ix4b2PqgVhTUY1Bpalw=="></script>
<script src="/js/dabory.owner-key-linker.js?serverUrl=&ownerKey="></script>
serverUrl : MAIN APP의 도메인주소를 입력합니다.
ownerKey : MAIN_APP 등록시 발급받은 OwnerKey를 입력합니다.
API 요청 함수(OwnerApp)
JavaScript에서 API를 호출할 때는 ownerApp() 함수를 사용할 수 있습니다. ajax를 사용하여 API 요청을 보낼 때 사용됩니다.
$.fn.ownerKeyLinker.ownerApp = function (url, request, callback, async = true) {
getParameter();
$.ajax({
// ${$.fn.ownerKeyLinker.serverUrl} : script 파라미터 url에 입력한 serverUrl
url: `${$.fn.ownerKeyLinker.serverUrl}/dabory-app/${url}`, //ex. https://www.daborysso.com/dabory-app/auth/signup
data: JSON.stringify(request),
beforeSend: function (xhr) {
xhr.setRequestHeader('OwnerKey', $.fn.ownerKeyLinker.ownerKey);
},
method: 'POST',
dataType: 'json',
async: async,
})
.done(function (json) {
callback(json);
})
.fail(function (json, textStatus, errorThrown) {
callback(json);
iziToast.error({ title: 'Error', message: 'Dabory Owner App Error' });
});
};
url : API 요청의 엔드포인트( ex. www.daborysso.com/dabory-app/auth/signup)
request : 서버로 전송할 요청데이터 (JSON형식)
callback : 응답을 처리할 콜백함수
async : 요청의 동기/비동기 여부 (기본값 true -> 비동기 요청)
beforeSend: 요청 이전에 setRequestHeader를 통해 OwnerKey를 header에 넣습니다.
API 요청 함수(OwnerApi)
JavaScript에서 API를 호출할 때는 ownerApi() 함수를 사용할 수 있습니다. ajax를 사용하여 API 요청을 보낼 때 사용됩니다.
$.fn.ownerKeyLinker.ownerApi = function (url, request, callback, async = true) {
getParameter(); // $.fn.ownerKeyLinker.serverUrl과 $.fn.ownerKeyLinker.ownerKey를 추출하는 함수
$.ajax({
url: `${$.fn.ownerKeyLinker.serverUrl}/dabory-app/call-owner-api`,
data: JSON.stringify(request),
beforeSend: function (xhr) {
xhr.setRequestHeader('OwnerKey', $.fn.ownerKeyLinker.ownerKey);
xhr.setRequestHeader('Url', url);
},
method: 'POST',
dataType: 'json',
async: async,
})
.done(function (json) {
callback(json);
})
.fail(function (json, textStatus, errorThrown) {
callback(json);
iziToast.error({ title: 'Error', message: 'Dabory Owner API Error' });
});
};
url : API 요청의 엔드포인트( ex. www.daborysso.com/dabory-app/call-owner-api)
request : 서버로 전송할 요청데이터 (JSON형식)
callback : 응답을 처리할 콜백함수
async : 요청의 동기/비동기 여부 (기본값 true -> 비동기 요청)
beforeSend: 요청 이전에 setRequestHeader를 통해 OwnerKey를 header에 넣습니다.
OwnerApi 함수는 OwnerApp 함수와는 다르게 api 서버에 요청할 api url을 header에 넣습니다.
OwnerApi vs OwnerApp
두 함수는 모두 다보리 API와 통신하는 역할을 하지만 요청을 처리하는 방식과 목적이 다릅니다.
두 함수에서 사용할 수 있는 API 목록은 링크를 참고해주시기 바랍니다.
OwnerApp() |
OwnerApi() |
|
차이점 |
게스트앱에서 메인앱에 구현된 백엔드 API를 호출할때 (메인앱의 백엔드에 로직 구현 필요) |
게스트 앱에서 메인앱의 백엔드 API를 거쳐 api 서버에 구현된 api를 호출할 때 (api 서버에 구현된 로직을 호출) |
호출 흐름 | guest (frontend)-> main (backend) -> guest(frontend) | guest (frontend)-> main (backend) -> api 서버 (backend) -> guest(frontend) |
ownerApi 호출 예제
- API를 호출하여 비밀번호 정책 (passwd-policy) 데이터를 가져오는 예제입니다.
$.fn.ownerKeyLinker.ownerApi(
'remote-signup-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');
}
);
첫번째 인자값 : api 서버의 url
두번쨰 인자값 : api 서버 요청시 body에 포함될 request 객체
세번째 인자값 : response를 받아온뒤 실행될 callback 함수
ownerApp 호출 예제
- API를 호출하여 휴대폰 인증코드 (auth/send-smsConfirm)를 발송하는 예제입니다.
$.fn.ownerKeyLinker.ownerApp('auth/send-smsConfirm', {
"MobileNo": $('#mobile-no-txt').val(),
}, function (response) {
if (response['error']) {
$($this).prop('disabled', false);
SmsNumber = null;
iziToast.error({ title: 'Error', message: response['message'] });
} else {
SmsNumber = response['data'];
iziToast.success({ title: 'Success', message: '휴대전화 전송 성공' });
}
});
- API를 호출하여 이메일 인증코드 (auth/send-emailConfirm)를 발송하는 예제입니다.
$.fn.ownerKeyLinker.ownerApp('auth/send-emailConfirm', {
"Email": $('#email-txt').val(),
}, function (response) {
if (response['error']) {
$($this).prop('disabled', false);
EmailNumber = null;
iziToast.error({ title: 'Error', message: '인증메일 전송 에러' });
} else {
EmailNumber = response['data'];
iziToast.success({ title: 'Success', message: '인증메일 전송 성공' });
}
});
API를 호출하여 회원가입을 요청하는 예제입니다.
$.fn.ownerKeyLinker.ownerApp('auth/signup', {
"Email": $('#email-txt').val(),
"Password": $('#password-txt').val(),
"MobileNo": $('#mobile-no-txt').val(),
"FirstName": $('#first-name-txt').val(),
}, function (response) {
if (response['error']) {
if (response['code'] === 701) {
iziToast.info({
title: 'Info',
message: '해당 이메일은 이미 다보리 통합 회원가입이 완료되었습니다. 로그인 버튼을 눌러 바로 로그인해 주세요.'
});
} else if (response['validator']) {
showErrorMessages(response['message']);
} else {
iziToast.info({ title: 'Info', message: response['message'] });
}
click_submit_btn(self, false);
} else {
iziToast.success({ title: 'Success', message: $('#action-completed').text() });
$('#join').modal('hide');
}
});
첫번째 인자값 : main app의 백엔드 api의 url을 입력합니다.
두번쨰 인자값 : main app의 백엔드 api url입니다.
세번째 인자값 : response를 받아온뒤 실행될 callback 함수입니다.
response['error'] : api의 response status가 200이 아닐 경우 respons['error']이 반환됩니다.
[WebApp] Protocal22-API 사용예제 (PHP)
[WebApp] PROTOCOL22-API 사용예제
시작하기 전에
이 문서는 Dabory OwnerKey API for WebApp을 사용하여 Main App과 Guest App을 개발할 때 필요한 참고 정보를 제공하며
PHP Laravel을 활용한 WebApp 방식으로 PROTOCOLl22-API를 호출하는 방법을 설명합니다.
WebApp 방식의 Owner Key API 호출 흐름
1. .env 파일에 환경변수를 저장합니다.
2. Laravel callOwnerApi() 함수를 통해 Owner APP에 등록된 API 서버로 요청을 보냅니다.
3. 세션에 저장된 GateToken과 frontUrl 정보를 활용하여 API 요청을 보냅니다.
4. API 응답을 받아 데이터를 처리합니다.
WebApp 사용예제
- env 파일에 환경변수 저장
먼저 .env 파일에 OwnerKey 및 APP 정보를 설정해야합니다.
변수명은 다운로드 받은 그대로 동일하게 작성해야 하지만 설정할 MAIN APP이 2개 이상이라면
개수의 맞게 변수 끝에 _ 숫자를 입력하여 변수명을 네이밍합니다.
# [protocol22]
OWNER_APP_NAME=YOUR_OWNER_APP_NAME # Owner APP의 이름 (자유롭게 지정)
GUEST_APP_OWNER_KEY=YOUR_OWNER_KEY # Guest APP에서 발급받은 OwnerKey 입력
GUEST_APP_OWNER_URL=YOUR_OWNER_URL # Owner APP의 URL 입력 (ex.www.daborysso.com)
OWNER_APP_NAME2=YOUR_OWNER_APP_NAME_2
GUEST_APP_OWNER_KEY2=YOUR_OWNER_KEY_2
GUEST_APP_OWNER_URL2=YOUR_OWNER_URL_2
OWNER_APP_NAME3=YOUR_OWNER_APP_NAME_3
GUEST_APP_OWNER_KEY3=YOUR_OWNER_KEY_3
GUEST_APP_OWNER_URL3=YOUR_OWNER_URL_3
- OwnerKey는 GUSET APP이 MAIN APP의 API를 호출할 때 사용되는 고유한 인증 키입니다.
- WebApp 방식에서는 OwnerKey를 .env 파일에 저장하고, API 요청 시 세션을 활용하여 사용합니다.
- Laravel에서 Owner API 호출
public function callOwnerApi($request)
{
// 요청된 'type'에서 숫자를 추출 (guest[1] → 1)
preg_match('/\d+/', $request['type'], $matches);
$index = isset($matches[0]) ? (int) $matches[0] : null;
// 세션에서 API URL 및 GateToken 조회
if ($index !== null) {
$apiUrl = session("OwnerGateToken.guest")[$index]['frontUrl'] ?? null;
$gateToken = session("OwnerGateToken.guest")[$index]['gateToken'] ?? null;
}
// API 요청 URL 설정
$request['url'] = $apiUrl . '/' .$request['url'];
$request['headers'] = ['GateToken' => $gateToken];
return $this->callApi($request);
}
- API 호출 예제
API를 호출하여 remote-signup-setup-get api의 데이터를 가져오는 예제입니다.
$officeInfo = $this->callApiService->callOwnerApi([
'url' => 'remote-signup-setup-get', // api 서버에 요청할 api url
'data' => [ // 요청할 data
'SetupCode' => 'passwd-policy',
'BrandCode' => 'member',
],
'type' => 'guest[1]' // env에 저장했던 owner app이 배열로 session에 저장되기 때문에 index로 접근
]);
이제 Dabory Protocol22-API for WebApp을 활용하여 안전하게 API를 호출할 수 있습니다.
[WebApp] Protocal22-API 사용예제 (GoLang)
[WebApp] Protocal22-API 사용예제2
시작하기 전에
이 문서는 Dabory OwnerKey API for WebApp을 사용해 main app과 guest app 개발시 필요한 참고 정보를 안내합니다.
WebApp 사용예제
2. WebApp 사용 예제
📌 GateToken 발급 스케줄러
package main
func main() {
// 새로운 고루틴(Goroutine) 실행: 백그라운드에서 주기적으로 실행됨
go func() {
for {
// 1. UpdateGateTokenIfNeeded() 함수 호출 (GateToken 발급 및 업데이트)
err := controllers_func.UpdateGateTokenIfNeeded()
// 2. 만약 에러가 발생하면 로그를 남김
if err != nil {
e.ErrLog("UpdateGateTokenIfNeeded Error", err)
}
// 3. 2초 동안 대기 후 반복 (즉, 2초마다 실행됨)
time.Sleep(2 * time.Second)
}
}()
// 주의: main 함수가 종료되면 고루틴도 종료됨
select {} // main 함수가 종료되지 않도록 무한 대기
}
📌 "OwnerKey"를 활용한 GateToken, BackUrl 반환
Host의 dabory-app/gate-token-get을 호출 -> Host -> main_api (GateToken) 반환
// GateToken을 요청하는 함수
func UpdateGateTokenIfNeeded() error {
myOwnerKey := "My_OwnerKey" //OwnerKey (GateToken 발급 주체 선정을 위해 사용)
// GateToken을 요청 (OwnerKey를 사용하여 요청)
err := locals.GuestGateTokenGets(myOwnerKey)
if err != nil {
fmt.Println("GateToken 요청 실패:", err)
return err
}
return nil
}
type AppApi struct {
ApiUrl string
GateToken string
}
var GAppApis [2]AppApi // GateToken, ApiUrl 저장 장소
func GuestGateTokenGets(myOnwerKey string) error {
appType := 0 //Dbupdate
// 0:keypair, 1:Dbu // "SsoConnString" Must be Deprecated
var err error
if myOnwerKey != "" {
// e.LogStr("lskdjqfals", e.LogFuncName()+"; GuestGateTokenOwner with OwnerKey: "+myOnwerKey)
_, _, err = GuestGateTokenOwner(appType, "https://host_domain_URL.com", myOnwerKey) // app type -> OwnerCode
// Host Domain URL, OwnerKey를 매개변수로 던짐
if err != nil {
return e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err)
}
}
return nil
}
func GuestGateTokenOwner(appType int, pivotUrl string, ownerKey string) (string, string, error) { // HOST URL/dabory-app -> pivot URL
var appTypeCode string
if appType == 0 {
appTypeCode = "keypair"
} else if appType == 1 {
appTypeCode = "dbupdate"
}
if GAppApis[appType].GateToken != "" { // 할당되어 있는 경우 (이미 GateToken이 있는 경우)
// fmt.Println("34092ujfa : "+"Using GateToken in ARRAY to access : ", GAppApis[0].GateToken)
} else { // (GateToken이 없는 경우 발급 로직)
fmt.Println("34092ujfa : " + "isn't exist GateToken in ARRAY to access ")
vGt := &GateTokenGetReq{
OwnerKey: ownerKey,
}
bodyBytes, _ := json.Marshal(vGt)
frontUrl := pivotUrl + "/dabory-app/gate-token-get"
msgBytes, staInt, err := HttpResponseSimplePost("POST", frontUrl, bodyBytes)
// Strong -> Host Lalavel로 Http 요청 -> Lalavel -> main_api로 GateToken 요청
e.LogStr("23rfsr3qr-GateTokenGetReq", e.LogFuncName()+"; Raravel frontUrl : "+frontUrl)
if err != nil {
return "", "", e.ErrLog(e.FuncRun("45425fd34sd-The HTTP request "+frontUrl, e.CurrFuncName()), err)
}
if staInt != 200 {
TrackFailure() // 요청 실패 시 실패 기록 추가
fmt.Println("GateToken 요청 실패:", err, "(최근 1시간 내 실패 횟수:", len(failTimestamps), ")", "반환 Code : ", staInt)
// 최근 1시간 동안 실패 횟수가 maxFailures(3) 이상이면 프로그램 종료
if len(failTimestamps) >= maxFailures {
fmt.Println("1시간 내 GateToken 요청이", maxFailures, "번 실패 -> 스케줄러를 종료")
os.Exit(1) // 프로그램 종료
}
return "", "", errors.New(e.FuncRun("87ty344ra3-Request Fail "+string(msgBytes), e.CurrFuncName()))
}
failTimestamps = []int64{} // 성공 시 실패 기록 초기화
ret := &struct {
ApiUrl string
GateToken string
}{}
if err := json.Unmarshal(msgBytes, ret); err != nil { // GateToken과 BackendUrl을 ret 구조체에 할당
return "", "", e.ErrLog(e.FuncRun("45425fd34sd-Json Format "+frontUrl, e.CurrFuncName()), err)
}
// 새로 받은 GateToken을 전역 변수에 저장
GAppApis[appType].ApiUrl = ret.ApiUrl
GAppApis[appType].GateToken = ret.GateToken
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + appTypeCode)
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + ret.GateToken)
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + ret.ApiUrl) // main_api URL
}
return GAppApis[appType].ApiUrl, GAppApis[appType].GateToken, nil
}
📌 발급받은 GateToken을 사용하여 main_api 요청
// 🔹 API 요청을 수행하는 함수
func process() {
// 1. GateToken과 API URL 가져오기
apiUrl := locals.GAppApis[0].ApiUrl // API 요청을 보낼 기본 URL
gateToken := locals.GAppApis[0].GateToken // API 요청 시 필요한 인증 토큰
// 2. 요청할 API 엔드포인트 설정 (credit-page 요청)
mainApiURL := apiUrl + "/credit-page"
// 3. 요청 바디 구성 (전달할 데이터)
requestBody := map[string]interface{}{
"PageVars": map[string]interface{}{
"Fields": "credit_no",
"Limit": 1,
"Desc": "id",
"MyFilter": "",
"QueryCnt": 0,
"Query": "",
"Asc": "",
"Offset": 0,
"ReturnJson": "",
},
}
// 4. API 요청 실행 (GateToken 포함)
Body, err := RequestWithGateToken(mainApiURL, gateToken, requestBody)
if err != nil {
// 요청 실패 시 에러 로그 출력
e.ErrLog("API 요청 실패: ", err)
return
}
// 5. 응답 데이터 출력
fmt.Println("API 응답 데이터:", string(Body))
}
📌 저장된 GateToken으로 요청 (만료된 GateToken 재 발급)
// GateToken을 사용하여 API 요청을 보내는 함수
func RequestWithGateToken(mainApiURL string, gateToken string, requestBody map[string]interface{}) ([]byte, error) {
// 1. HTTP 요청 보내기 (기존 GateToken 사용)
resp, body, err := SendHttpRequest(mainApiURL, gateToken, requestBody)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, err
}
defer resp.Body.Close()
fmt.Println("응답 본문:", string(body)) // API 응답 출력
// 2. 응답 코드가 505라면 -> GateToken 만료 (새로운 GateToken 발급 필요)
if resp.StatusCode == 505 {
fmt.Println("GateToken 만료! 새로운 GateToken 발급 시도..")
// 기존 만료된 GateToken 초기화
locals.GAppApis[0] = locals.AppApi{}
// 스케줄러가 새로운 GateToken이 얻어올 때까지 대기 (최대 5초마다 확인)
for locals.GAppApis[0].GateToken == "" {
fmt.Println("새로운 GateToken 발급 중..")
time.Sleep(5 * time.Second)
}
fmt.Println("새로운 GateToken 발급 완료!")
// 새로운 GateToken으로 API 재요청
newGateToken := locals.GAppApis[0].GateToken
resp, body, err := SendHttpRequest(mainApiURL, newGateToken, requestBody)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, err
}
defer resp.Body.Close()
// 새로운 요청 응답 확인
if resp.StatusCode == 200 {
e.OkLog("새로운 GateToken을 사용한 HTTP 요청 성공!")
return body, nil
} else {
return nil, fmt.Errorf("새로운 GateToken 요청 실패, 상태 코드: %d", resp.StatusCode)
}
}
// 기존 GateToken으로 요청 성공한 경우
e.OkLog("기존 GateToken을 사용한 HTTP 요청 성공!")
return body, nil
}
// HTTP 요청을 보내는 함수
func SendHttpRequest(mainApiURL string, gateToken string, requestBody map[string]interface{}) (*http.Response, []byte, error) {
// 1. JSON 데이터로 변환
jsonData, err := json.Marshal(requestBody)
if err != nil {
fmt.Println("JSON 변환 실패:", err)
return nil, nil, err
}
// 2. HTTP 요청 생성 (POST 요청)
req, err := http.NewRequest("POST", mainApiURL, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("HTTP 요청 생성 실패:", err)
return nil, nil, err
}
// 3. HTTP 헤더 설정 (GateToken 포함)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("GateToken", gateToken)
// 4. HTTP 요청 실행
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, nil, err
}
// 5. 응답 데이터 읽기
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("응답 본문 읽기 실패:", err)
return nil, nil, err
}
// 6. 응답 로그 출력
fmt.Println("응답 코드:", resp.StatusCode)
fmt.Println("응답 본문:", string(body))
return resp, body, nil
}
OwnerKey를 활용한 게시판 연동 예제
시작하기 전에
이 문서는 OwnerKey를 사용하여 Guest App에서 Owner App의 게시판 데이터 연동할 때 필요한 참고정보를 제공 및 설명합니다.
OwnerKey와 SSO는 뭐예요?
1. OwnerKey = 나만의 열쇠 (공유 가능한 친구링크)
-
내가 만든 콘텐츠나 앱을 다른 웹사이트에서도 쉽게 붙여서 쓸 수 있게 해주는 열쇠
-
예: 내 사이트에 있는 “예약 시스템”을 다른 가게 주인이 자신의 홈페이지에 붙일 수 있음
→ 하지만 관리 권한은 여전히 내게 있음
2. SSO (Single Sign-On) = 한번 로그인하면 여러 사이트 친구집도 들락날락
-
내 이메일/계정 하나로 여러 사이트(다보리로 만든)에서 자유롭게 이용 가능
-
마치 네이버 계정으로 웹툰, 쇼핑, 카페 다 들어갈 수 있는 것처럼
📱 더 쉽게 말하면 이렇습니다:
"Dabory는 모든 가게, 회사, 블로그, 커뮤니티가 서로 친구처럼 연결되는 마을입니다.
마을에서 누가 만든 물건(앱, 기능)을 누구나 쓸 수 있고,
각자 가게를 운영하면서도, 필요한 건 서로 공유하며 살아갈 수 있죠."
🔄 플랫폼 독점이 아니라, 모두의 플랫폼
-
쿠팡/네이버 같은 플랫폼은 모든 트래픽을 자기 플랫폼에 모아 수수료를 받습니다.
-
반면 Dabory는, 각자의 웹사이트가 자립형 플랫폼이 될 수 있도록 도와줍니다.
-
쇼핑몰, 블로그, ERP, 고객관리, 다 따로 만들 필요 없이,
한 시스템 안에서 자유롭게 조합해 쓸 수 있게 한 것이죠.
✅ 정리하면,
기존 플랫폼 | Dabory Composable |
---|---|
기능 독점, 수수료 기반 | 오픈소스, 기능 공유 기반 |
나만의 앱 추가 어려움 | 누구나 앱 추가 및 공유 가능 |
모든 데이터 중앙 집중 | 각자가 주인이 되는 구조 |
폐쇄적인 구조 | 친구처럼 연결된 공유형 구조 |
DC(Dabory Composable)의 OwnerKey 기반 웹사이트 상호 연결 구조는, 구조적으로 매우 독특한 컨텐츠 협업 기반 SEO 강화 모델을 구현합니다. 이 모델은 구글 SEO 관점에서 백링크 SEO와 컨텐츠 SEO 양 측면 모두에서 다음과 같은 강점을 가집니다:
✅ 1. 백링크 SEO 관점에서의 강점
1.1 자연스럽고 의미 있는 백링크 구성
-
OwnerKey를 통해 실제 관련 업종 또는 업태 간의 연결이 이루어짐
-
이는 구글이 선호하는 "의미 있는 관계를 가진 사이트 간의 링크"로 인식되어 신뢰도 높은 백링크로 평가됨
-
예:
A
가 안경원이고B
도 안경 프랜차이즈일 때, 블로그·상품 링크 상호 공유 → 주제 관련성 높음 → 백링크 가치 상승
1.2 도메인 권한 전이(Authority Sharing)
-
구글은 높은 권한을 가진 사이트로부터의 링크를 중요하게 평가함
-
DC 클러스터 구조에서는 상대적으로 강한 사이트가 약한 친구 사이트에 도메인 권한을 분산 공유하는 효과를 제공
-
중장기적으로 클러스터 전체가 상호 이득을 보며 도메인 권한이 상승
1.3 링크 다양성과 분산 효과
-
여러 친구 사이트 간의 OwnerKey 기반 클러스터 구조는 다양한 IP/도메인/콘텐츠 소스에서의 백링크 생성을 유도함
-
이는 구글이 선호하는 “링크 다양성(link diversity)”을 충족 → 스팸 백링크가 아니라는 신호
✅ 2. 컨텐츠 SEO 관점에서의 강점
2.1 컨텐츠 확산과 정규화 (Canonical) 구조의 이상적 활용
-
원본 사이트는 canonical 메타태그로 정규화된 컨텐츠로 인정받고,
-
친구 사이트는 정규화된 컨텐츠의 요약 또는 소개글 + 링크를 갖게 되어 중복 컨텐츠 패널티를 회피
-
동시에, 친구 사이트도 컨텐츠가 풍부해지면서 사용자 체류 시간 증가 → SEO 점수 향상
2.2 주제 클러스터(Topic Cluster) 구조 형성
-
다수의 유사 업종 사이트가 하나의 주제(예: 안경, 미용, 세무 등)를 중심으로 연결됨
-
이는 구글의 E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) 기준에서 주제 전문성 강화를 유도
-
결과적으로 각 사이트는 전문적인 니치 콘텐츠 허브로 진화
2.3 신속한 컨텐츠 재활용과 확산
-
OwnerKey 구조는 1분 내 컨텐츠 공유 가능 → 트렌드 대응 속도 빠름
-
블로그, 상품, 이벤트 등을 빠르게 클러스터 전체에 배포 가능
-
구글이 선호하는 신선한 콘텐츠(fresh content) 제공 주기가 짧아져 순위 향상에 유리
✅ 3. 다대다 클러스터로의 확장 효과
3.1 네트워크 효과 (Network SEO Effect)
-
각 사이트가 단순히 소비자에게 노출되는 것뿐 아니라, 서로를 위한 SEO 강화 인프라가 됨
-
마치 분산형 콘텐츠 CDN처럼 작동하여, 검색 엔진에 광범위한 존재감을 형성
-
구글 알고리즘 상에서는 "업계 전체의 권위 있는 리소스 그룹"으로 인식 가능성 증가
3.2 경쟁이 아닌 협업 기반 SEO 전략
-
기존에는 동일 업종 간 SEO 경쟁이 치열했으나, DC 구조는 **경쟁이 아닌 동맹(Cluster SEO)**으로 방향 전환
-
협업 기반 구조는 SEO 예산의 효율적 사용, 컨텐츠 품질 제고, 순위 상승 가속화로 이어짐
✅ 결론 및 전략 제안
DC OwnerKey 기반 구조는 다대다 P2P형 SEO 협업 구조로서:
-
콘텐츠 중심의 상호 권위 강화
-
백링크의 품질과 신뢰성 향상
-
주제별 클러스터링을 통한 전문성 상승
-
검색엔진이 선호하는 시맨틱 연결 구조 강화
를 실현합니다.
🔧 전략적으로는 각 클러스터 참여 사이트가
고유한 컨텐츠 생산 → 친구 사이트에 공유
canonical 태그 정확히 적용
제품/서비스와 연관된 블로그 글에 키워드 삽입 및 내부 링크 최적화
를 동시에 진행하면 SEO 시너지 효과를 최대화할 수 있습니다.
예제실행전에 아래 준비사항들을 반드시 준비해주시기 바랍니다.
- 오너 사이트로부터 제공받은 OwnerKey (env 파일에 저장)
- css 파일( 디자인 커스터마이징의 경우 )
- app 등록하기
- owner app의 게시판 코드
- env 파일에 저장된 OWNER_APP_NAME
게시판 연동의 흐름
1. 제공받은 OwnerKey를 env 파일에 저장합니다.
2. owner app의 게시판 정보를 기반으로 guest app에 저장합니다.
게시판 연동예제
위 이미지는 dabory compoable 사이트의 USE CASES 게시판(블로그)입니다. 이 게시판을 factory 사이트에서 연동하겠습니다.
- env 파일에 오너키 저장
먼저 .env 파일에 OwnerKey를 저장해야합니다. 만약 설정할 오너앱이 두개 이상 이상이라면 오너앱의 개수에 맞게 변수 끝에 _숫자를 입력하여 순서에 맞게 변수명을 입력합니다. FriendKeys는 다수개의 연동웹사이트를 가질수 있으면 맨뒤에 붙은 번호를 postfix 로 하여 Laravel 실행시 Array 에모리에 들어가서 저장됩니다.
# [Friend Keys]
OWNER_APP_NAME_0=YOUR_OWNER_APP_NAME # Owner APP의 이름 (자유롭게 지정)
GUEST_APP_OWNER_KEY_0=YOUR_OWNER_KEY # Guest APP에서 발급받은 OwnerKey 입력
GUEST_APP_OWNER_URL_0=YOUR_OWNER_URL # Owner APP의 URL 입력 (ex.https://composable.daboryhost.com)
OWNER_APP_NAME_1=YOUR_OWNER_APP_NAME_2
GUEST_APP_OWNER_KEY_1=YOUR_OWNER_KEY_2
GUEST_APP_OWNER_URL_1=YOUR_OWNER_URL_2
OWNER_APP_NAME_2=YOUR_OWNER_APP_NAME_3
GUEST_APP_OWNER_KEY_2=YOUR_OWNER_KEY_3
GUEST_APP_OWNER_URL_2=YOUR_OWNER_URL_3
- OwnerKey는 GUSET APP이 MAIN APP의 API를 호출할 때 사용되는 고유한 인증 키입니다.
- WebApp 방식에서는 OwnerKey를 .env 파일에 저장하고, API 요청 시 세션을 활용하여 사용합니다.
- 프랜드 웹사이트의 게시판 URL 확인
만약 오너사이트에서 제공받으려는 게시판 url을 모른다면 프렌드 사이트에서 해당 게시판 url을 확인할 수 있습니다.
(1). 프렌드 사이트인 composable에서 Use Cases를 클릭합니다.
(2). /bbs/list/use-cases를 복사하여 메모장에 붙여넣습니다.
- 마이(Guest) 홈페이지 메뉴 등록
(1) 나의 홈페이지 관리자 보드로 로그인 합니다.
(2) 설정과 로그(바둑판메뉴) - 수퍼관리자(공통)- 메뉴가져오기(주의) - 홈페이지 메뉴 불러오기 메뉴로 진입합니다.
(2). 우측 상단의 메인메뉴 추가 버튼을 클릭합니다.
(3). 입력창을 모두 입력한 뒤 저장버튼을 클릭하여 저장합니다.
페이지URI 에 프렌드 사이트의 게시판URI와 .env의 OWNER_APP_NAME 을 아래와 같이 결합하여 저장합니다.
메뉴코드 : 메뉴코드는 메뉴의 순서와 상/하위 메뉴를 지정할 수 있습니다 . 예를들어 메뉴코드가 100000인 메뉴가 홈페이지 헤더 메뉴에 가장 먼저 위치하고 200000~900000인 메뉴가 순서대로 노출됩니다. 301000, 302000은 300000의 하위메뉴를 뜻합니다.
메뉴명 : 홈페이지 나타내려는 메뉴(게시판)의 이름
페이지 URI : 오너로부터 제공받은 게시판 URL을 입력한뒤 가장 끝부분에 env파일에 저장된 OWNER_APP_NAME 을 입력합니다.
예를들어 오너 사이트에서 제공받은 게시판 URI가 /bbs/list/use-cases 고 env파일에 저장된 OWNER_APP_NAME이 composable이라면 /bbs/list/use-cases/composable 이라고 입력합니다.
언어구분 : 원하는 언어형식을 선택합니다.
링크타입 : 게시판을 선택합니다.
종류 : primary를 선택합니다.
메뉴표시 누락 : 체크시 홈페이지에서 해당 메뉴가 노출되지 않습니다.
target=_blank 인가 : 체크시 홈페이지에서 해당 메뉴를 클릭했을때 새탭으로 열립니다.
PC에서누락 : 체크시 PC로 홈페이지에 접속했을때 해당 메뉴가 노출되지 않습니다.
Mobile에서누락 : 체크시 모바일로 홈페이지에 접속했을 때 해당 메뉴가 노출되지 않습니다.
테블릿에서누락 : 체크시 테블릭PC로 홈페이지에 접속했을 때 해당 메뉴가 노출되지 않습니다.
로그인경우만 : 체크시 로그인했을 경우에만 해당 메뉴가 노출됩니다.
로그아웃경우만 : 체크시 로그아웃했을 경우에만 해당 메뉴가 노출됩니다.
(4). 홈페이지에 접속하여 추가한 게시판이 노출되었는지 확인합니다.
(5). composable과 게시판 연동이 완료되었습니다.
STRONG-API
개요
🛠️ 표준 API (main_api)란?
표준 API(main_api)는 여러 회사에서 공통적으로 사용하는 핵심 API입니다.
예를 들어, 주문 관리, 재고 관리, 결제 처리 등의 기능을 표준 API가 제공할 수 있습니다.
하지만 모든 회사가 동일한 방식으로 운영되지는 않기 때문에, 개별적인 기능 확장이 필요할 수 있습니다.
🛠️ Strong API란?
✅ Strong API는 클라이언트 요청을 받아 컨트롤러에서 처리 후 응답을 반환하는 기본적인 API입니다.
(예: 클라이언트가 주문 정보를 요청하면, 컨트롤러가 데이터를 가공하여 응답을 반환함)
✅ 표준 API(main_api)를 변경하지 않고도 회사의 요구에 맞춰 새로운 기능을 쉽게 추가할 수 있도록 설계되었습니다
✅ 표준을 유지하면서도 맞춤형 기능을 확장 가능
🚀 유지보수가 쉬운 구조 & 빠른 커스터마이징 가능!
💡 왜 Strong API를 사용할까?
📌 표준 백엔드를 직접 수정하면 표준을 사용하는 모든 사용자에게 영향을 미치므로 각 회사마다 원하는 기능을 추가하기 어렵습니다
📌 하지만 Strong API를 사용하면 표준을 유지하면서도 원하는 기능을 쉽게 추가 가능!
ex) 안경사에 맞춘 검안/판매 기능 Strong 커스터마이징
------------------------------------------------------------------------------------------------------------------
📂 다음 내용: [🔍 STRONG-API의 구조]
STRONG-API의 구조
Dabory의 Strong-API 구조 (strong-go)
│── dabory/ # Dabory 관련 코드
│ ├── themes/opticalpos/ # OpticalPOS 테마 관련 코드
│ │ ├── erp/ # ERP 관련 코드
│ │ ├── pro/ # Pro 관련 코드
│ │ ├── qry/ # Query를 분리하여 코드
│ │ ├── strong/ # Strong API Directory
│ │ │ ├── backend/strong-go/ # Strong API 백엔드 코드
│ │ │ │ ├── conf/ # 설정 파일
│ │ │ │ ├── controllers/ # 컨트롤러 로직
│ │ │ │ ├── handlers/ # 컨트롤러와 모델 역할을 둘 다 하는 로직
│ │ │ │ ├── locals/ # 유틸리티 기능을 제공하는 패키지
│ │ │ │ ├── models/ # 데이터 처리 로직 (Table 구조체 정의)
│ │ │ │ ├── routers/ # routers 패키지는 클라이언트 요청을 받아 해당 요청을 적절한 컨트롤러로 전달하는 역할
│ │ │ │ ├── tmp/ # 임시 파일
│ │ │ │ ├── vendor/ # 외부 라이브러리 (Go Modules)
│ │ │ │ ├── .gitignore # Git에서 제외할 파일 목록
│ │ │ │ ├── docker-compose.yml # Docker 설정 파일
│ │ │ │ ├── go.mod # Go 모듈 관리 파일
│ │ │ │ ├── go.sum # Go 의존성 관리 파일
│ │ │ │ ├── main.go # 프로그램 진입점 (Entry Point)
│ │ │ │ ├── Readme.md # 프로젝트 설명 파일
│ │ │ │ ├── strong-go # 빌드된 실행 파일