본문 바로가기
Spring

Spring Boot

by 스니펫 2023. 11. 1.

Gradle

빌드 자동화 시스템

  1. Java 코드를 설정에 맞게 자동으로 Build 하여 소스 코드를 실행한 가능한 jar 파일로 만들어준다.
  2. build.gradle은 Gradle 기반의 빌드 스크립트이다. 소스 코드를 빌드하고 라이브러리들의 의존성을 자동으로 관리하기 때문에 라이브러리들간의 충돌 걱정이 없어진다.

API; application programming interface

웹 서버의 기본 동작 원리

다른 소프트웨어 시스템과 통신하기 위해 따라야 하는 규칙으로, 개발자는 다른 애플리케이션이 프로그래밍 방식으로 애플리케이션과 통신할 수 있도록 API를 표시하거나 생성한다. 서로 다른 애플리케이션이 약속한 방식의 API 요청을 수행하면 정해진 결과물을 반환한다.

 

RESTful API ( Representational State Transfer )란 API 작동 방식에 대한 조건을 부과하는 소프트웨어 아키텍처이다.

 

해당 API에 적절하게 HTTP 메서드를 사용했다면, RESTful하게 설계된 RESTful API 라고 볼 수 있다. 대표적인  HTTP 메서는 다음과 같다.

  • GET : 서버에 데이터 요청
  • POST : 데이터를 서버 데이터베이스에 전송
  • PUT : 서버의 데이터를 수정
  • DELETE : 서버의 데이터를 삭제

API 테이블

API 들을 한눈에 확인하고 협업하는 개발자들과 소통하기 위해 작성하는 일종의 표

Postman 을 사용하여 API 테스트 해보기

@RestController
public class HelloController {
    @GetMapping("/api/hello")
    public String hello(){
        return "Hello World!";
    }
}

Postman 에서 워크 스페이스 생성 후 GET 방식을 선택, http://localhost:8080/api/hello URL을 입력한다. 

localhost 는 '내 컴퓨터'를 의미한다. 또한  SpringBoot 에 내장되어 있는 Tomcat 은 기본적으로 8080 포트로 서버를 실행시키도록 설정되어 있다.

더보기
  • Postman : API 개발을 빠르고 쉽게 구현할 수 있도록 도와주는 소프트웨어 플렛폼
  • Tomcat : 동적인 처리를 할 수 있는 웹 서버를 만들기 위한 웹 컨테이너, Apache Tomcat은 Apache와 Tomcat이 합쳐진 형태로 정적인 데이터 처리와 동적인 데이터 처리를 효율적으로 해줄 수 있음

HTTP 상태 코드(Status Code)

브라우저와 서버간의 요청, 응답 과정에서 발생할 수 있는 상황들을 표현할 수 있음

  • 1xx (Informational) : 요청이 수신 되었으며 처리가 계속되고 있음, 웹 브라우저와 같은 클라이언트가 서버와의 연결 상태를 확인하기 위해 사용
  • 2xx (Successful) : 클라이언트의 요청이 성공적으로 처리 되었음, 클라이언트가 요청한 데이터가 서버에서 제공됨을 의미
  • 3xx (Redirection) : 페이지 이동, 리다이렉션 등에 사용
  • 4xx (Client Error) : 클라이언트에 오류가 있음을 나타냄, 주로 클라이언트의 잘못된 요청, 인증 오류 등에 사용 ( ex. 404 : 클라이언트가 요청한 페이지나 리소스를 서버에서 찾을 수 없음을 의미 )
  • 5xx (Server Error) : 서버에 오류가 발생했음을 나타냄, 서버의 오류, 서버 과부하 등에 사용 ( ex. 서버 내부 오류가 발생함을 의미 )

테스트 코드

  • 블랙박스 테스트 : 소프트웨어 내부 구조나 동작원리를 모르는 블랙박스와 같은 상태에서, 웹 서비스의 사용자 입장에서 동작을 검사하는 방법
  • 개발자 테스트 (화이트박스 테스트) : 내부 소스 코드를 테스트하는 기법으로 사용자가 들여다 볼 수 없는 구간의 코드 단위를 테스트

