본문으로 이동
  • 이 서버는 리버티게임의 개발용 베타 서버로, 게임 플레이 용도로 제작된 사이트가 아닙니다.
  • 리버티게임의 자동 인증된 사용자라면 개발에 필요한 관리자 권한을 신청할 수 있습니다.
  • 틀 및 기능별 소도구를 필요한 문서에만 선택적으로 로딩하는 테스트를 진행하고 있습니다. 작동하지 않는 문서가 있다면 담당자에게 알려주세요.

사용자:Senouis/도전과제 서버 명세: 두 판 사이의 차이

리버티게임(개발), 모두가 만들어가는 자유로운 게임
Senouis (토론 | 기여)
잔글 Read
Senouis (토론 | 기여)
 
(같은 사용자의 중간 판 13개는 보이지 않습니다)
3번째 줄: 3번째 줄:
모든 결과에는 HTTP 응답 코드와 메세지를 응답 헤더에 포함할 것
모든 결과에는 HTTP 응답 코드와 메세지를 응답 헤더에 포함할 것


==예상 기술 스택==
2025년 6월 전까지 동작하는 물건을 만드는 것이 목표, 1월에 계획을 시작할 예정
*백엔드 개발 환경: Java + Spring<ref>Apache Tomcat이 포함됩니다.</ref> 기반 or Javascript + Node.js + Express.js
 
