@Tag
API 그룹 지정. Tag에 설정된 name이 같은 것끼리 하나의 API 그룹으로 묶는다.
Controller 또는 Controller의 메서드 영역에 설정한다. REST API의 엔드포인트는 컨트롤러에 있으므로, 컨트롤러 클래스 위에 @Tag어노테이션을 붙여서 API 그룹을 설정할 수 있다.
- Target - ANNOTATION_TYPE, METHOD, TYPE
- name : 태그 이름
- description : 태그 설명
@Tag(name="User", description="사용자 API")
@RestController
@RequestMapping("/users")
public class UserApiController {
//Post, Get, Patch, ... 에 해당하는 메서드들
}

@Operation
각 API 동작(Get, Post, Put 등)에 대한 상세 설명. Controller의 메서드 영역에 설정한다.
Swagger UI에서 세부 내용을 펼치지 않았을 때 간략히 확인할 수 있는 정보는 summary에, 필요에 따라 상세 정보를 표기하고자 한다면 description에 설명을 추가한다.
- Target - ANNOTATION_TYPE, METHOD
- summary : API에 대한 간략 설명
- description : API에 대한 상세 설명
@Operation(summary = "이벤트 회원 조회", description = "특정 모임에 속한 회원을 조회한다.")
public List<EventUserDto> getUserByEvent(@Parameter(description = "모임 ID", example = "1") @PathVariable("eventId") Long eventId){
...
}

@Operation 어노테이션의 parameters 프로퍼티를 사용해 Swagger UI에 파라미터 입력 창을 띄울 수도 있다.
@Operation(summary = "이벤트 회원 조회", description = "특정 모임에 속한 회원을 조회한다.",
parameters = {@Parameter(name="eventId", description = "모임 ID")})
public List<EventUserDto> getUserByEvent(@Parameter(description = "모임 ID", example = "1") @PathVariable("eventId") Long eventId){
...
}

@Parameter
메서드 파라미터에 대한 설명 추가. 경로 변수, 쿼리 파라미터 등에서 유용하다.
타겟은 4가지지만 PARAMETER에 작성하면 name을 설정해줄 필요가 없어서 주로 PARAMETER에 작성하여 명시적으로 설정하는 것을 선호하는 듯 하다.
- Target - ANNOTATION_TYPE, FIELD, METHOD, PARAMETER
- name : 파라미터 이름
- description : 파라미터 설명
- in : 파라미터 위치
- query : query string 방식으로 전달하는 경우
- header : header에 담겨 전달하는 경우
- path : pathvariable 방식으로 전달하는 경우
- cookie : cookie에 담겨 전달하는경우
아까 @Operation의 내부 속성으로 @Parameter을 준 것과 동일하게 메서드의 @PathVariable 인자 앞에 @Parameter을 붙여서 파라미터입력창을 나타낼 수도 있다. 그런데 @PathVariable의 name속성을 파라미터 이름과 동일하게 지정해줘야 한다.
@GetMapping("/{eventId}")
public List<EventUserDto> getUserByEvent(@Parameter(description = "모임 ID", example = "1") @PathVariable("eventId") Long eventId){
...
}

