스프링 프레임워크의 대표적인 적용 분야인 웹 개발에 사용할 수 있는 두 가지 모듈로는 WebMVC와 RestController가 있다. WebMVC는 서블릿과 같이 MVC 패턴 기반의 웹 애플리케이션을 구현할 때 사용하는 모듈이며, RestController는 REST API 구현에 사용된다.
스프링 프레임워크 기반 개발의 가장 기본이 되는 부분이며 스프링을 처음 배울 때에도 가장 쉽게 배울 수 있는 부분이다.
WebMVC
스프링 WebMVC는 MVC 기반 웹 애플리케이션 개발과 구조적으로 거의 동일하다. 특히 컨트롤러 부분을 제외하면 모델과 뷰는 기존의 코드를 그대로 사용할 수 있을 만큼 유연한 구조를 가지고 있다.
컨트롤러
스프링을 사용하면 컨트롤러 구조를 직접 구현할 필요 없이 특정 요청에 대한 처리 메서드만 작성하면 된다. 따라서 불필요한 중복 구현을 하지 않아도 되고, 개발자가 보다 나은 컨트롤러 구조를 만들기 위해 고민할 필요가 없다.
모델
모델 부분은 기존 코드를 그대로 사용할 수 있으며, 스프링의 JDBCTemplate을 사용해 코드를 간결하게 개선할 수도 있다. Spring Data JPA를 적용할 경우 데이터베이스와 관련된 코드의 많은 부분을 스프링에 넘길 수 있어 보다 간편하게 데이터베이스 관련 작업도 처리할 수 있다.
물론 JPA를 도입하는 것은 단순한 문제는 아니며 JPA 자체에 대한 충분한 이해를 전제로 한다.
뷰
뷰의 경우 JSP를 그대로 사용할 수 있다. EL과 JSTL 기반이라면 구조적으로도 나쁘지 않기 때문에 많은 경우 JSP를 뷰로 사용하고 있다. 다만 JSP의 커스텀 태그나 이를 이용한 JSTL, JSP 액션 태그 사용으로 인해 웹 페이지 자체의 독립적 개발이나 테스트 등이 어려워지는 문제가 존재한다. 또한 최근에는 서버 사이드 렌더링이 아닌 클라이언트 렌더링 중심의 프론트엔드 기반 개발도 확대되고 있으며, REST 기반 개발이 보편화되면서 JSP의 사용이 예전만큼 필수적인 요소가 되지 못하고 있다.
스프링 프레임워크의 경우 자바 기반 프레임워크이지만 JSP에 대한 종속은 없으며 타임리프(Thymeleaf), JSP, 프리마커(FreeMarker) 등 다양한 템플릿 엔진과의 연동을 지원하고 있다. JSP 사용은 별도의 설정이 필요하지만 타임리프의 경우 'pom.xml'에 추가만 하면 바로 사용할 수 있다.
JSP와 타임리프 선택
어떤 뷰 템플릿 엔진을 사용할지는 개발 정책에 따라 결정될 사항이다. 그럼에도 스프링 부트 기반의 프로젝트를 진행한다면 JSP 사용은 신중하게 고려해야 한다. 스프링 부트의 장점은 jar 패키지를 이용해 서버와 웹 애플리케이션을 한 번에 실행할 수 있다는 것인데, jar 패키지를 사용하면 스프링 부트에서 JSP를 사용할 수 없기 때문이다. 따라서 JSP를 사용하려면 war 패키지를 사용해야한다. 스프링 부트의 장점을 최대한 살리기 위해서는 jar 패키지가 적합하며, 커스텀 태그 기반보다는 HTML 속성 기반으로 동작하는 타임리프가 스프링 개발에 더 효율적이므로 참고한다.
컨트롤러 구현하기
클래서 생성 후 선언부 위에 다음과 같이 어너테이션을 추가한다.
@Controller
@RequestMapping("/web")
public class DemoWebController {
}
- @Controller: MVC 컨트롤러로 동작할 클래스를 의미한다.
- @RequestMapping: 서블릿의 @WebServlet의 request mapping 속성과 같다.
이후 요청 메서드와 URL에 따라 동작할 메서드를 구현하면 된다. 예를 들어 GET/web/hello 요청에 동작하는 메서드는 다음과 같다.
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("msg", "Hello World");
return "hello";
}
- hello() 메서드의 인자인 Model 객체는 뷰에 전달되는 객체로 컨트롤로에서 뷰로 전달할 값이 있다면 model.addAttribute()로 전달한다. JSP에서 request.setAttribute()와 같은 개념이다.
- return 타입은 String이고, 값은 단순한 문자열이 아니라 뷰의 이름이 들어간다. 즉 JSP, 타임리프 파일의 이름을 확장자 없이 이름만 사용한다.
- 여기서는 hello.jsp(혹은 HTML)를 호출하게 되고 실제 파일의 위치는 스프링 설정에 따른다.
기본적으로 JAX-RS와 유사한 구조로 볼 수 있으며, 서블릿과 달리 하나의 컨트롤러 클래스에서 여러 메서드와 요청을 다양하게 처리할 수 있다는 차이가 있다.
모델 구현하기
모델 영역은 기존 코드를 완전히 재사용할 수 있다. 컨트롤러의 요청 처리 메서드에서 DAO 객체를 불러와 필요한 메서드를 호출한다. DAO 자체도 기존의 JDBC 코드 구조를 사용할 수 있으며, 스프링의 JDBCTemplate 또는 JPA를 사용하여 개선할 수도 있다. DO(Entity) 클래스의 경우 거의 재사용이 가능하며, JPA를 도입할 경우 몇몇 어너테이션을 추가로 사용해야 한다.
다음은 컨트롤러에서 dao를 사용하는 예다.
@Autowired
ProductDAO dao;
@GetMapping("/productlist")
public String getProducts(Model model) {
model.addAttribute("products", dao.getDatas());
return "product_list";
}
@PostMapping("/productadd")
public String addProduct(Product p) {
dao.addProduct(p);
return "redirec:/web/productlist";
}
- @Autowired로 스프링 컨테이너로부터 ProductDAO 객체를 전달받아 요청 메서드에서 사용하게 된다. getProducts()에서는 dao.getDatas() 메서드로 데이터를 받아 model 객체에 넣은 후 뷰 페이지를 리턴한다.
- addProduct()에서는 인자로 받은 Product 객체를 dao.addProduct()로 저장한 뒤 목록 페이지로 이동하고 있다.
DAO 자체는 기존 코드를 그대로 사용해도 되지만 스프링 JDBCTemplate을 사용하는 경우 다음과 같이 코드가 간략화될 수 있다.
public void addProduct(Product p) {
String SQL = "insert into product(name, price) values(?, ?)";
jdbcTemplateObject.update(SQL, p.name, p.price);
}
뷰 구현하기
뷰의 경우 JSP를 사용한다면 기존과 동일하게 EL, JSTL로 구성된 페이지를 만들면 된다. 만일 타임리프를 사용한다면 다음과 같이 작성할 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Hello Spring Boot Project</h2>
<hr>
MSG: <span data-th-text="${msg}">hello</span>
</body>
</html>
JSP와 달리 page 지시어와 JSTL과 같은 태그 라이브러리 요소가 없는 것을 볼 수 있다. EL은 동일하게 사용할 수 있으며 태그 사이에 JSTL 대신 data-th-xxx 형식으로 로직이나 반복 처리 등을 구현할 수 있다.
서버를 거쳐야만 완전하게 화면에 보이는 부분은 JSP와 다르지 않지만 기본 구조 자체가 표준 HTML 형식이므로 화면 디자인 과정에서 별도의 서버 실행 없이 페이지를 디자인할 수 있다는 장점이 있다.
RestController
스프링에서 REST API 구현을 위해 사용하는 모듈이다. 스프링에서는 JAX-RS를 사용할 수도 있고, 스프링의 RestController를 사용할 수도 있는데 RestController가 좀 더 편하고 간결하다. 기본적인 REST API 개발 구조나 원리는 동일하며 사용하는 어너테이션 등에서만 차이가 있다.
RestController는 메서드에 따를 요청을 구분하고, 요청 또는 경로 파라미터에 따라 파라미터를 제공받을 수 있다. 또한 JSON 규격으로 전달되는 데이터를 자바 객체로 매핑할 수도 있으며 리턴 타입으로 사용하면 자동으로 JSON으로 변환되는 점도 JAX-RS와 동일하다.
@RestController
@RequestMapping("/api")
public class DemoRestController {
@GetMapping("/hello")
public String hello(@RequestParam(value="msg", required=false) String msg) {
return msg;
}
@GetMapping("/hello/{msg}")
public String hello2(@PathVariable String msg) {
return msg;
}
}
- @RestController로 REST API를 위한 컨트롤러 클래스라는 것을 스프링 컨테이너에 전달한다.
- @RequestMapping은 API 호출의 시작점이다.
- hello() 메서드는 /api/hello?msg=Welcome 형식으로 요청이 이루어지고, hello2() 메서드는 /api/hello/Welcome 형식의 요청이 동작한다.
'Programming > Web' 카테고리의 다른 글
[Web] Spring Bean 선언, 오토와이어링(Autowired) (0) | 2022.11.03 |
---|---|
[Web] JSTL(다운로드, 사용법, 정리), EL(정리) (1) | 2022.11.03 |
[Web] IoC(Inversion of Control), DI(Dependency Injection), AOP(Aspect-Oriented Programming) (1) | 2022.10.31 |
[Web] 스프링 프레임워크와 스프링 부트 (0) | 2022.10.27 |
[Web] REST 클라이언트 (0) | 2022.10.27 |