**3월까지 Spring을 제대로 익히지 못하면 Express.js로 개발을 시작합니다.
== 기술 스택==
**현재 만든 [https://github.com/Xen-alpha/Libertymedia-backend 임시 리포지토리]에는 Node.js 기반으로 환경이 구축되어 있습니다.(아직 작업 시작 안함)
*백엔드 개발 환경: Java + Spring<ref>Apache Tomcat이 포함됩니다.</ref> 기반
*DB: MongoDB 확정
*DB: Oracle DB + JPA로 확정
**도전과제 서버의 진행도 데이터는 금융권 DB마냥 ACID가 중요한 데이터 종류가 아님: 빠른 로드가 우선됨
* 스키마를 고정할 방법을 찾은 관계로 기존 기획이었던 MongoDB 대신
**기존의 JSON 파일 저장 방식 대신 BSON 스키마로 저장하는 MongoDB 채택
* 도전과제를 생성 가능한 유저와 달성 가능한 유저 사이의 권한을 분리
***Spring을 사용할 경우 Spring Data for MongoDB로 DB를 연결할 예정
 
***Express.js를 사용할 경우 Mongoose로 연결 예정
== DB 스키마 ==
 
{{#mermaid:
erDiagram
    Progress||--||Achievement : "achieve specific achievement"
    User||--o{Progress : "user have progress"
    User||--o|Promote : "ADVANCED promotion request"
    Achievement {
      id Long
      name String
      description String
      maxProgress Integer
    }
    Progress {
      id Long
      achievement_id Long
      user_id Long
      progress Integer
    }
    User {
      id Long
      name String
      email String
      password String
      promote_id Integer
    }
    Promote {
      id Long
      user_id Long
    }
}}


==기능==
==기능==
===처음 시작할 때===
===처음 시작할 때===
* OAuth 2.0으로만 로그인 가능하고, 'BASIC' 권한이 발행됨
** BASIC 권한: 도전과제 달성만 가능
** ADVANCED 권한: 도전과제 생성 및 삭제 가능
*** ADVANCED 권한 신청 API를 요청하면 관리자에게 허가 요청 메일이 날아감(허가 및 거부 API 링크 포함됨)
** ADMIN 권한: ADVANCED 권한 부여 가능한 권한, DB에서 서버 제작자 포함하여 직접 설정할 예정
*안내문(수집하게 되는 개인정보 등을 공시)과 함께 OAuth 2.0 인증 절차를 수행하는 링크를 추가
*안내문(수집하게 되는 개인정보 등을 공시)과 함께 OAuth 2.0 인증 절차를 수행하는 링크를 추가
**웹 페이지에 진입했을 때 Authorization Token과 Refresh 토큰이 모두 없는 경우
**웹 페이지에 진입했을 때 Authorization Token과 Refresh 토큰이 모두 없는 경우
24번째 줄: 59번째 줄:
***쿠키에 Access 토큰 및 Refresh 토큰을 1주 유효기간으로 설정
***쿠키에 Access 토큰 및 Refresh 토큰을 1주 유효기간으로 설정
* 아래 CRUD 요청에서 Access Token 뿐만 아니라 Refresh 토큰까지 만료된 경우 mw.notification으로 재연동을 요청할 것
* 아래 CRUD 요청에서 Access Token 뿐만 아니라 Refresh 토큰까지 만료된 경우 mw.notification으로 재연동을 요청할 것
{{#mermaid:
sequenceDiagram
    User->>OAuth Server: Request Authorization code
    OAuth Server-->>User: Give Authorization code
    User->>OAuth Server: Request Access token(AT) and refresh token(RT)
    OAuth Server-->>User: Give AT and RT
    User ->> Achievement Server: Request Collection creation with AT
    Achievement Server ->> OAuth Server: Request Profile with AT
    OAuth Server-->>Achievement Server: Give User Profile if it is right
    Achievement Server ->> Oracle DB: Create database
    MongoDB -->> Achievement Server: Response Success
    Achievement Server -->> User: Response Success
}}


===Create===
===Create===
libertyga.me/achievement/v0/initialization
*스키마 초기화 과정
**웹 페이지에 진입하면 READ를 시도하고, 없다는 오류 응답이 왔을 때 Access Token이 있는 경우에만 사용자 이름과 토큰을 헤더에 삽입하여 Create 수행
***요청 종류는 PUT으로 설정
***PUT 요청을 받은 서버는 profile 리소스를 요청하여 인증 성공시 DB에 사용자 이름으로 된 스키마를 생성
****스키마 내부에는 항목 이름을 문자와 숫자로 자유롭게 생성 가능하도록 이름 제약을 특수 문자 필터링 외에 걸지 않음
****타입의 경우 integer로 강제해야 함
**성공/실패할 경우 [https://doc.wikimedia.org/mediawiki-core/REL1_39/js/#!/api/mw.notification mw.notification.notify()]로 알려야 함
libertyga.me/achievement/v0/addition/{user}/{itemname}


* 웹 페이지에 진입하면 READ를 시도하고, 없다는 오류 응답이 왔을 때 Access Token이 있는 경우에만 사용자 이름과 토큰을 헤더에 삽입하여 Create 수행
libertyga.me/achievement/v0/addition
 
* 고유한 값을 가지는 도전과제 이름(title)과 설명, 그리고 도전 과제 달성까지 필요한 행동 횟수를 요청함
* 성공시 도전과제 이름 반환, 실패할 경우 에러 처리
 
{{#mermaid:
sequenceDiagram
    User->>Achievement Server: Request document add request with AT
    Achievement Server->>OAuth Server: Request Profile with AT
    OAuth Server-->>Achievement Server: Give User Profile if it is right
    Achievement Server-)MongoDB: Request addition to TABLE achievement TABLE achievement
    MongoDB -->> Achievement Server: Response Success
    Achievement Server -->> User: Response Success
}}
==== Request Body ====
<syntaxhighlight lang=json>
{
  "title": String,
  "description": String,
  "MaxNumber": Number
}
</syntaxhighlight>
==== Response Body ====
<syntaxhighlight lang=json>
{
  "success": true,
  "result": String
}
</syntaxhighlight>
===Read===
libertyga.me:6400/achievement/v0/list/{user}
 
* 아이템 조회 과정
* 파라미터: user URL 파라미터는 숫자 ID
 
{{#mermaid:
sequenceDiagram
    User->>Achievement Server: Request collection read with AT
    Achievement Server ->> OAuth Server: Request Profile with AT
    OAuth Server-->>Achievement Server: Give User Profile if it is right
    Achievement Server-)MongoDB: Request read DATABASE achievement TABLE progress
    MongoDB -->> Achievement Server: Response Success
    Achievement Server-->>User: Response Success
}}
 
==== Response Body ====
<syntaxhighlight lang=json>
{
  "success": true,
  "result" : [
    {
      "title": String,
      "description": String,
      "progress": Number,
      "maxProgress": Number
    },
    ...
  ]
}
</syntaxhighlight>
 
=== Update ===
 
libertyga.me/achievement/v0/achieved
 
* 웹 페이지에 진입하면 Access Token이 있는 경우에만 사용자 이름과 토큰을 헤더에 삽입하여 Create 수행, 없으면 로그인 요청을 mw.notification.notify()로 알림
** 다음과 같은 상황에서 스키마에 항목을 추가
** 다음과 같은 상황에서 스키마에 항목을 추가
*** 특정 classname을 가진 링크를 클릭했을 때
*** 특정 classname을 가진 링크를 클릭했을 때
*** 특정 classname을 가진 div 태그를 발견했을 때 innerHTML에 있는 데이터를 itemname에 밀어넣음
*** 특정 classname을 가진 div 태그를 발견했을 때 innerHTML에 있는 데이터를 itemname에 밀어넣음
**요청 종류는 PUT으로 설정
**요청 종류는 POST으로 설정
**PUT 요청을 받은 서버는 profile 리소스를 요청하여 인증 성공시 DB에 사용자 이름으로 된 스키마 내에 항목을 하나 추가
**POST 요청을 받은 서버는 profile 리소스를 요청하여 인증 성공시 DB에 사용자 이름으로 된 스키마 내에 항목을 하나 추가
***스키마 내부에는 항목 이름을 문자와 숫자의 조합으로 자유롭게 생성 가능하도록 이름 제약을 특수 문자 필터링 외에 걸지 않음
***스키마 내부에는 항목 이름 및 설명을 문자와 숫자의 조합으로 자유롭게 생성 가능하며, 리버티게임 계정 유저의 DB ID 번호를 넘김
***max_value를 설정해야 함: data-value 커스텀 HTML attribute에 기록된 값을 읽어야 함, 기본값은 1로 할 것
***max_value를 설정해야 함: data-value 커스텀 HTML attribute에 기록된 값을 읽어야 함, 기본값은 1로 할 것
***value는 1로 초기화
***value는 1로 초기화
**결과 반환은 상황에 따라 다름
**결과 반환은 상황에 따라 다름
***value == maxvalue == 1이면 즉시 달성으로 결과 반환
***value == maxvalue == 1이면 즉시 달성으로 결과 반환
***value < maxvalue면 (1/n)을 붙여 결과 반환
***value < maxvalue면 (1/n)을 붙여 결과 반환, 이후 달성할 때마다 value를 늘림
*성공/실패할 경우 [https://doc.wikimedia.org/mediawiki-core/REL1_39/js/#!/api/mw.notification mw.notification.notify()]로 알려야 함
*성공/실패할 경우 [https://doc.wikimedia.org/mediawiki-core/REL1_39/js/#!/api/mw.notification mw.notification.notify()]로 알려야 함
** 성공 후에는 사용자 LocalStorage에 기록하여 다시 요청하지 않도록 함


===Read===
{{#mermaid:
libertyga.me:6400/achievement/v0/item/{user}/{itemname}
sequenceDiagram
 
    User->>Achievement Server: Request collection read with AT
* 아이템 조회 과정
    Achievement Server ->> OAuth Server: Request Profile with AT
* 파라미터: user와 itemname은 특수문자 필터링 필요
    OAuth Server-->>Achievement Server: Give User Profile if it is right
** 필터링 통과 실패 -> '제작자가 도전과제 이름을 잘못 지정했습니다.'라는 오류 메세지를 반환하여 mw.notification으로 송출하도록 함
    Achievement Server-)MongoDB: Request update DATABASE achievement TABLE progress
 
    MongoDB -->> Achievement Server: Response Success
libertyga.me:6400/achievement/v0/allitem/{user}
    Achievement Server-->>User: Response Success
}}


* 브라우저 캐싱 기능 추가할 경우 개발할 것
==== Request Body ====
* 브라우저에 저장된 도전 과제 값을 전부 갱신하기 위해 전부는 요청(자주 사용하지 않는 API)
<syntaxhighlight lang=json>
** IndexedDB
{
  "title": String,
}
</syntaxhighlight>
==== Response Body ====
<syntaxhighlight lang=json>
{
  "success": true,
  "result" : [
    {
      "title": String,
      "description": String,
      "progress": Number,
      "maxProgress": Number
    },
    ...
  ]
}
</syntaxhighlight>


===Update===
===Delete (선택 구현) ===
libertyga.me/achievement/v0/modification/{user}/{itemname}
libertyga.me:6400/achievement/v0/deletion
 
* POST 요청으로, 헤더에 Access 토큰 부착할 것
* 진행도 향상용
** 특정 classname을 가진 링크를 클릭했을 때
** 특정 classname을 가진 div 태그를 발견했을 때 innerHTML에 있는 데이터를 itemname에 밀어넣음
* 스키마에 항목이 있고, 달성하지 않은 경우(value < maxvalue) 값을 +1
* 스키마에 항목이 없는 경우 addition API를 호출
 
===Delete===
libertyga.me/achievement/v0/deletion/{user}/{itemname}


* 도전과제를 초기화하고 스키마만 남김
* 도전과제를 초기화하고 스키마만 남김
* DELETE 요청이므로 헤더에 Access 토큰 부착할 것
* DELETE 요청이므로 헤더에 Access 토큰 부착할 것
** 성공 후에는 사용자 LocalStorage도 초기화하여 다시 요청하도록 함
{{#mermaid:
sequenceDiagram
    User->>Achievement Server: Request collection update with AT
    Achievement Server-)OAuth Server: Request Profile with AT
    OAuth Server-->>Achievement Server: Give User Profile if it is right
    Achievement Server-)MongoDB: Request delete DATABASE achievement TABLE Progress (user = '...')
    MongoDB -->> Achievement Server: Response Success
    Achievement Server-->>User: Response Success
}}


