본문 바로가기
Spring/게시판프로젝트

[Spring] 게시판 프로젝트6 - Presentation계층 구현

by 태옹 2021. 7. 4.

Presentation계층에서 Controller를 작성하기 전에 url설계부터 진행함

 


리스트 조회(List) 처리 과정

 

1. BoardController.java 생성

이 위치에다가 추가하기

package com.taeong.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.taeong.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) {	//addAttribute메소드를 이용해 Model객체에 담아서 전달
		log.info("[CONTROLLER]get list...");
		model.addAttribute("list",service.getList());	//Model에 BoardVO의 목록을 담아서 전달
	}
}

@Controller : 스프링의 빈으로 등록

영속계층, 서비스계층과 다르게 따로 root-context.xml에 알려주는 작업을 하지 않는 이유 - 이미 되어있으니까..! (BoardController가 속한 org.zerock.controller패키지는 servlet-context.xml에 기본으로 설정되어 있음)

@Log4j : log를 기록함
@RequestMapping("/board/*") :  /board/~로 시작하는 url의 경우 해당

@AllArgsConstructor : BoardService의 생성자를 만들고 자동으로 주입

 

2. 테스트

BoardContollerTests.java 생성

이 위치에다가 추가하기

 

(1) import, 의존성 주입, MockMvc객체 생성, testList() 메소드 생성

package com.taeong.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)

@WebAppConfiguration
@ContextConfiguration({ "file:src/main/webapp/WEB-INF/spring/root-context.xml",
		"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" })
@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("[CONTROLLER]testList : "+mockMvc.perform(MockMvcRequestBuilders.get("/board/list"))	//[CONTROLLER]testList :org.springframework.test.web.servlet.MockMvc$1@3aa41da1
				.andReturn()	//[CONTROLLER]testList : org.springframework.test.web.servlet.DefaultMvcResult@3c3c4a71
				.getModelAndView()	//[CONTROLLER]testList : ModelAndView [view="board/list"; model={list=[BoardVO(bno=1, title=테스트제목, content=테스트내용, writer=user00, regdate=Fri Jul 02 15:01:38 KST 2021, updateDate=Fri Jul 02 15:01:38 KST 2021), BoardVO(bno=2,  ...)]}]
				.getModelMap());	//[CONTROLLER]testList : {list=[BoardVO(bno=1, title=테스트제목, content=테스트내용, writer=user00, regdate=Fri Jul 02 15:01:38 KST 2021, updateDate=Fri Jul 02 15:01:38 KST 2021), BoardVO(bno=2, ...)]}
	}
}
  • @WebAppConfiguration : WebApplicationContext를 이용하기 위함
  • @Before : 모든 테스트 전에 매번 실행되는 메소드 (JUnit이용)
  • MockMvc = 가짜 mvc (스프링에서는 단위테스트가 중요하기 때문에 만들어진 존재임) 
    • 가짜로 URL과 파라미터 등을 브라우저에서 사용하는 것처럼 만들어서 Controller를 실행해 볼 수 있음
    • MockMvcRequestBuilders를 이용해서 GET방식의 호출을 함 - /board/list인 경우를 테스트해볼 수 있음
    • andReturn : 테스트한 결과 객체를 받을 때 사용
    • 각 단계별 메소드의 결과는 옆에 주석으로 확인해보고 차이 이해하기

MockMvc에 대해서는 아래의 포스팅에서 더 자세하게 다루고 있으니 참고!

https://jdm.kr/blog/165

 

Spring MockMvc(spring-test) :: JDM's Blog

스프링 프레임워크에서 단위 테스트의 중요성은 다들 아실거라 생각합니다. :D 이번 포스팅에서는 Spring 3.2부터 사용 가능한 MockMvc를 활용한 단위 테스트에 대해 알아보고자 합니다. 또한 Springboo

jdm.kr

junit테스트를 진행해보면 콘솔창에서 리스트가 출력되는 것을 확인할 수 있음

 

 


게시물 등록(Register) 처리 과정

 

1. BoardController.java에 register()을 작성

