레벨2 2주차

@VERO
Created Date · 2023년 04월 25일 01:04
Last Updated Date · 2023년 04월 25일 01:04

4/25

2주차 목표

  • 템플릿 엔진을 이용해 페이지 응답을 경험한다.
  • 웹 애플리케이션에서의 테스트와 전구간 기능 테스트 구현을 경험한다.
  • 인증 방법에 대해 학습하고 직접 구현해본다.
  • Spring MVC Configuration 설정을 경험한다.
  • Spring MVC 에서 MVC는 무엇을 의미하고 활용하는 이유를 궁금해 해보자.

목표와 계획을 제출한 이유

내가 잘 알고 있는 것이 맞는가? 어떻게 하면 더 잘 알 수 있을까? 에 대해 스스로에게 계속해서 질문을 던지자.

한 번 세운 목표와 계획은 끝까지 가야 하나?

목표: 레벨2 로드맵에 있는 것들을 제대로 알고 쓰고 싶다. 방법: 학습 로그 스터디를 하고, 공부하면서 모르는 내용을 계속해서 마인드맵처럼 공부하자.

다음의 질문을 계속하자.

  • 레벨2가 끝날 때 내가 세운 목표를 달성했을 때의 내 모습이 만족스러울 것 같은가?: 만족스러울 것이다. 그러나 더 알았어야 했나라는 생각은 들 것 같다.
  • 목표를 달성하는 것이 진정 내가 원하는 모습인가? 내가 원하는 모습에 도달하기 위한 목표는 아닌가? : 원하는 모습은 내가 쓰는 기술들을 알고 쓰는 것이다. 시간은 많으니 지금은 도달하지 못하더라도 계속해서 목표에 가까워지는 사람이 될 수 있을 것이다.
  • 계획을 달성하면 목표에 도달할 수 있는가?: 도달할 수는 있지만, 완전히 도달할 수 있는지는 알 수 없다.
  • 실행하는 데 어려움은 없었는가? 그 어려움은 해결할 수 없는 어려움은 아닌가?: 아직은 무엇을 모르는지, 어떤 것을 알아야 하는지 알지 못한다. 무언가를 판단하기에 지금은 너무 이른듯하다.

Spring MVC 어디까지 왔나?

Spring MVC Annotation + Exception -> 오늘 Dispatcher Servlet이 추구하는 패턴 -> 두 번째 피드백 강의 HTTP & REST, API 설계 -> 금요일 강의 인증 + Spring MVC Configuration -> 다음 주 화요일 강의

Spring MVC Configuration이나 Spring MVC Annotation 등에서 삽질을 많이 해봐야 Dispatcher Servlet을 이해하기 수월할 것이다.

Template Engine

(오늘 토리랑 허브랑 이야기한 내용인데 나와서 신기하다 ㅋㅋ)

request-structure.png

view는 Dispatcher Servlet에 의해 변환된다. 템플릿을 가지고 view가 결과물을 만들어서 Web browser에 전달한다.

@Controller
public class SampleController{

	@RequestMapping(value = ~~)
	public String SampleMethod(Model model) {
		model.addAttribute("~~~~");
		return "sample";  // sample 이라는 template를 찾는다.
	}
}

템플릿의 기본 경로는 src/main/resources/templates이다.

Spring MVC는 thymeleaf view를 찾고, thymeleaf는 template으로 렌더링을 한다. 렌더링한 것을 web browser한테 전달한다.

SpringBootTest

@SpringBootTest

  • 테스트 환경을 손쉽게 설정하도록 도와줌
  • ApplicationContext를 자동으로 생성하여 테스트에서 사용할 수 있게 함
  • 기존 @ ContextConfiguration의 발전된 기능

webEnvironment

@SpringBootTest의 webEnvironment 속성을 사용하여 테스트 서버의 실행 방법을 설정

  • MOCK: Mocking된 웹 환경을 제공, MockMvC를 사용한 테스트를 진행 할 수 있음. 가짜 웹 환경을 구성한다.
  • RANDOM_PORT: 실제 웹 환경을 구성
  • DEFINED_PORT: 실제 웹 환경을 구성, 지정한 포트를 listen
  • NONE: 아무런 웹 환경을 구성하지 않음

mockmvc.png

RestAssured

rest-assured-test.png RANDOM_PORT를 쓰면 포트 번호를 모르니까 주입을 받아야 한다.

주입 받을 때 @LocalServerPort 로 주입을 받아야 한다.

@LocalServerPort
int port;

@BeforeEach
public void setUp() {
	RestAssured.port = port;
}

RestAssured와 SpringBootTest로 전체 테스트를 경험해보자.

왜 부분이 아닌 전체를 검증할까?
부분과 전체 중에 어떤 것이 더 중요할까?

4/28

좋은 API 설계란?

API 설계를 꼭 잘해야 하는가?

그냥 서버와 클라이언트 간의 약속만 잘하면 되는 거 아닌가?