==== Request Body ====
<syntaxhighlight lang=json>
{
  "username": String
}
</syntaxhighlight>
== 기타 ==
== 기타 ==


* 브라우저 캐싱 기능을 후에 추가할 것
* LocalStorage 브라우저 캐싱 기능을 추가할 것
** HEAD 요청이 추가로 필요하며, 자신의 데이터베이스 스키마의 SHA-256 해시값을 헤더에 포함해 반환할 것
** 반환한 해시값이 다르면 통짜 조회
<references />
<references />

2025년 3월 13일 (목) 11:43 기준 최신판

'미디어위키:Gadget-Achievement.js'를 통해 다음 과정을 수행

모든 결과에는 HTTP 응답 코드와 메세지를 응답 헤더에 포함할 것

2025년 6월 전까지 동작하는 물건을 만드는 것이 목표, 1월에 계획을 시작할 예정

기술 스택

  • 백엔드 개발 환경: Java + Spring[1] 기반
  • DB: Oracle DB + JPA로 확정
  • 스키마를 고정할 방법을 찾은 관계로 기존 기획이었던 MongoDB 대신
  • 도전과제를 생성 가능한 유저와 달성 가능한 유저 사이의 권한을 분리

DB 스키마

ProgressidLongachievement_idLonguser_idLongprogressIntegerAchievementidLongnameStringdescriptionStringmaxProgressIntegerUseridLongnameStringemailStringpasswordStringpromote_idIntegerPromoteidLonguser_idLongachieve specific achievementuser have progressADVANCED promotion request

