FE와 BE의 의사소통; Swagger

kyeong su kim
월요일 오후 9시
10 min readJul 11, 2023

--

Spring Swagger를 처음 접하는 분들은 Swagger가 무엇인지, 어떤 기능을 가지고 있는지 궁금해 할 것입니다. Swagger는 RESTful API를 문서화하고, 사용자가 쉽게 테스트하고 호출할 수 있도록 하는 도구입니다. 이번 포스팅에서는 Swagger를 사용하는 이유와 Swagger를 사용하는 방법에 대해 알아보도록 하겠습니다. Spring Boot에서 Swagger를 사용하는 방법에 대해서도 함께 알아보겠습니다.

Swagger가 나오기 전에 FE와 BE의 소통방식

Swagger가 나오기 전에는 FE 개발자와 BE 개발자간의 소통방식은 단순무식했습니다. BE가 문서로 일일히 URL 및 Request, Response를 적어서 FE에게 전달하는 방식을 사용했습니다.이 방식은 BE 개발자가 API 문서를 일일히 작성해야 했기 때문에 생산성이 떨어졌습니다. 또한 문서의 일관성이 떨어지고, API가 변경되면 문서를 일일히 수정해야 하는 번거로움이 있었습니다. 더군다나 수기로 작성하다보니 휴먼에러가 발생할 수 있어서, FE와 BE의 의사소통이 어려울 수 있습니다. 그리고 FE 입장에서 API를 테스트할 수 있는 방식으로 Postman이나 cURL로 직접 URL 및 Request 작성하여 테스트해야합니다. 이러한 문제점을 해결하기 위해 Swagger가 등장하게 되었습니다.

예를 들어, BE 개발자와 FE 개발자들이 어떤 기능을 구현을 위한 API 명세 및 요구사항이 있다고 가정했을 때, 다음과 같은 조건이 만족해야지 기능을 구현했다고 볼 수 있습니다.

  1. BE 개발자는 API 구현에 있어서 어떠한 실수가 없어야 합니다.
  2. BE 개발자는 기능 요구사항을 완벽히 이해해야 합니다.
  3. FE 개발자는 기능 구현에 있어서 어떠한 실수가 없어야 합니다.
  4. FE 개발자는 기능 요구사항을 완벽히 이해해야 합니다.

요구사항 및 구현을 완벽히 구현했다고 다 해결한게 아니겠죠. 경우에 따라 요구사항이 바뀔 수 있기 때문입니다. (개발자는 그저 웁니다. ㅠㅠ)

Swagger 나온 이후

Swagger를 사용하면 API 문서를 생성할 때, 개발자가 문서를 작성하지 않아도 되므로 개발 시간을 단축할 수 있습니다. 또한, Swagger UI를 이용하면 API를 쉽게 테스트할 수 있으며, API 호출 시 전달해야 할 파라미터를 확인할 수 있습니다. 이외에도 Swagger를 사용하면 API 버전 관리가 용이해지고, 다양한 API 문서를 통합할 수 있습니다. Spring Boot에서 Swagger를 사용하면 API 문서를 생성하는 데 필요한 코드를 직접 작성하지 않아도 되므로, 개발자는 API 개발에 집중할 수 있습니다.

Swagger 사용 방법

Swagger를 구성하는 방법은 주로 두 가지가 있습니다. 첫 번째는 YAML 파일을 사용하여 구성하는 방법이고, 두 번째는 소스코드 내에서 Swagger를 설정하여 구성하는 방법이 있고 Java, Nodejs, Python에도 Swagger를 위한 라이브러리도 제공하고 있습니다. 각 방법에 따라 구현되는 아키텍처가 달라집니다. YAML를 사용하게 된다면 Swagger UI를 위한 서버를 따로 두고, Swagger에서 API 요청을 하면 그 요청을 해당 서버로 전달하게 됩니다. 반면 Spring Framework에서 구성한다면, 서버 자체가 Swagger 겸 백엔드 서버가 돼서, 요청 및 응답을 처리하게 됩니다.

YAML로 구성

이러한 구조를 따르면, YAML 파일을 이해하고 수정하기 쉬워지고, 명확한 아키텍처를 가질 수 있어서 개발자 뿐만 아니라 기획자도 쉽게 이해할 수 있습니다.

