종종 면접에서 **“Swagger 사용해보셨나요?”**라는 질문을 받는다. 사용해본 건 맞는데, 대답이 자신감있게 나오지는 않았다. 왜 그랬을까 생각해보면 이유는 단순하다.
Swagger를 API 응답값 확인용 도구로만 써왔기 때문이다. API가 제대로 내려오는지 보고, 필드 값 확인하고, 그 정도 선에서만 사용했다.
그래서 막상 면접에서 이 질문을 받으면 기술적인 이야기나 협업 경험까지 자연스럽게 이어가지 못했다.
근데 곰곰이 생각해보면 이 질문의 의도는 단순히 **“Swagger라는 툴 써봤어요?”**가 아니다.
면접관이 진짜 알고 싶은 건 이런 쪽에 가깝다.
- API 스펙을 기준으로 프론트엔드랑 어떻게 맞춰서 일했는지
- 문서랑 실제 구현이 어긋났을 때 어떻게 정리했는지
- API 변경이 생기면 어디까지 영향이 가는지 어떻게 관리했는지
- 정상 케이스 말고 에러나 엣지 케이스는 어떻게 다뤘는지
결국 “Swagger를 썼다”보다 Swagger를 기준으로 어떻게 협업했고, 어떻게 관리했는지를 듣고 싶은 거다. 이런 질문에 대한 답변은 앞으로 면접 대비 차원에서 따로 계속 정리해보려고 한다.
그리고 그 전에, 오늘은 조금 다른 방향에서 접근해보려 한다.
그래서 Swagger는 도대체 서버에서 어떻게 동작하는 걸까?
Spring Boot에서는 어떤 흐름으로 API 문서가 만들어지는 걸까?
Swagger 이전에는 API 문서를 어떻게 관리했을까?
Swagger가 없던 시절에는 Confluence, Wiki, HTML 페이지, README 같은 수동 문서가 API 문서의 대부분이었다.
당시에는 프론트엔드와 백엔드 분리가 지금만큼 뚜렷하지 않았고, API 문서를 자동으로 관리해야 할 필요성도 크지 않았다.
그 결과,
- 문서는 있는데 실제 API와 다른 경우
- 누가 언제 수정했는지 알 수 없는 문서
- 필드 타입이나 필수 여부를 사람끼리 물어보며 확인하는 상황
같은 문제가 자주 발생했다. 코드와 문서가 쉽게 어긋났고, 협업 비용도 계속 커졌다.
이후 웹 프론트엔드뿐 아니라 모바일 앱 등 같은 API를 사용하는 클라이언트가 늘어나면서,
API 변경이 여러 서비스에 동시에 영향을 주게 되었고 신뢰할 수 있는 API 명세의 필요성이 커졌다.
Swagger는 왜 등장했을까?
Swagger는 이런 문제를 해결하기 위해 2010년경 Wordnik의 Tony Tam이 만들었다.
API를 “설명 문서”가 아니라 명확한 구조를 가진 명세로 관리하자는 게 핵심이었다.
이후 2015년, Swagger Specification은 Linux Foundation에 기부되었고 지금은 **OpenAPI Specification(OAS)**이라는 표준으로 자리 잡았다.
초기 Swagger 형태
초기 Swagger는 API를 **계약(contract)**처럼 엄격하게 정의하기보다는, JSON 형태로 API 구조를 설명하고 이를 UI로 시각화해 보여주는 문서 중심 도구에 가까웠다. API 목록, 요청 파라미터, 응답 구조를 한눈에 볼 수 있고 문서 화면에서 바로 API를 호출해볼 수 있다는 점이 가장 큰 특징이었다. 정적 문서를 읽고 Postman으로 다시 테스트하던 흐름을 하나의 화면으로 묶어준 것이 Swagger의 핵심 변화였다.
이후 OpenAPI 명세가 발전하면서 단순 문서를 넘어 요청·응답 구조 검증, 코드 생성, 계약 기반 개발까지 점점 역할이 확장되었다.
Swagger 관련 설정 (Spring + springdoc)
Spring 환경에서는 보통 springdoc-openapi를 통해 Swagger를 사용한다.
기본 아이디어는 간단하다. Controller와 어노테이션 정보를 기반으로 OpenAPI 스펙을 자동 생성하는 방식이다.
기본 OpenAPI 설정
- API 문서의 기본 정보(title, version, description) 정의
- JWT 기반 인증을 사용하는 경우, Security Scheme을 전역으로 등록
- Swagger UI에서 Authorize 버튼을 통해 토큰을 한 번만 입력하면
- 전체 API 호출에 적용할 수 있다
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.components(new Components()
.addSecuritySchemes("bearerAuth", new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
)
)
.addSecurityItem(new SecurityRequirement().addList("bearerAuth")) // 전체 API에 인증 적용
.info(new Info()
.title("API Documentation")
.version("1.0")
.description("API 문서입니다."));
}
Global Header 커스터마이징
- 모든 API에 공통으로 들어가는 헤더가 있다면 각 Controller마다 반복해서 작성하는 대신 이렇게 전역 Header 로 등록할 수 있다.
@Bean
public OpenApiCustomizer globalHeaderCustomiser() {
return openApi -> {
Parameter acceptLanguage = new Parameter()
.in(ParameterIn.HEADER.toString())
.name("Accept-Language")
.description("'ko' or 'en'")
.required(false)
.schema(new StringSchema()._default("ko"));
openApi.getPaths().values().forEach(pathItem -> {
pathItem.readOperations().forEach(operation -> {
operation.addParametersItem(acceptLanguage);
});
});
};
}
API Grouping
- springdoc은 API를 그룹 단위로 분리할 가능(서비스 규모가 커지면 API를 찾기 위한 스크롤 압박이 커짐)
- 버전별(/v1) 또는 도메인(auth, promotion 등) 기준으로 분리 가능
- 프론트엔드나 다른 팀과 협업할 때 필요한 API만 보여줄 수 있음
springdoc:
api-docs:
enabled: true
group-configs:
- group: v1
paths-to-match: /v1/**
- group: auth
packages-to-scan: com.example.application.api.auth
- group: promotion
packages-to-scan: com.example.application.api.promotion
- group: settings
packages-to-scan: com.example.application.api.settings
- group: support
packages-to-scan: com.example.application.api.support
swagger-ui:
path: /swagger-ui
persist-authorization: true
operations-sorter: method
tags-sorter: alpha
urls-primary-name: v1
Controller 레벨 문서화
- @Tag : API를 묶는 단위 (그룹 내 섹션)
- @Operation : API 한 개에 대한 요약과 설명
- @Parameter(hidden = true) : 내부에서만 쓰는 값은 문서에서 숨김 처리
@Tag(
name = "Notice API",
description = "공지 관련 API 입니다."
)
@RestController
@RequestMapping("/api/notices")
public class NoticeController {
@Operation(
summary = "공지 목록 조회",
description = "공지사항 목록을 조회합니다."
)
@GetMapping(produces = "application/json")
public ApiResponse<List<NoticeResponse>> getNoticeList(
@Parameter(hidden = true) @AuthenticatedUser UserContext userContext
) {
// ...
}
}
Swagger 서버는 어떻게 켜질까? 포트 번호는?
Swagger는 별도의 서버가 뜨는 게 아니다.
Spring Boot 애플리케이션 안에서 함께 동작한다.
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
이 의존성을 추가하면:
Spring Boot 실행
→ Embedded Tomcat 기동
→ Controller 스캔
→ springdoc이 @RestController + OpenAPI 어노테이션 분석
→ OpenAPI JSON 생성
→ Swagger UI 제공
- 포트 번호는 애플리케이션 포트와 동일
- 기본 접속 경로: /swagger-ui 또는 /swagger-ui/index.html
- OpenAPI JSON: /v3/api-docs
springdoc은 Spring의 HandlerMapping 정보를 기반으로 실제 매핑된 API만을 사용해 OpenAPI 스펙을 동적으로 생성한다.
'Dev Log' 카테고리의 다른 글
| Spring Batch 프로젝트 동작 원리 정리 (0) | 2025.12.28 |
|---|---|
| “Swagger 사용해보셨나요?”라는 질문에 제대로 답하기2 (0) | 2025.12.21 |
| API 개발 과정에서 반복되는 SQL 질문 (1) | 2025.12.07 |
| 서버 Yaml 파일 개념 정리 (2) | 2025.11.26 |
| Expo / EAS Build 사용하면서 겪은 이슈 정리 (1) | 2025.11.23 |