Helmi

프레젠테이션(웹)계층 CRUD 구현 -①Controller 작성 본문

SpringBoot

프레젠테이션(웹)계층 CRUD 구현 -①Controller 작성

Helmi 2023. 5. 4. 17:21

비즈니스 계층 구현까지 모든 테스트 진행되었다면 이제 남은 작업은 프레젠테이션 계층인 웹의 구현

 

1. Controller 작성

스프링 MVC의 Controller는 하나의 클래스 내에서 여러 메서드 작성하고, @RequestMappoing 등 이용해 URL을 분기하는 구조로 작성 가능하므로 하나의 클래스에서 필요한 만큼 메서드 분기 이용하는 구조로 작성

 

BoardController의 분석

작성 전 반드시 현재 원하는 기능 호출하는 방식에 대해 정리한 후 코드 작성하는 것이 좋음

Task URL Method Parameter Form URL 이동
전체 목록 /board/list GET      
등록 처리 /board/register POST 모든 항목 입력화면 필요 이동
조회 /board/get GET bno = 123    
삭제 처리 /board/remove POST bno 입력화면 필요 이동
수정 처리 /board/modify POST 모든 항목 입력화면 필요 이동

테이블에서 Form 항목은 해당 URL 호출 위해 별도 입력화면 필요함을 의미. 화면 구성 단계에서 진행 가능


2. BoardController 작성

package com.board.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
public class BoardController {

}

BoardController는 @Controller 어노테이션 추가해 스프링의 빈으로 인식할 수 있도록 하고,

@RequestMapping 통해 '/board/'로 시작하는 모든 처리를 BoardController가 하도록 지정

 

BoardController가 속한 com.board.controller 패키지는 servlet-context.xml에 기본으로 설정되어 있으므로 별도의 설정 필요하지 않음. (java 설정 이용 시 @ComponentScan 이용)

 

목록에 대한 처리와 테스트

BoardController에서 전체 목록 가져오는 처리 먼저 작성

BoardController는 BoardService 타입의 객체와 같이 연동해야 하므로 의존성에 대한 처리도 같이 진행

 

com.board.controller.BoardController.java

package com.board.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.board.service.BoardService;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {

	private BoardService service;
	
	@GetMapping("/list")
	public void list(Model model) {
		
		log.info("list");
		model.addAttribute("list",service.getList());
	}
}

BoardController는 BoardService에 대해서 의존적이므로 @AllArgsConstructor를 이용해 생성자 만들고 자동으로 주입되도록 함. (만일 생성자 만들지 않을 경우 @Setter(onMethod_={@Autowired}) 이용해 처리)

 

list()는 나중에 게시물의 목록 전달해야 하므로 Model을 파라미터로 지정하고, 이를 통해 BoardServiceImol 객체의 getList() 결과를 담아 전달. (addAttribute)

BoardController 테스트는 스프링 테스트 기능을 통해 확인 가능

 

src/test/java에 com.board.controller 패키지에 BoardControllerTests 클래스 선언

테스트 코드는 기존과 좀 다르게 진행. 이유는 웹 개발할 때 매번 URL을 테스트 하기 위해선 Tomcat과 같은 WAS 실행하는 불편한 단계 생략 위해. 스프링의 테스트 기능 활용하면 개발 당시에 Tomcat(WAS)을 실행하지 않고도 스프링과 웹 URL 테스트 가능

 

WAS 실행하지 않기 위해선 약간의 추가적 코드 필요하나 반복적으로 서버 실행하고 화면에 입력하고, 오류 수정하는 단계 줄여줄 수 있으므로 Controller를 테스트 할 땐 한 번쯤 고려해 볼 만한 방식.

 

src/test/java 밑 com.board.controller.BoardControllerTests.java

package com.board.controller;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)

//Test for Controller
@WebAppConfiguration

@ContextConfiguration({
	"file:src/main/webapp/WEB-INF/spring/root-context.xml",
	"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})

//Java Config
//@ContextConfiguration(classes = {
//		com.board.config.RootConfig.class.
//		com.board.config.ServletConfig.class})

@Log4j
public class BoardControllerTests {

	@Setter(onMethod_={@Autowired})
	private WebApplicationContext ctx;
	
	private MockMvc mockMvc;
	
	@Before
	public void setup() {
		this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
	}
	
	@Test
	public void testList() throws Exception {
		log.info(
				mockMvc.perform(MockMvcRequestBuilders.get("/board/list"))
						.andReturn()
						.getModelAndView()
						.getModelMap());		
	}	
}

테스트 클래스 선언부에는 @WebAppConfiguration 어노테이션 적용

@WebAppConfigurationServlet의 ServletContext 이용하기 위해서, 스프링에서는 WebApplicationContext 존재 이용하기 위해서.

@Before 어노테이션 적용된 setUp()에서는 JUnit 이용해야 함.

@Before가 적용된 메서드는 모든 테스트 전에 매번 실행되는 메서드가 됨

 

MockMvc는 말 그대로 '가짜 mvc'. 가짜로 URL과 파라미터 등을 브라우저에서 사용하는 것처럼 만들어 Controller 실행 해볼 수 있음.

testList()는 MockMvcRequestBuilders 라는 존재 이용해 GET 방식 호출. 이후 BoardController의 getList()에서 반환된 결과 이용해 Model에 어떤 데이터 담겨있는지 확인. Tomcat 통해 실행되는 방식 아니므로 기존 테스트 코드 실행하는 것과 동일히 실행