@ApiResponse
각 엔드포인트 응답 상태 코드에 대한 설명 추가. 가능한 HTTP 응답 상태 코드와 그에 대한 설명, 응답 본문의 구조를 알려준다.
- responseCode - http 응답 상태코드
- description - response 에 대한 설명
- content - response payload 구조 (응답 본문이 어떤 형식으로 반환되는지 정의)
- mediaType - 응답 데이터 형식
- schema - payload에서 이용하는 schema
- hidden - schema 숨김 여부
- implementation - schema 대상 클래스
@ApiResponses 안에 value로 @ApiResponse들을 넣어주면 된다.
- responseCode = "200": HTTP 상태 코드 200은 요청이 성공적으로 처리되었음
- description = "200 ok 요청이 성공적으로 처리되었습니다.": 200 상태 코드에 대한 설명
- content = {@Content(...)}: 응답 본문이 어떤 형식으로 반환되는지 정의
- content = @Content 만 있으면 응답 본문이 제공되지 않고 단순히 상태 코드만 반환될 수 있음을 의미
- mediaType = "application/json": 응답 데이터의 형식은 JSON
- schema=@Schema(implementation = EventUserDto.class): 데이터는 EventUserDto클래스 형태임
- array=@ArraySchema(schema=@Schema(...위와 동일)) : 데이터가 EventUserDto클래스의 리스트 또는 배열 형태로 반환됨
@Operation(summary = "이벤트 회원 조회", description = "특정 모임에 속한 회원을 조회한다.")
//exceptionhandler response status
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "200 ok 요청이 성공적으로 처리되었습니다.",
content = {@Content(mediaType = "application/json", array=@ArraySchema(schema=@Schema(implementation = EventUserDto.class)))}),
@ApiResponse(responseCode = "201", description = "201 created 요청 결과 새로운 리소스가 생성되었습니다.", content = @Content),
@ApiResponse(responseCode = "202", description = "202 accepted 요청을 수신하였지만 그에 응하여 행동할 수 없습니다.", content = @Content),
@ApiResponse(responseCode = "400", description = "400 bad request 서버가 요청을 이해할 수 없습니다.", content = @Content),
@ApiResponse(responseCode = "404", description = "404 not found 서버가 요청받은 리소스를 찾을 수 없습니다.", content = @Content),
@ApiResponse(responseCode = "500", description = "500 server error 서버가 처리할 수 없는 요청입니다.", content = @Content)})
@GetMapping("/{eventId}")
public List<EventUserDto> getUserByEvent(@Parameter(description = "모임 ID", example = "1") @PathVariable("eventId") Long eventId){
...
}
@RequestBody, @RequestParam
요청 본문이나 파라미터에 대한 설명 작성
@Operation(summary = "사용자 생성")
@PostMapping("/users")
public User createUser(
@RequestBody(description = "생성할 사용자 정보") User user,
@RequestParam(description = "사용자 이름", required = true) String name) {
// 로직
}
@Schema
API Schema 지정. 각 필드값에 대한 설명, 기본값, 허용 가능 값 등 api 문서를 더 상세히 기술하는 데 사용된다.
- Target - ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE
- description : 설명
- defaultValue : 기본값
- allwableValues
@Schema(description="특정 모임에 속한 회원")
@Getter
@Setter
public static class EventUserDto{
@Schema(description = "이름", example = "김철수", required = true)
private String name;
@Schema(description = "성별", example = "M", required = true)
private Gender gender;
@Schema(description = "소개", example = "성남시 분당구에 사는 직장인입니다.", required = true)
private String introduction;
}
public List<EventUserDto> getUserByEvent(@Parameter(description = "모임 ID", example = "1") @PathVariable("eventId") Long eventId){
EventUserDto dto = new EventUserDto();
dto.setName("ddd");
dto.setGender(Gender.W);
dto.setIntroduction("ddd입니다.");
List<EventUserDto> list = new ArrayList<>();
list.add(dto);
return list;
}
이런 식으로 컨트롤러의 반환 값이 되는 엔티티에 @Schema를 붙여두면 어떤 값이 반환되는지 Swagger에 명확하게 드러낼 수 있다.

