Skip to content

Commit

Permalink
feat: REST docs를 통한 문서화 (#238)
Browse files Browse the repository at this point in the history
* feat: REST Docs 적용

* feat: REST Docs prettyPrint 및 snippets 적용

* feat: REST Docs에 예외 항목 추가

* test: 행사 액션 이력 조회 테스트 추가

* refactor: 중복된 http-request snippet 제거

* refactor: 사용되지 않는 snippet 제거

* refactor: 빌드 시 자동으로 문서 최신화하도록 gradle 설정 추가

* fix: CookieProperties에 sameSite 옵션 추가

---------

Co-authored-by: Arachne <[email protected]>
  • Loading branch information
khabh and Arachneee authored Aug 8, 2024
1 parent 3e1c52f commit ae82699
Show file tree
Hide file tree
Showing 12 changed files with 1,122 additions and 0 deletions.
34 changes: 34 additions & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
id 'org.asciidoctor.jvm.convert' version '3.3.2'
}

group = 'server'
Expand All @@ -17,6 +18,7 @@ configurations {
compileOnly {
extendsFrom annotationProcessor
}
asciidoctorExt
}

repositories {
Expand All @@ -40,8 +42,40 @@ dependencies {

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}

ext {
snippetsDir = file('build/generated-snippets')
}

tasks.named('test') {
useJUnitPlatform()
outputs.dir snippetsDir
}

asciidoctor {
inputs.dir snippetsDir
configurations 'asciidoctorExt'
dependsOn test
baseDirFollowsSourceFile()
}

tasks.register('copyApiDocuments', Copy) {
doFirst {
delete file('src/main/resources/static/docs')
}
dependsOn asciidoctor
from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}

bootJar {
dependsOn copyApiDocuments
}

build {
dependsOn copyApiDocuments
}
121 changes: 121 additions & 0 deletions server/src/docs/asciidoc/billAction.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
== 지출 액션

=== 지출 액션 생성

operation::createBillActions[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"REQUEST_EMPTY",
"message":"지출 금액은 비어 있으면 안됩니다."
},
{
"code":"REQUEST_EMPTY",
"message":"지출 내역은 비어 있으면 안됩니다."
},
{
"code":"BILL_ACTION_TITLE_INVALID",
"message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다."
},
{
"code":"BILL_ACTION_PRICE_INVALID",
"message":"지출 금액은 10,000,000 이하의 자연수여야 합니다."
},
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"TOKEN_NOT_FOUND",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_EXPIRED",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_INVALID",
"message":"유효하지 않은 토큰입니다."
}
]
----

=== 지출 액션 수정

operation::updateBillAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"REQUEST_EMPTY",
"message":"지출 내역 제목은 공백일 수 없습니다."
},
{
"code":"REQUEST_EMPTY",
"message":"지출 금액은 공백일 수 없습니다."
},
{
"code":"BILL_ACTION_TITLE_INVALID",
"message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다."
},
{
"code":"BILL_ACTION_PRICE_INVALID",
"message":"지출 금액은 %,d 이하의 자연수여야 합니다."
},
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"BILL_ACTION_NOT_FOUND",
"message":"존재하지 않는 지출 액션입니다."
},
{
"code":"TOKEN_NOT_FOUND",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_EXPIRED",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_INVALID",
"message":"유효하지 않은 토큰입니다."
}
]
----

=== 지출 액션 삭제

operation::deleteBillAction[snippets="path-parameters,http-request,http-response,request-cookies"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"TOKEN_NOT_FOUND",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_EXPIRED",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_INVALID",
"message":"유효하지 않은 토큰입니다."
}
]
----
165 changes: 165 additions & 0 deletions server/src/docs/asciidoc/event.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
== 행사

=== 행사 생성

operation::createEvent[snippets="http-request,request-body,request-fields,response-body,response-fields,http-response,response-cookies"]
==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"REQUEST_EMPTY",
"message":"행사 이름은 공백일 수 없습니다."
},
{
"code":"EVENT_NAME_LENGTH_INVALID",
"message":"행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : 21"
},
{
"code":"EVENT_NAME_MULTIPLE_BLANK",
"message":"행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : 공백 문자"
},
{
"code":"EVENT_PASSWORD_INVALID",
"message":"비밀번호는 4자리 숫자만 가능합니다."
}
]
----

=== 행사 관리자 로그인

operation::eventLogin[snippets="path-parameters,http-request,request-body,request-fields,http-response,response-cookies"]
==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"REQUEST_EMPTY",
"message":"비밀번호는 공백일 수 없습니다."
},
{
"code":"PASSWORD_INVALID",
"message":"비밀번호가 일치하지 않습니다."
}
]
----

=== 행사 정보 조회

operation::getEvent[snippets="path-parameters,http-request,response-body,response-fields,http-response"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
}
]
----

=== 행사 전체 참여자 목록 조회

operation::findAllEventMember[snippets="path-parameters,http-request,response-body,response-fields,http-response,response-fields"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
}
]
----

=== 행사 전체 액션 이력 조회

operation::findActions[snippets="path-parameters,http-request,http-response,response-fields"]

==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
}
]
----

=== 행사 참여자 이름 변경

operation::updateEventMemberName[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"]
==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"REQUEST_EMPTY",
"message":"멤버 이름은 공백일 수 없습니다."
},
{
"code":"MEMBER_NAME_LENGTH_INVALID",
"message":"멤버 이름은 1자 이상 4자 이하만 입력 가능합니다."
},
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"MEMBER_NAME_DUPLICATE",
"message":"중복된 행사 참여 인원 이름이 존재합니다."
},
{
"code":"TOKEN_NOT_FOUND",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_EXPIRED",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_INVALID",
"message":"유효하지 않은 토큰입니다."
}
]
----

=== 행사 참여자 삭제 (특정 참여자의 모든 참여자 액션 삭제)

operation::deleteAllMemberActionByName[snippets="path-parameters,http-request,http-response,request-cookies"]
==== [.red]#Exceptions#

[source,json,options="nowrap"]
----
[
{
"code":"EVENT_NOT_FOUND",
"message":"존재하지 않는 행사입니다."
},
{
"code":"TOKEN_NOT_FOUND",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_EXPIRED",
"message":"토큰이 존재하지 않습니다."
},
{
"code":"TOKEN_INVALID",
"message":"유효하지 않은 토큰입니다."
}
]
----
18 changes: 18 additions & 0 deletions server/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:source-highlighter: highlightjs
:hardbreaks:
:toc: left
:doctype: book
:icons: font
:toc-title: 전체 API 목록
:toclevels: 2
:sectlinks:
:sectnums:
:sectnumlevels: 2

= 행동대장

include::{docdir}/event.adoc[]
include::{docdir}/memberBillReport.adoc[]
include::{docdir}/memberAction.adoc[]
include::{docdir}/billAction.adoc[]

Loading

0 comments on commit ae82699

Please sign in to comment.