JUnit

자바 프로그래밍 언어 용 단위 테스트 프레임워크. 따로 main() 메서드를 실행하거나 서버를 실행시키지 않아도 각각의 메서드 혹은 기능별로 테스트 코드를 작성하여 실행시킬 수 있도록 해준다.

Calculator 클래스에 대한 CalculatorTest 생성
메소드나 클래스 단위로 실행시켜 테스트할 수 있다.

Lombok

자바 프로젝트에 반필수적인 메서드/생성자 등을 자동 생성해줌으로써 코드를 절약할 수 있도록 도와주는 라이브러리이다. 

@Getter
public class Memo {
    private String username;
    private String contents;
}

클래스 위에 롬복 @Getter를 추가한 후 build에서 컴파일된 코드를 확인해보면 직접 작성하지 않은 getUsername(), getContents() 메서드가 자동으로 추가되어있음을 확인할 수 있다. ( cf. @Setter )

  • @AllArgsConstructor : 모든 필드를 파라미터로 가진 생성자를 만들어 준다.
  • @NoArgsConstructor : 기본 생성자를 만들어 준다.
  • @RequiredArgsConstructor : final 제어자가 붙은 필드를 파라미터로 가진 생성자를 만들어 준다.

application.properties

Spring과 관련된 설정을 할 때 사용되는 파일이다.

DB 연결 시 이 파일을 이용하여 쉽게 DB의 정보 값을 전달할 수 있다. 또한 Apache Tomcat을 사용하여 서버를 실행하면 기본 port 설정이 8080으로 되어 있는데, 이 파일에서 server.port=8081 로 설정을 하면 서버의 port 번호를 ‘8080’에서 ‘8081’로 바꿔서 실행시킬 수 있다.

 

Spring MVC ( Model-View-Controller )

  • Model : 데이터와 비즈니스 로직 담당
  • View : 사용자 인터페이스 담당
  • Controller : Model과 View 사이의 상호작용을 조정하고 제어, 사용자의 입력을 받아 Model에 전달하고, Model의 결과를 바탕으로 View를 업데이트

Spring Web MVC는 Servlet API를 기반으로 구축된 독창적인 웹 프레임워크, 중앙에 있는 DispatcherServlet이 요청을 처리하기 위한 공유 알고리즘을 제공하는 Front Controller 패턴을 중심으로 설계되어 있음

(HTTP) API 요청했을 때 서버의 서블릿의 동작

  • Servlet;서블릿 : 자바를 사용하여 웹 페이지를 동적으로 생성(필요를 다하면 소멸)하는 서버 측 프로그램 / 사양

  1. 사용자가 Client(브라우저)를 통해 서버에 HTTP Request 즉, API 요청
  2. 요청을 받은 Servlet 컨테이너는 HttpServletRequest, HttpServletResponse 객체 생성
  3. 어떠한 Servlet에 대한 요청인지 찾음
  4. 해당 Servlet에서 service 메서드를 호출한 뒤 브라우저의 요청 Method에 따라 doGet 혹은 doPost 등의 메서드를 호출
  5. 동적 페이지를 생성한 뒤 HttpServletResponse 객체에 응답을 담아 Client(브라우저)에 반환
  6. 응답이 완료되면 생성한 HttpServletRequest, HttpServletResponse 객체를 소멸

But 서블릿의 동작 방식에 맞춰 코드를 구현한다면 무수히 많은 Servlet 클래스를 구현해야 함

따라서 Spring은 DispatcherServlet을 사용하여 Front Controller 패턴 방식으로 API 요청을 효율적으로 처리함

Front Controller 패턴 동작과정

1. Client(브라우저)에서 HTTP 요청이 들어오면 DispatcherServlet 객체가 요청을 분석