required=true로 설정하면 필드 옆에 빨간 별 표시가 뜨면서 반드시 필요한 값임을 표시할 수 있다.
컨트롤러 설정 예시
package lems.cowshed.api.controller.user;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lems.cowshed.domain.event.Event;
import lems.cowshed.domain.user.Gender;
import lems.cowshed.domain.user.User;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@Tag(name="User", description="사용자 API")
@RestController
@RequestMapping("/users")
public class UserApiController {
@Operation(summary = "모임 회원 조회", description = "특정 모임에 속한 회원을 조회한다. [이벤트 상세 > 참여자 목록]")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "200 ok 요청이 성공적으로 처리되었습니다.",
content = {@Content(mediaType = "application/json", array=@ArraySchema(schema=@Schema(implementation = EventUserDto.class)))})})
@GetMapping("/event/{eventId}")
public List<EventUserDto> getUserByEvent(@Parameter(name="eventId", description = "모임 ID", example = "1") @PathVariable("eventID") Long eventId){
//return List<EventUserDto>
EventUserDto eventUserDto = new EventUserDto();
eventUserDto.setName("kim");
eventUserDto.setGender(Gender.W);
eventUserDto.setIntroduction("안녕하세요 kim 입니다.");
List<EventUserDto> list = new ArrayList<>();
list.add(eventUserDto);
return list;
}
@Operation(summary = "마이페이지 회원 조회", description = "본인 정보를 가져온다. [마이페이지]")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "200 ok 요청이 성공적으로 처리되었습니다.",
content = {@Content(mediaType = "application/json", schema=@Schema(implementation = MyInfoDto.class))})})
@GetMapping("/my-page/{userId}")
public void getMyInfoById(@Parameter(name = "userId", description = "회원 ID", example = "1") @PathVariable("userId") Long userId){
//return MyInfoDto
}
@Operation(summary = "회원 등록", description = "새로운 회원 정보를 저장한다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "200 ok 요청이 성공적으로 처리되었습니다.",
content = {@Content(mediaType = "application/json", schema=@Schema(implementation = UserSaveRequestDto.class))})})
@PostMapping("/")
public void saveUser(@RequestBody UserSaveRequestDto userSaveRequestDto){
//return Long
}
@Operation(summary = "회원 수정", description = "회원 정보를 수정한다. [프로필 편집]")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "200 ok 요청이 성공적으로 처리되었습니다.",
content = {@Content(mediaType = "application/json", schema=@Schema(implementation = UserUpdateRequestDto.class))})})
@PatchMapping("/{userId}")
public void editUser(@Parameter(name = "userId", description = "회원 ID", example = "1") @PathVariable("userId") Long userId, @RequestBody UserUpdateRequestDto userUpdateDto){
//return
}
@Getter
@Setter
@Schema(description="특정 모임에 속한 회원")
public static class EventUserDto{
@Schema(description = "이름", example = "김철수", required = true)
private String name;
@Schema(description = "성별", example = "M", required = true)
private Gender gender;
@Schema(description = "소개", example = "성남시 분당구에 사는 직장인입니다.", required = true)
private String introduction;
}
@Getter
@Setter
@Schema(description = "마이페이지 회원 정보")
public static class MyInfoDto{
@Schema(description = "이름", example = "김철수", required=true)
private String name;
@Schema(description = "성별", example = "M", required=true)
private Gender gender;
@Schema(description = "생년월일", example = "1999-05-22", required=true)
private String birth;
@Schema(description = "성격유형", example = "ISTP")
private String character;
@Schema(description = "참여 모임", example = "")
private List<Event> joinEvents;
@Schema(description = "북마크 모임", example = "김철수")
private List<Event> bookmarkEvents;
}
@Getter
@Setter
@Schema(description = "회원 등록")
public static class UserSaveRequestDto {
@Schema(description = "이름", example = "김철수", required=true)
private String name;
@Schema(description = "성별", example = "M", required=true)
private Gender gender;
@Schema(description = "이메일", example = "cheolsukim@lems.com")
private String email;
@Schema(description = "생년월일", example = "1999-05-22", required=true)
private String birth;
@Schema(description = "지역명", example = "서울시", required=true)
private String local
'프로젝트' 카테고리의 다른 글
| [Next Step 사전과제] 도메인 설계(2) - 도메인 규칙 정의 (0) | 2025.09.18 |
|---|---|
| [Next Step 사전과제] 도메인 설계(1) - 행동과 책임 (1) | 2025.09.18 |
| (5)-2 SPA, MPA (0) | 2025.03.30 |
| (5)-1 Spring Boot3에서 Swagger 사용하기 : Swagger 설치, Swagger Config 설정 (0) | 2025.03.30 |
| (4) Rest API : Envelop pattern 봉투 패턴, 에러 공통 응답 형식 (1) | 2025.03.28 |