but...

  • 한 번 정해진 API는 바꾸기 쉽지 않다. API의 변경에 클라이언트가 영향을 받기 떄문이다.
  • 새로운 데이터 요소와 비즈니스 규칙이 계속 추가/변경될 수 있다. 확장성 있는 API를 만들게 되면 앞으로의 시간을 아낄 수 있다.
  • 잘 설계된 API는 커뮤니케이션 비용을 아껴준다.

API 설계 표준화 시도

  • 한 곳에 모아서 비교할 수 있는 서비스가 있었지만 없어졌다.
  • 표준을 만드는 시도들이 있었지만 거의 사용되지 않고 있다.
  • 각 서비스들마다 요구사항이 다르고 환경이 다르다.
  • 자신들만의 설계를 원하는 경향이 있다.

좋은 API 특징

  • 배우기 쉬울 것
  • 문서가 없어도 사용하기 쉬울 것
  • 잘못 사용하기 어려울 것
  • 읽기 쉽고, API를 사용하는 코드를 유지보수하기 쉬울 것
  • 요구사항을 만족시키기에 충분히 강할 것
  • 확장하기 쉬울 것
  • 사용하는 사람들의 수준에 맞을 것

REST

미션 권장사항은 아님.

REST 란?

  • WWW(web)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍 처의 한 형식, 로이 필딩의 2000년 논문을 통해서 공개
  • 당시 웹은 큰 성공을 거두었지만 발전이 너무 빨라 관련 내용에 대한 표준이나 문서가 부족한 시기
  • 웹과 같은 시스템이 어떻게 동작해야 하는지에 대한 구조적 모델을 만들어내고 표준 역할을 하기 위해 몇 가지 제약 조건을 만들어 냄
  • 웹 기반으로 동작하는 대부분의 서비스도 글 뿐이 아닌 다양한 형태로 제공되기 때문에 분산 하이퍼미디어 시스템으로 볼 수 있음

요즘 REST 용어의 사용

  • 최초 소개되었던 목적 보다 다소 과하게 쓰이기도 함
  • 잘못 사용되는 경우도 많음
  • 역사적인 관점에서 SOAP API와 경쟁관계인 시점에 마케팅 버즈워드로 많 이 사용되면서 SOAP 계열의 반대 슬로건으로 사용됨
  • 그럼에도 리소스와 URI의 개념 등 API 설계 시 중요한 요소로 잘 스며들었다고 평가됨
  • RESTful API 규칙이라고 불리는 것은 참고만 하고, 추상적인 제약 조건을 이해하고 일부 조건의 구체적인 세부 규칙을 직접 정해보자.
  • 이게 어렵다면 굳이 REST를 시도하지 말고 HTTP 프로토콜 사용법에 맞는 정도로만 API를 설계하자.

용어 설명

리소스

자원과 내부적인 클래스 설계는 다를 수 있다. 또한 클래스 설계는 데이터베이스와 다를 수 있다.

주소창으로 요청을 보내면 웹 페이지를 응답받을 수 있다. 페이지나 json 형태의 문자열을 응답으로 받을 수 있다. 서버로부터 얻을 수 있는 자원이 리소스다.

즉, 리소스란

  • 네트워크 데이터 개체
  • 클라이언트가 얻길 원하는 것
  • URI로 식별할 수 있는 대상

URI - path와 query

  • path: 계층적 형태로 구성된 데이터
  • query: 비계층적 형태로 구성된 데이터

리소스의 표현

서버로부터 응답 받는 것은 리소스인가? -> 아니다.

RacingCar 를 받는다고 했을 때 실제로 RacingCar 를 응답 받는 것이 아니라 표현을 전달받는 것이다.

서버는 리소스의 표현만 내려주는 것이 아니라 해석하는 방법을 알려줘야 한다. => 클라이언트가 리소스에 GET 요청을 보내면 서버는 그 리소스를 나타내는 방법을 제공해야 한다.

Content-Type: application/json;charset=UTF-8

만약 여러 개의 표현이 있는 리소스라면?

  • /racingcars/1이라는 리소스를 요청할 때 html 표현과 json 표현이 있다면 어떻게 해야할까?
    • html: 1번 레이싱카를 소개하는 페이지
    • json: 1번 레이싱카의 정보를 응답하는 JSON

많이 사용하는 API 설계

리소스 네이밍 가이드

@RestController
public class CartApiController {
	@PostMapping("/cart/add/{productId}")
	public ResponseEntity addCart(@PathVariable String productId) {
		cartService.addCart(autoService.toCart(Long.parseLong(productId)));
		return new ResponseEntity(HttpStatus.OK);
	}
}

Cart의 add는 계층이라고 보기 어렵다. add를 빼고, POST로 표현하는 것이 더 좋지 않을까.

@RestController
public class HttpMethodController {
	@GetMapping("/items")
	public ResponseEntity<Void> addItem(@RequestBody Item item) {
		Item item = itemService.addItem(item);
		return ResponseEntity.ok().build();
	}
}

GET이 아닌 POST가 되면 좋을 것 같다. ok 대신 201 (CREATED) 를 사용하면 좋겠다.