Spring 심화반 - 1주차 - 1

귀찮Lee·2022년 4월 12일
0

2022년 4월 12일(화)
[스파르타코딩클럽] Spring 심화반 - 1주차

◎ Servlet 으로 API 구현

  • Servlet(서블릿): 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말함

  • 예시 (현업에서 소수 Servlet을 사용한다 함)

@WebServlet(urlPatterns = "/api/search")
public class ItemSearchServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. API Request 의 파라미터 값에서 검색어 추출 -> query 변수
        String query = request.getParameter("query");

        // 2. 네이버 쇼핑 API 호출에 필요한 Header, Body 정리
        RestTemplate rest = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("X-Naver-Client-Id", [Naver-Client-Id]);
        headers.add("X-Naver-Client-Secret", [Naver-Client-Secret]);
        String body = "";
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);

        // 3. 네이버 쇼핑 API 호출 결과 -> naverApiResponseJson (JSON 형태)
        ResponseEntity<String> responseEntity = rest.exchange("https://openapi.naver.com/v1/search/shop.json?query=" + query, HttpMethod.GET, requestEntity, String.class);
        String naverApiResponseJson = responseEntity.getBody();

        // 4. naverApiResponseJson (JSON 형태) -> itemDtoList (자바 객체 형태)
        //  - naverApiResponseJson 에서 우리가 사용할 데이터만 추출 -> List<ItemDto> 객체로 변환
        ObjectMapper objectMapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        JsonNode itemsNode = objectMapper.readTree(naverApiResponseJson).get("items");
        List<ItemDto> itemDtoList = objectMapper
                .readerFor(new TypeReference<List<ItemDto>>() {})
                .readValue(itemsNode);

        // 5. API Response 보내기
        //  5.1) response 의 header 설정
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        //  5.2) response 의 body 설정
        PrintWriter out = response.getWriter();
        //     - itemDtoList (자바 객체 형태) -> itemDtoListJson (JSON 형태)
        String itemDtoListJson = objectMapper.writeValueAsString(itemDtoList);
        out.print(itemDtoListJson);
        out.flush();
    }
}

◎ Controller

  • Controller 의 장점
    • HTTP request, response 처리를 위해 매번 작성해 줘야하는 중복코드들 생략 가능
    • API 이름마다 파일을 만들 필요 없음
@Controller
public class UserController {
	@GetMapping("/user/login")
	public String login() {
	    // ...
	}

  	@GetMapping("/user/logout")
 	 public String logout() {
   	  	 // ...
  	}

	@GetMapping("/user/signup")
	public String signup() { 
		// ... 
	}
	
	@PostMapping("/user/signup")
  	public String registerUser(SignupRequestDto requestDto) {
		// ... 
	}
}

◎ 스프링 MVC 이해

  • 스프링 MVC : MVC (Model - View - Controller) 디자인 패턴

  • 정적 (static) 웹 페이지에서 Controller

    • Client 의 요청을 Model 로 받아 처리
    • Client 에게 View (정적 웹 페이지, HTML) 를 내려줌
  • 동적 (dynamic) 웹 페이지에서 Controller

    • Client 의 요청을 Model 로 받아 처리
    • Template engine 에게 View, Model 전달
      • View: 동적 HTML 파일
      • Model: View 에 적용할 정보들
    • Template engine
      • ViewModel 을 적용 → 동적 웹페이지 생성
      • Template engine 종류: 타임리프 (Thymeleaf), Groovy, FreeMarker, Jade 등 (스프링에서 JSP 이용은 추천하지 않고 있음)
    • Client 에게 View (동적 웹 페이지, HTML) 를 내려줌
  • 스프링 MVC 동작원리

    • DispatcherServlet: 가장 앞단에서 요청을 받음(FrontController 라고도 함)
    • Handler mapping: API path 와 Controller 함수가 매칭되어 있음
    • Controller → DispathcerServlet
      • Controller 가 Client 으로 받은 API 요청을 처리
      • 'Model' 정보와 'View' 정보를 DispatcherServlet 으로 전달
    • ViewResolver : 'Model' 정보와 'View' 정보를 조합해서 하나의 View로 만듦 (Thymeleaf)

◎ HTTP 메시지

  • Client 와 Server 간 Request, Response 는 HTTP 메시지 규약을 따름

  • HTTP 메시지는 웹 서비스 개발자(백엔드, 프론트 개발자)에게 매우 중요한 내용이다. (API 통신시 안되는 이유를 쉽게 파악 가능)

  • HTTP Request 메시지 구조(필요 내용만)

    • 시작줄: API 요청 내용
      - GET naver.com HTTP/1.1
    • 헤더의 "Content type" (필수요소 아님)
      • Content type: application/x-www-form-urlencoded // HTML form 태그로 요청 시
      • Content type: application/json // AJAX 요청시
    • 본문
      • GET 요청 시: (보통) 없음
      • POST 요청 시: (보통) 사용자가 입력한 폼 데이터
  • HTTP Response 메시지 구조(필요 내용만)

    • 상태줄: API 요청 결과 (상태 코드, 상태 텍스트)
      - HTTP/1.1 404 Not Found
    • 헤더의 "Content type" (필수요소 아님)
      • Content type: text/html // 본문 내용이 HTML인 경우
      • Content type: application/json // 본문 내용이 JSON 인 경우
    • 헤더의 "Location" (Redirect시 사용)
    • 본문
      • HTML, JSON...
  • 추가 내용 : velog 참고

◎ Controller 와 HTTP 메세지 관계

  • Controller 와 HTTP Response 메시지

    • html template를 넘길 때는 주로 type 1 을 사용
    • JSON 데이터로 통신해야 할 때는 주로 type 4를 이용
    • @RestController = @ResponseBody + @Controller
    • 자세한 예시는 학습자료 참고
  • 동적 웹페이지 예시 (Thymeleaf 사용)

private static long visitCount = 0;

@GetMapping("/html/dynamic")
public String helloHtmlFile(Model model) {
    visitCount++;
    model.addAttribute("visits", visitCount);
    return "hello-visit";
}
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Hello Spring</title></head>
<body>
  <div>
    Hello, Spring 동적 웹 페이지!!
  </div>
  <div>
    (방문자 수: <span th:text="${visits}"></span>)
  </div>
</body>
</html>
  • Controller 와 HTTP Request 메시지

◎ AllInOneController 의 문제점

  • 현재 Servlet 대신 Controller 사용중 문제점 발생

  • AllInOneController 클래스의 문제점

    • 한 개의 클래스에 너무 많은 양의 코드가 존재
      -> 코드 이해가 어려움: 처음부터 끝까지 다 읽어야 코드 내용을 이해할 수 있음
    • 현업에서는 코드 추가 혹은 변경 요청이 계속 생김
  • 객체지향 프로그래밍(Object-Oriented Programming)을 통해 하나의 파일에 너무 많은 코드가 들어가지 않게, 역할별로 코드를 분리하고, 코드를 읽기 편하게 할 수 있다.

profile
배운 것은 기록하자! / 오류 지적은 언제나 환영!

0개의 댓글