44import io .swagger .v3 .oas .annotations .enums .SecuritySchemeType ;
55import io .swagger .v3 .oas .annotations .info .Info ;
66import io .swagger .v3 .oas .annotations .security .SecurityScheme ;
7+ import io .swagger .v3 .oas .models .Operation ;
8+ import io .swagger .v3 .oas .models .PathItem ;
9+ import org .springdoc .core .customizers .OpenApiCustomizer ;
710import org .springdoc .core .models .GroupedOpenApi ;
811import org .springframework .context .annotation .Bean ;
912import org .springframework .context .annotation .Configuration ;
1013
14+ import java .util .Comparator ;
15+ import java .util .LinkedHashMap ;
16+ import java .util .Map ;
17+ import java .util .regex .Matcher ;
18+ import java .util .regex .Pattern ;
19+
1120@ Configuration
1221@ OpenAPIDefinition (info = @ Info (title = "AI Lawyer API" , version = "beta" , description = "AI 변호사 서비스 API 문서입니다." ))
1322@ SecurityScheme (
@@ -24,6 +33,7 @@ public GroupedOpenApi memberApi() {
2433 .group ("Member API" )
2534 .pathsToMatch ("/api/auth/**" )
2635 .packagesToScan ("com.ai.lawyer.domain.member.controller" )
36+ .addOpenApiCustomizer (orderBySummaryNumber ())
2737 .build ();
2838 }
2939
@@ -53,4 +63,33 @@ public GroupedOpenApi allApi() {
5363 .packagesToScan ("com.ai.lawyer.domain" )
5464 .build ();
5565 }
66+
67+ private OpenApiCustomizer orderBySummaryNumber () {
68+ return openApi -> {
69+ if (openApi .getPaths () == null ) return ;
70+
71+ Map <String , PathItem > sortedPaths = new LinkedHashMap <>();
72+
73+ // 정렬을 위해 summary 안에 있는 번호 추출
74+ Pattern pattern = Pattern .compile ("^(\\ d+)\\ ..*" );
75+
76+ openApi .getPaths ().entrySet ().stream ()
77+ .sorted (Comparator .comparingInt (e -> {
78+ PathItem pathItem = e .getValue ();
79+ // POST, GET, 등등 중 첫 번째 Operation의 summary 사용
80+ Operation op = pathItem .readOperations ().stream ().findFirst ().orElse (null );
81+ if (op == null || op .getSummary () == null ) return Integer .MAX_VALUE ;
82+
83+ Matcher matcher = pattern .matcher (op .getSummary ());
84+ if (matcher .find ()) {
85+ return Integer .parseInt (matcher .group (1 ));
86+ }
87+ return Integer .MAX_VALUE ;
88+ }))
89+ .forEachOrdered (entry -> sortedPaths .put (entry .getKey (), entry .getValue ()));
90+
91+ openApi .setPaths (new io .swagger .v3 .oas .models .Paths ());
92+ sortedPaths .forEach (openApi .getPaths ()::addPathItem );
93+ };
94+ }
5695}
0 commit comments