코틀린 백엔드 프로젝트 2기 - 3주차

코틀린 백엔드 프로젝트 2기 - 3주차

섹션 4 6강 ~ 섹션 5 9강까지의 내용 학습

 

타임리프 문법 정리

  • xmlns:th=""

    • 타임리프의 네임스페이스 선언, 타임리프 문법 사용을 위한 선언 문법

       

  • th:fragment=""

    • 템플릿 일부 재사용을 위한 문법

  • th:replace=""

    • 해당 요소를 다른 요소로 대체할 때 사용, fragment로 대체할 영역에 사용

  • th:href=""

    • 링크의 URL을 동적으로 설정

  • th:each=""

    • 반복문, 반복할 데이터의 개수만큼 HTML 요소를 생성

  • th:class=""

    • HTML 요소의 클래스를 동적으로 설정합니다

  • th:text=""

    • 텍스트 컨텐츠를 동적으로 설정

 

컨트롤러 개발

@RestController

@controller와 @ResponseBody가 합쳐진 어노테이션, 리턴을 HTTP 바디에 문자열로 넣을 수 있으며 JSON형식으로도 지정이 가능

@RequestMapping("/경로")

클래스 단위에 달아주고 경로를 설정해주면 컨트롤러 클래스의 ENTRY 포인트 지정

@GetMapping("/test")

메서드 단위에 달아주면 컨트롤러에 진입한 메서드의 ENTRY 포인트 지정

http 메서드 get을 받음, post, put, patch, delete도 존재

 

@RestController
@RequestMapping("/api")
class PresentationApiController(
    private val presentationService: PresentationService
) {

    @GetMapping("/test")
    fun test(): String {
        return "OK"
    }
}

/api의 경로 에서 /test로 진입하면 fun test() 메소드가 실행됨

현재 코드에선 "ok"가 리턴됨 즉, HTTP 바디에 OK하는 문자열이 담김

 

@Controller

해당 어노테이션이 붙은 클래스는 리턴값의 이름과 같은 html파일에 연동됨 해당 html파일에는 model을 이용해서 값을 넘겨줄 수 있으며 해당 html파일이 view가 되어 model에 담긴 값을 꺼내어 사용하고 타임리프 뷰 템플릿을 사용하여 동적으로 만들어 주는 것이 가능함

@Controller
class PresentationViewController(
    private val presentationService: PresentationService
) {
    @GetMapping("/resume")
    fun resume(model: Model): String {
        val resume = presentationService.getResume() 
        model.addAttribute("resume", resume)
        model.addAttribute("skillTypes", SkillType.values())
        return "presentation/resume"
    }
}

get 메서드로 /resume로 요청을 하면 fun resume() 메소드가 실행됨

모델에 resume, SkillType.values() 값을 담고 리턴을 하면 리턴에 해당하는 html파일에서 모델에 담긴값을 이용해서 뷰를 꾸며줌

 

컨트롤러 테스트 코드

  • @SpringBootTest

    • Spring Boot 애플리케이션을 테스트하는 데 사용 실제 애플리케이션과 유사한 환경을 구성하여 테

      스트를 실행할 수 있습니다

  • @AutoConfigureMockMVC

    • Spring MVC를 모의 테스트 할 때 사용, MockMVC객체가 자동으로 구성되어 컨트롤러를 모의로 테스트 하는것이 가능함

    @SpringBootTest
    @AutoConfigureMockMvc
    @DisplayName("[API 컨트롤러 테스트]")
    class PresentationApiControllerTest(
        @Autowired private val mockMvc: MockMvc
    ) {
    
        @Test
        @DisplayName("Introductions 조회")
        fun testGetIntroductions() {
        // given
            val uri = "/api/v1/introductions"
        // when
            val mvcResult = performGet(uri)
            val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8)
            val jsonArray = JSONArray(contentAsString)
        // then
            assertThat(jsonArray.length()).isPositive()
        }
    
        private fun performGet(uri: String): MvcResult { 
            return mockMvc
               .perform(MockMvcRequestBuilders.get(uri))
               .andDo(MockMvcResultHandlers.print())
               .andReturn()
        }
    
    }

    @Autowired private val mockMvc: MockMvc

mockmvc를 주입받아서 모의 객체 생성을 함

"/api/v1/introductions"의 uri로 요청을 하면 해당 경로의 메서드가 실행되어 응답을 받고 그 응답을검증함.

 

 

인터셉터 개발

인터셉터의 호출 순서는

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러

이며 컨틀롤러 도달전의 호출된다

HandlerInterceptor 를 구현하였고 프로젝트에선 afterCompletion만 오버라이딩 하여 모든 요청에 대한 정보를 데이터 베이스에 저장하도록 구현하였다

인터셉터는 경로를 설정하여 어떤 경로게 대하여 인터셉터를 실행할지 결정이 가능하다

WebMvcConfigurer 를 구현한 클래스의 addInterceptors() 메소드를 통해 인터셉터를 등록하고 경로 설정이 가능하다

override fun addInterceptors(registry: InterceptorRegistry) {
    registry.addInterceptor(presentationInterceptor)
     .addPathPatterns("/**")
     .excludePathPatterns("/assets/**", "/css/**", "/js/**", "/admin/**", "/h2**",
      "/favicon.ico", "/error")
 }

 

 

어드민 패키지

AdminApiControllerAdvice

@RestControllerAdvice 를 사용하면 전역적으로 모든 컨트롤러에 대한 예외를 처리하는 것이 가능해진다.

@ExceptionHandler와 같이 사용해야 하며 특정 예외 클래스에 대한 핸들러 메서드를 작성할 수 있습니다.

오류의 종류

image개발자가 직접 처리가 가능한 오류는 Exception의 하위 오류들이다. 애플리케이션에서 대응할 수 있는 오류로서

UnckechedException, ckechedException이 존재하고 UnckechedException은 실행중에 발생하는 오류이다.

 

 

댓글을 작성해보세요.

채널톡 아이콘