@PostMapping("/register")	//글을 등록하는 경우에는 get방식이 아니라 post방식을 사용한다.
public String register(BoardVO board,RedirectAttributes rttr) {	//RedirectAttributes : 
    log.info("[CONTROLLER]register : "+board);
    service.register(board);
    rttr.addFlashAttribute("result",board.getBno());
    return "redirect:/board/list";
}
  • @PostMapping : POST방식으로 처리
  • BoardVO타입의 인스턴스(board)로 바인딩해서 메소드에서 활용함
  • 새로운 게시물의 번호를 전달하기 위해 RedirectAttributes파라미터를 이용함
  • return "redirect:/board/list" : redirect:를 이용해서 다시 목록으로 이동

 

RedirectAttributes에 대한 설명은 아래의 포스팅에서 자세하게 확인해볼 것! 특히 연습문제 부분

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=allkanet72&logNo=220964699929 

 

[스프링] RedirectAttributes

RedirectAttributes 폼 형식의 문서를 작성 후, 서버로 보내면(POST 방식) 곧이어 다른 페이지로 리...

blog.naver.com

 

2. BoardControllerTests.java에 testRegister() 작성 후 테스트 진행

@Test
public void testRegister() throws Exception {
    String resultPage = mockMvc
        .perform(MockMvcRequestBuilders.post("/board/register")
        .param("title", "테스트 새글 제목")
        .param("content", "테스트 새글 내용")
        .param("writer", "user00"))
        .andReturn().getModelAndView().getViewName();
    log.info("결과페이지 경로 : "+resultPage);
}
  • 이번에는 POST방식으로 데이터를 전달해야 하므로 post()를 이용함(MockMvcRequestBuilder)
  • param()을 이용해서 전달해야 하는 파라미터들을 지정할 수 있음

 


게시물 조회(Get) 처리 과정

1. BoardController,java에 get() 작성

@GetMapping("/get")
public void get(@RequestParam("bno") Long bno, Model model) {
    log.info("[ CONTROLLER ] get ……..");
    model.addAttribute("board", service.get(bno));
}

특정 게시물을 조회하는 경우이기 때문에 bno값을 파라미터로 받아 이용함

 

 

2. BoardControllerTests.java에 testGet() 작성

@Test	
public void testGet() throws Exception {
    log.info("get테스트를 진행합니다..."+
        mockMvc.perform(MockMvcRequestBuilders.get("/board/get")
        .param("bno", "2"))
        .andReturn()
        .getModelAndView()
        .getModelMap());
}
  • 얘도 조회하는 경우니까 GET방식 이용
  • get()메소드의 파라미터에 필요한 bno값을 임의로 test코드에서 넣어줌


게시물 수정(Modify) 처리 과정

1. BoardController.java에 modify() 작성

@PostMapping("/modify")
public String modify(BoardVO board, RedirectAttributes rttr) {
    log.info("[ CONTROLLER ] modify:" + board);
    if (service.modify(board)) {
        rttr.addFlashAttribute("result", "success");
    }
    return "redirect:/board/list";
}
  • service.modify가 1을 반환하는 경우 result값으로 "success"메시지를 rttr에 담아줌(일회성)

 

2. BoardControllerTests.java에 testModify() 작성

@Test
public void testModify() throws Exception {
    String resultPage = mockMvc
        .perform(MockMvcRequestBuilders.post("/board/modify")
        .param("bno", "1")
        .param("title", "수정된 테스트 새글 제목")
        .param("content", "수정된 테스트 새글 내용")
        .param("writer", "user00"))
        .andReturn().getModelAndView().getViewName();
    log.info("결과페이지 경로 : "+resultPage);
}

 


게시물 삭제(Remove) 처리 과정

1. BoardController.java에 remove() 작성

@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
    log.info("[ CONTROLLER ] remove..." + bno);
    if (service.remove(bno)) {
        rttr.addFlashAttribute("result", "success");
    }
    return "redirect:/board/list";
}

2. BoardControllerTests.java에 testRemove() 작성

@Test
public void testRemove() throws Exception {
    // 삭제전 데이터베이스에 게시물 번호 확인할 것
    String resultPage = mockMvc.perform(MockMvcRequestBuilders.post("/board/remove")
        .param("bno", "2"))
        .andReturn()
        .getModelAndView()
        .getViewName();
    log.info("결과페이지 경로 : "+resultPage);
}

 

여기까지 MVC에 대한 이해를 위해 간략히 테스트 코드로 스프링의 동작을 확인해보았다.

이 다음 포스팅부터는 jsp파일을 이용하여 프론트 부분도 함께 구현하는 내용을 다루도록 하겠다🙋‍♀️

댓글