본문 바로가기
web/SpringBoot

Spring Boot 3.1.x 환경세팅부터 Swagger 까지(2)

by 뽀리님 2023. 8. 17.

지난시간에 이어 오늘은 swagger 페이지까지 띄워보겠다.

 

보통 Swagger UI 를 위해 Springfox 와 SpringDoc 2가지를 많이 쓴다.

그러나 Springfox 경우 2020년 이후로 업데이트가 되지 않은 반면 SpringDoc은 꾸준히 업데이트 중이다.(springDoc 공식 문서 참조)

또한, Spring boot 3.x 버전대에는 Springfox는 지원되지 않으므로SpringDoc을 이용하여 Swagger를 구현해보도록 하겠다.

 

 

1. build.gradle 에 다음 의존성을 추가한다.

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

 

2. Swagger Class 를 추가한다. 

@OpenAPIDefinition(
        info = @Info(
                title = "API TITLE",
                description = "API DESCRIPTION",
                version = "v1"
        )
)
@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI();
    }
}

 

io.swagger.v3.oas.annotations 패키지에 있는 어노테이션을 사용하여OpenAPI 를 정의 하고 빈(@Bean)을 등록한다.

  • title: API의 이름 또는 제목
  • description: API에 대한 간단한 설명을 제공
  • version: API 버전

(Spring Security 를 사용한다면)

Spring Security 기본설정에 의해 보호된 리소스에 대한 접근 시 로그인이 필요하도록 설정되어 있으므로, Security 설정을 해줘야 한다.

 

3. SecurityFilterChain 설정

@Configuration // Ioc Bean 등록
@EnableWebSecurity // Spring Security 사용
@RequiredArgsConstructor // 생성자 자동생성
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .httpBasic(AbstractHttpConfigurer::disable) // HTTP 기본 인증 비활성화
                .formLogin(AbstractHttpConfigurer::disable) // 폼 기반 로그인 비활성화
                .build();
    }

}

 

Spring Security 5.7.0-M2 부터 WebSecurityConfigurerAdapter Deprecated 되었고 기존에 security 예외 url 설정하던 antMatchers 아예 삭제되었으므로 Spring Boot 3.x 버전부터는 SecurityFilterChain 를 사용하여 구현해야한다.

또한 non-lamda-DSL -> lamda-DSL 변경되었으며  인증,인가 옵션등을 HttpSecurity 쪽에 등록해야 한다.

 

@RequiredArgsConstuctor

    • final 키워드가 붙은 필드에 대해 생성자를 만들어준다. -> 인스턴스가 생성될 1번만 참조되므로 코드 변이의 걱정은 사라진다.
    • 생성자의 파라미터 타입이 Bean으로 등록되어 있다면  @Autowired 어노테이션 없이도 스프링부트가 자동으로 의존성 주입(DI)을 해준다
    • Spring 4.3부터는 @Autowired 사용을 지양하고 항상 생성자 주입을 사용하는 것을 권장한다. -> 한번 의존성 주입을 받은 객체는 프로그램이 끝날 때까지 변하지 않는 특징을 가지므로 불변성을 표시해주는 것이 좋기 때문이다. (객체의 불변성(Immutability) 보장)

@Autowired는 DI가 타입(Type)이 같은 빈(Bean)이 발견되면 그냥 주입한다.

지금까지 의존성 주입이 간편했던 이유인데 이것이 문제가 되는 이유는 같은 Type의 다른 객체가 여러 개일 때 문제가 발생한다.

DI Type 보고 내려주기에 서로 다른  A타입의 객체가 2 존재한다면 @Autowired Error 띄울 수밖에 없다.

 

 

 

 

 

 

4. 컨트롤러 및 서비스 작성

테스트를 위해 API endpoint 정의와 Service 를 각각 간단하게 작성한다.

 

- controller

@Tag(name = "User API", description = "사용자 관련 API") // swagger 에서 API 타이틀, 설명
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
@Slf4j
public class UserController {
    final private UserService userService;

    /**
     * SwaggerTest
     * @return
     */
    @GetMapping("/hello")
    @Operation(summary = "api endpoint title", description = "동작테스트설명")
    @ApiResponse(responseCode = "200", description = "결과설명")
    ResponseEntity<?> getHelloWorld(){
        String result = userService.tellHelloWorld("world");
        return new ResponseEntity<>( result + " By Get Method", HttpStatus.OK);
    }
    
}

 

@Contoller 와 @RestController 의 차이는 대부분 다 알고있을꺼라 넘어가려한다. 간단하게 설명하자면,

@Controller

-> 예전에 Spring MVC에서 View 반환하기 위해 사용했었다. 그래서 주로 ViewResolver를 통해 뷰를 찾아 랜더링한다.

ex) return "/users/detailView";

 

@RestController 

-> @Controller+@ResponseBody가 추가된 것으로 주 용도는 Json 형태로 객체 데이터를 반환하는 것이다.(ResponseEntity)

REST API를 개발할 때 주로 사용한다.

(실제로 @Controller @ReponseBody 붙인 것과 동일하게 작동한다.)

 

 

- service

@Service
public class UserService {
    public String tellHelloWorld(String hello) {
        if (hello != null) {
            return "hello " + hello;
        } else {
            return "param is null";
        }
    }
}

 

@Service 

@Component 는Spring에서 관리되는 객체임을 표시하기 위해 사용하는 가장 기본적인 annotation 이고,

@Service도 @Component 안에 포함되지만, 역할을 명시적으로 구분해주기 위해 각자 분리해서 사용한다. 즉 Spring AOP 에 부합하는 개념이고 Spring 에서 권장된다.

 

 

 

 

5. 서버 구동후

http://localhost:8080/swagger-ui/index.html

접속하면 다음과 같은 화면을 확인할 수 있다.

 

초기화면

 

API 실행시 결과화면

 

위와같이 접속이 잘된걸 확인할 수 있다. 

 

다음시간엔 DB를 연동하여 restFul API 서버 구현하는걸 해보려한다.

 

 

 

 

 

( 참조 문서 : https://docs.spring.io/spring-security/reference/migration-7/configuration.html 

https://backendcode.tistory.com/209

https://velog.io/@_koiil/Spring-Component%EC%99%80-Repository-Service-Controller

)