openapi: 3.0.0
info:
title: My API
version: 1.0.0
servers:
- url: https://{env}.example.com/api/v1
description: Server A
variables:
env:
default: production
enum:
- production
- staging
- url: <https://api.example-2.com>
description: Server B
paths:
# 현재 API 스펙에서 사용되는 경로들을 추가합니다.
/users:
get:
summary: Get all users
responses:
200:
description: A list of users
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
components:
schemas:
# 각 객체 타입에 대한 스키마를 정의합니다.
User:
type: object
properties:
id:
type: integer
name:
type: string
  • Swagger YAML 구조
  1. 기본 구조:
  • openapi: YAML 문서의 상단에 OpenAPI 사양의 버전을 명시합니다.
  • info: API 문서의 기본 정보를 기술합니다. API의 제목, 버전, 설명, 저자 및 라이선스 정보를 포함합니다.
  • servers: API 서버들의 URL과 설명을 나열합니다.
  1. 경로(paths): 경로별로 묶음으로 API 엔드포인트 관련 정보를 기술하고, 각 경로에서 사용 가능한 HTTP 메서드를 명시 및 요청과 응답 매개변수를 정의합니다.
  2. 컴포넌트(components): 컴포넌트에선 스키마, 응답, 매개변수, 예제, 요청 본문, 헤더, 보안 스키마 및 링크와 같은 재사용 가능한 API 구성 요소를 정의할 수 있습니다.
  • schemas: JSON Schema를 사용하여 설명된 복잡한 데이터 타입을 정의합니다. 주로, 요청 및 응답 데이터의 모습을 나타냅니다.
  • responses: 공통된 응답 메시지의 상태 코드와 설명을 기술합니다. 미리 정의된 응답들을 paths 섹션에서 참조할 수 있습니다.
  • parameters: API의 여러 엔드포인트에서 재사용 될 수 있는 매개변수를 정의합니다.
  • examples: 응답 및 요청 본문 예시를 정의합니다.
  • requestBodies: 공통된 요청 본문을 정의합니다.
  • headers: 공통된 헤더를 정의하고, API에서 재사용할 수 있습니다.
  • securitySchemes: API에서 사용되는 보안 방식을 정의합니다. 예를 들어, API 키 또는 OAuth2를 사용하는 인증 방법을 정의할 수 있습니다.
  1. 태그(tags): 각 API 엔드포인트를 논리적으로 그룹화하고 이름을 부여하는데 사용되는 태그입니다.

하지만 이 방법은 API 서버와 Swagger UI를 별도로 배포 및 관리하고자 하는 경우에 적합합니다. 하지만 이런 접근법은 관리 비용이 더 들 수 있고, 애플리케이션 애플리케이션 간의 동기화를 고려해야 하므로 주의가 필요합니다.

Spring Framework에서 구성

Spring Framework 내에서 Java 코드를 사용한 구성 Spring Framework 내에서 Java 코드를 사용하려면 먼저 springfox 라이브러리를 추가해야 합니다. 그런 다음, 설정 클래스를 생성하여 Swagger 구성을 정의합니다.

Gradle에서 springfox 라이브러리를 추가하려면 build.gradle 파일에 다음을 추가합니다.

dependencies {
implementation('io.springfox:springfox-boot-starter:3.0.0')
}

springfox-boot-starter 안에 swagger-ui, swagger-api 등 swagger를 구성하는데 필요한 라이브러리들이 들어있습니다.

Java 코드를 사용하여 Swagger를 구성하면, 보다 높은 수준의 유연성과 자동화가 가능합니다. 하지만 YAML 파일을 사용하면 좀 더 직관적인 설정을 제공할 수 있습니다.

@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}


@Api(tags = "스웨거 튜토리얼")
@RestController
@RequestMapping("/api/v1")
public class HelloController {
@ApiOperation(value = "헬로 1")
@GetMapping("/hello")
public ResponseEntity<String> hello() {
return ResponseEntity.ok("Hello World");
}

@ApiOperation(value = "헬로 2")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "리턴 성공", response = String.class),
@ApiResponse(code = 500, message = "서버 에러")
})
@PostMapping("/hello/{name}")
public ResponseEntity<String> hello2(
@ApiParam(value = "이름") @PathVariable String name
) {
if (name.equals("aa")) {
throw new IllegalArgumentException("유효하지 않은 이름입니다.");
}
String body = "Hello, " + name;
return ResponseEntity.ok(body);
}
}

springfox를 통해 문서화에 필요한 어노테이션은 다음과 같습니다.

  • @EnableSwagger2: Swagger 기능을 활성화하는 어노테이션입니다.
  • @Api: 클래스 레벨에서 사용되며, 특정 리소스에 대한 간단한 설명을 제공합니다. tags 속성을 사용하여 태그를 추가할 수 있습니다.
  • @ApiOperation: 메소드 레벨에서 사용되며, API 작업에 대한 짧은 설명을 제공합니다. 추가적인 메타데이터를 추가하기 위해 notes, response, value 등의 속성을 사용할 수 있습니다.
  • @ApiParam: API 매개 변수에 대한 메타데이터를 지정합니다. 설명, 이름, 기본값, 예제 값 등이 포함될 수 있습니다.
  • @ApiResponse: 메서드 레벨에 사용되며, API 호출에 대한 가능한 응답 코드와 각 코드에 대한 설명을 제공합니다.
  • @ApiImplicitParam(s): API에서 전달되는 암시적인 매개 변수 (헤더, 경로 변수, 쿼리 매개 변수 등)에 대한 설명을 제공하려면 이 어노테이션을 사용합니다. 하나의 암시적 매개 변수 정보에 @ApiImplicitParam을 사용하고, 여러개의 경우에는@ApiImplicitParams 어노테이션을 사용합니다

localhost:088/swagger-ui/index.html

결론

개발자로 지내다보면 많은 사람들과 커뮤니케이션이 필요하게 됩니다. 오히려 커뮤니케이션이 익숙하지 않은 개발자에게 문서화는 가장 효율적인 방법일 수 있습니다. 문서화 중에 Swagger는 프론트엔드 개발자와 소통하기 위한 가장 훌륭한 도구입니다.

Reference

https://typeable.io/blog/2021-09-06-api-diff.html

--

--