기능

처음 시작할 때

  • OAuth 2.0으로만 로그인 가능하고, 'BASIC' 권한이 발행됨
    • BASIC 권한: 도전과제 달성만 가능
    • ADVANCED 권한: 도전과제 생성 및 삭제 가능
      • ADVANCED 권한 신청 API를 요청하면 관리자에게 허가 요청 메일이 날아감(허가 및 거부 API 링크 포함됨)
    • ADMIN 권한: ADVANCED 권한 부여 가능한 권한, DB에서 서버 제작자 포함하여 직접 설정할 예정
  • 안내문(수집하게 되는 개인정보 등을 공시)과 함께 OAuth 2.0 인증 절차를 수행하는 링크를 추가
    • 웹 페이지에 진입했을 때 Authorization Token과 Refresh 토큰이 모두 없는 경우
      • OAuth 확장 기능의 절차대로 리버티게임 서버 내 OAuth 기능에 Authorization 토큰 발급 요청
      • Authorization 코드 발급 기능을 먼저 구현한 후 PKCE 과정을 추가해 code_challenge 수행 필요
      • Redirect URI는 요청한 페이지로 설정
    • 웹 페이지에 진입했을 때 Authorization 토큰이 있는 경우 or Refresh 토큰이 있는 경우
      • 즉시 OAuth 확장 기능의 절차대로 리버티게임 서버 내 OAuth 기능에 Access 토큰 및 Refresh 토큰 발급 요청
      • 쿠키에 Access 토큰 및 Refresh 토큰을 1주 유효기간으로 설정
  • 아래 CRUD 요청에서 Access Token 뿐만 아니라 Refresh 토큰까지 만료된 경우 mw.notification으로 재연동을 요청할 것