2. 분석한 데이터를 토대로 Handler mapping을 통해 Controller를 찾아 요청을 전달

    ( ex. GET /api/hello → HelloController 의 hello() 함수 )

  • Handler mapping 에는 API path 와 Controller 메서드가 매칭되어 있음
@RestController
public class HelloController {
    @GetMapping("/api/hello")
    public String hello() {
        return "Hello World!";
    }
}
  • API path 즉, URL을 Controller에 작성하는 방법은 @Controller 애너테이션이 달려있는 클래스를 생성한 뒤 @GetMapping 처럼 요청한 HTTP Method 와 일치하는 애너테이션을 추가한 메서드를 구현
  • 직접 Servlet을 구현하지 않아도 DispatcherServlet에 의해 간편하게 HTTP 요청을 처리할 수 있게 됨

3. Controller → DispathcerServlet : 해당 Controller는 요청에 대한 처리를 완료 후 처리에 대한 결과 즉, 데이터('Model')와 'View' 정보를 전달

4. DispatcherServlet → Client : ViewResolver 통해 View에 Model을 적용하여 View를 Client에게 응답으로 전달

Servlet Code VS Controller Code

// Servlet Code
// 4개의 API를 처리하기 위해 무려 3개의 클래스를 만들어야 함

@WebServlet(urlPatterns = "/user/login")
public class UserLoginServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}
}

@WebServlet(urlPatterns = "/user/logout")
public class UserLogoutServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}
}

@WebServlet(urlPatterns = "/user/signup")
public class UserSingUpServlet extends HttpServlet {
	@Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}

	@Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) {
		// ... 
	}

}

 

// Controller Code
// 유사한 성격의 API 를 하나의 Controller 로 관리

@Controller // Controller 임을 명시
@RequestMapping("/user") // @RequestMapping은 중복되는 URL를 단축시켜줌
public class UserController {
  @GetMapping("/login") // HTTP Method에 매핑되는 애너테이션 → @GET
  public String login() {
      // ...
      return "login"; // Controller가 login.html(View name 정보)을 찾아 반환함
  }

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

  @GetMapping("/signup")
  @ResponseBody // signup.html을 찾아 반환하지 않고 순수하게 String "signup" 문자열을 반환하도록 만듦
  public String signup() { 
      // ... 
      return "signup";
  }
	
  @PostMapping("/signup") // @POST
  public String registerUser(SignupRequestDto requestDto) {
      // ... 
  }
}

정적 페이지와 동적 페이지

정적 페이지

이미 완성된 정적인 html 파일을 Controller를 통해서 반환할 필요는 없으나, static 폴더의 html 파일(정적 페이지)을 Controller를 통해서 처리하고 싶다면 return "redirect:/hello.html"; 과 같이 redirect 요청을 문자열로 반환한다. 그러면 http://localhost:8080/hello.html 요청이 재 수행되면서 static 폴더의 파일을 반환할 수 있다.

또는 templates 폴더에 해당 정적 html 파일을 추가하고 해당 html 파일명인 "hello" 문자열을 반환하여 처리할 수 있다. (.html은 생략가능)

동적 페이지

Template engine(Thymeleaf) 에게 View( 동적 HTML 파일 ), Model( View 에 적용할 정보들 ) 전달 후 View에 Model을 적용 → 동적 웹페이지 생성

@Controller
public class HtmlController {
    private static long visitCount = 0;

    @GetMapping("/html/dynamic")
    public String htmlDynamic(Model model) { // Model을 객체로 제공해 줌
        visitCount++;
        model.addAttribute("visits", visitCount); // addAttribute(데이터명, 데이터)
        return "hello-visit";
    }
}
<div>
  (방문자 수: <span th:text="${visits}"></span>)
</div>

'Spring' 카테고리의 다른 글

정적 컨텐츠, MVC, API  (0) 2024.06.24
라이브러리, view 환경설정  (0) 2024.06.23
IoC Container, Bean, JPA  (0) 2023.11.04
MySQL 실행 오류, 데이터 처리  (0) 2023.11.03