UserOAuth ServerAchievement ServerOracle DBMongoDBRequest Authorization codeGive Authorization codeRequest Access token(AT) and refresh token(RT)Give AT and RTRequest Collection creation with ATRequest Profile with ATGive User Profile if it is rightCreate databaseResponse SuccessResponse SuccessUserOAuth ServerAchievement ServerOracle DBMongoDB

Create

libertyga.me/achievement/v0/addition

  • 고유한 값을 가지는 도전과제 이름(title)과 설명, 그리고 도전 과제 달성까지 필요한 행동 횟수를 요청함
  • 성공시 도전과제 이름 반환, 실패할 경우 에러 처리
UserAchievement ServerOAuth ServerMongoDBRequest document add request with ATRequest Profile with ATGive User Profile if it is rightRequest addition to TABLE achievement TABLE achievementResponse SuccessResponse SuccessUserAchievement ServerOAuth ServerMongoDB

Request Body

{
  "title": String,
  "description": String,
  "MaxNumber": Number
}

Response Body

{
  "success": true,
  "result": String
}

Read

libertyga.me:6400/achievement/v0/list/{user}

  • 아이템 조회 과정
  • 파라미터: user URL 파라미터는 숫자 ID
UserAchievement ServerOAuth ServerMongoDBRequest collection read with ATRequest Profile with ATGive User Profile if it is rightRequest read DATABASE achievement TABLE progressResponse SuccessResponse SuccessUserAchievement ServerOAuth ServerMongoDB

Response Body

{
  "success": true,
  "result" : [
    {
      "title": String,
      "description": String,
      "progress": Number,
      "maxProgress": Number
    },
    ...
  ]
}

Update

libertyga.me/achievement/v0/achieved

  • 웹 페이지에 진입하면 Access Token이 있는 경우에만 사용자 이름과 토큰을 헤더에 삽입하여 Create 수행, 없으면 로그인 요청을 mw.notification.notify()로 알림
    • 다음과 같은 상황에서 스키마에 항목을 추가
      • 특정 classname을 가진 링크를 클릭했을 때
      • 특정 classname을 가진 div 태그를 발견했을 때 innerHTML에 있는 데이터를 itemname에 밀어넣음
    • 요청 종류는 POST으로 설정
    • POST 요청을 받은 서버는 profile 리소스를 요청하여 인증 성공시 DB에 사용자 이름으로 된 스키마 내에 항목을 하나 추가
      • 스키마 내부에는 항목 이름 및 설명을 문자와 숫자의 조합으로 자유롭게 생성 가능하며, 리버티게임 계정 유저의 DB ID 번호를 넘김
      • max_value를 설정해야 함: data-value 커스텀 HTML attribute에 기록된 값을 읽어야 함, 기본값은 1로 할 것
      • value는 1로 초기화
    • 결과 반환은 상황에 따라 다름
      • value == maxvalue == 1이면 즉시 달성으로 결과 반환
      • value < maxvalue면 (1/n)을 붙여 결과 반환, 이후 달성할 때마다 value를 늘림
  • 성공/실패할 경우 mw.notification.notify()로 알려야 함
    • 성공 후에는 사용자 LocalStorage에 기록하여 다시 요청하지 않도록 함
UserAchievement ServerOAuth ServerMongoDBRequest collection read with ATRequest Profile with ATGive User Profile if it is rightRequest update DATABASE achievement TABLE progressResponse SuccessResponse SuccessUserAchievement ServerOAuth ServerMongoDB

Request Body

{
   "title": String,
}

Response Body

{
  "success": true,
  "result" : [
    {
      "title": String,
      "description": String,
      "progress": Number,
      "maxProgress": Number
    },
    ...
  ]
}

Delete (선택 구현)

libertyga.me:6400/achievement/v0/deletion

  • 도전과제를 초기화하고 스키마만 남김
  • DELETE 요청이므로 헤더에 Access 토큰 부착할 것
    • 성공 후에는 사용자 LocalStorage도 초기화하여 다시 요청하도록 함
UserAchievement ServerOAuth ServerMongoDBRequest collection update with ATRequest Profile with ATGive User Profile if it is rightRequest delete DATABASE achievement TABLE Progress (user = '...')Response SuccessResponse SuccessUserAchievement ServerOAuth ServerMongoDB

Request Body

{
   "username": String
}

기타

  • LocalStorage 브라우저 캐싱 기능을 추가할 것
  1. Apache Tomcat이 포함됩니다.