[토이 투표] 22.07.04 일지

재호·2022년 7월 4일
0

Board 테이블 수정

이 투표글이 마감됐는지 아닌지 정보를 담고 있는 속성을 추가했다. 속성명은 dead(boolean).

메인 페이지

스타트 부트 스트랩 템플릿을 이용해서 메인 페이지를 만들었다.
스타트 부트스트랩

메인 내용의 3가지 컨텐츠들은 가장 투표량이 많은 즉, 인기 탑 쓰리 투표들에 대한 정보들을 보여주도록 했다.

	@Query(value="select b.*, "
			+ "sum(i.count) c from board as b left join voteitem as i "
			+ "on b.bno=i.board_num "
			+ "group by i.board_num order by c desc limit 3", nativeQuery = true)
	List<Board> findTop3();
    
    
    
	@Override //인기 글 조회
	public List<BoardDTO> mostPopluar() {
		List<Board> list = boardRepository.findTop3();
		List<BoardDTO> result = new ArrayList<>();
		
		for(Board board : list) {
			result.add(entityToDto(board, 2));
		}
		
		return result;
	}

투표 항목 테이블에서 count 속성을 그룹으로 나눠 총 합을 구한뒤 내림차순으로 정렬해 상단 3개만 보이도록 쿼리를 짜야하는데 JPQL로는 짜기가 힘들어 보여서 native queury로 만들었다.

@Controller
@Log4j2
@RequiredArgsConstructor
public class MainController {
	
	private final BoardService boardService;
	
	@RequestMapping("/")
	public String home(Model model) {
		log.info("mainpage 요청");
		List<BoardDTO> list = boardService.mostPopluar();
		model.addAttribute("list", list);
		return "index";
	}
}

컨트롤러에서는 쿼리 결과를 Model에 담아서 보내주기만 하면 된다.

MemberController

@Controller
@RequestMapping("/member")
@Log4j2
@RequiredArgsConstructor
public class MemberController {
	
	private final MemberService memberService;
	
	private boolean loginStat(HttpSession session) {
		Object loginSession = session.getAttribute("userLogin");
		if(loginSession != null && loginSession.toString().equals("login")) return true;
		return false;
	}
	
	//회원가입 폼 요청
	@GetMapping("/signup")
	public void signup() {
		log.info("singup form 요청");
	}
	
	//회원가입 처리
	@PostMapping("/signup")
	public String signupPro(MemberDTO dto) {
		log.info(dto);
		String email = memberService.insertMember(dto);
		if(email == null) {
			return null;
		}
		return "/main";
	}
	
	//로그인 화면 요청
	@GetMapping("/login")
	public String login(HttpSession session) {
		log.info("login 화면 요청");
		if(loginStat(session)) return "redirect:/main";
		return "/member/login";
	}
	
	//로그인 처리
	@PostMapping("/login")
	public String loginPro(MemberDTO dto, HttpSession session, Model model) {
		int result = memberService.memberLogin(dto);
		if(result == 1) { //로그인 성공 시
			session.setAttribute("userLogin", "login");
			session.setAttribute("userId", dto.getEmail());
			return "/main";
		}
		model.addAttribute("loginCheck", 0);
		return "/member/login";
	}
	
	//마이 페이지 요청
	@GetMapping("/mypage")
	public void mypage(MemberDTO dto, HttpSession session, Model model) {
		log.info("mypage 요청");
		if(loginStat(session)) {
			MemberDTO findMember = memberService.getMember(dto);
			if(findMember == null) {
				return;
			}
			model.addAttribute("memberDTO", dto);
		}
	}
	
	//회원 정보 수정 폼 요청
	@GetMapping("/modify")
	public void modify(MemberDTO dto, HttpSession session, Model model) {
		log.info("회원정보 수정 폼 요청");
		if(loginStat(session)) {
			model.addAttribute("memberDTO", dto);
		}
	}
	
	//회원 정보 수정 처리
	@Transactional
	@PutMapping("/modify")
	public void modifyPro(MemberDTO dto) {
		log.info("회원정보 수정 처리");
		memberService.updateMember(dto);
		//return "/member/mypage";
	}
	
	//회원 탈퇴 처리
	@Transactional
	@DeleteMapping("/modify")
	public String deletePro(MemberDTO dto, HttpSession session) {
		session.removeAttribute("userLogin");
		session.removeAttribute("userId");
		
		memberService.deleteMember(dto);
		return "/main";
	}
}

스프링 시큐리티는 사용하지 않았기에 사용자의 로그인 여부를 확인하는 loginStat()함수를 하나 만들었다. 단순히 세션에 로그인 정보가 있는 판단하는 함수이다. 마이페이지 같은 주소처럼 로그인 여부가 필요한 주소 요청시에 사용한다.

BoardController

@Controller
@RequestMapping("board")
@RequiredArgsConstructor
@Log4j2
public class BoardController {

	public final BoardService boardService;
	public final ItemService itemService;
	
	private boolean loginStat(HttpSession session) {
		Object loginSession = session.getAttribute("userLogin");
		if(loginSession != null && loginSession.toString().equals("login")) return true;
		return false;
	}
	
	@GetMapping("/register")
	public void boardRegister(HttpSession session, Model model) {
		log.info("게시글 등록 폼 요청");
		if(loginStat(session)) {
			String email = (String)session.getAttribute("userId");
			model.addAttribute("email", email);
		}
		return;
	}
	
	@PostMapping("/register")
	public String boardRegister(BoardDTO boardDTO, HttpServletRequest request) {
		log.info(boardDTO);
		
		String[] items = request.getParameterValues("item");
		
		List<VoteItemDTO> list = new ArrayList<>();
		for(String item : items) {
			VoteItemDTO dto = VoteItemDTO.builder().item(item).build();
			list.add(dto);
		}
		
		boardService.registerBoard(boardDTO, list);
		return "/board/list";
	}
	
	@GetMapping("/list")
	public String boardPage(@RequestParam(required = false) PageRequestBoardDTO dto, Model model) {
		log.info(dto);
		if(dto == null) {
			dto = new PageRequestBoardDTO();
		}
		
		PageResponseBoardDTO response = boardService.getList(dto);
		model.addAttribute("list", response.getBoardList());
		return "board/list";
	}
	
	@GetMapping("/vote")
	public void vote(BoardDTO dto, Model model) {
		log.info("투표글 상세 조회");
		BoardDTO result = boardService.getBoard(dto);
		model.addAttribute("result", result);
	}
	
	@GetMapping("/modify")
	public void modify(BoardDTO boardDTO, Model model) {
		List<Long> inoList = new ArrayList<>();
		for(VoteItemDTO itemDTO : boardDTO.getVoteItem()) {
			inoList.add(itemDTO.getIno());
		}
		int canMod = itemService.canModify(inoList);
		model.addAttribute("canMod", canMod);
		model.addAttribute("boardDTO", boardDTO);
	}
	
	@Transactional
	@PutMapping("/modify")
	public String modifyPro(BoardDTO boardDTO, HttpServletRequest request) {
		String[] inos = request.getParameterValues("ino");
		String[] items = request.getParameterValues("item");
		
		List<VoteItemDTO> itemList = new ArrayList<>();
		
		for(int i=0; i<items.length; i++) {
			try {
				VoteItemDTO itemDTO = VoteItemDTO.builder().ino(Long.parseLong(inos[i]))
														.item(items[i])
														.board_num(boardDTO.getBno()).build();
				itemList.add(itemDTO);
			} catch (ArrayIndexOutOfBoundsException e) {
				log.info("new item add");
				VoteItemDTO itemDTO = VoteItemDTO.builder()
										.item(items[i])
										.board_num(boardDTO.getBno()).build();
				itemList.add(itemDTO);
			}
		}
		itemService.itemUpdate(itemList);
		boardService.updateBoard(boardDTO);
		return "/board/list";
	}
	
	@Transactional
	@DeleteMapping("/modify")
	public String deletePro(BoardDTO boardDTO) {
		boardService.deleteBoard(boardDTO);
		return "/board/list";
	}
}

투표 글에는 단순히 글에 대한 데이터(제목, 설명 등)와 투표 내용에 대한 데이터(투표 항목, 득표수)가 동시에 사용되고 하나의 글에 여러개의 투표 항목이 들어가는 1:N 관계이다. 그로 인해 글에 대한 데이터는 BoardDTO를 파라미터로 써서 쉽게 body message를 받을 수 있지만 투표 항목은 List로 받아야 하기 때문에 HttpServletRequestgetParameterValues로 받아오는 작업이 필요했다.

타임리프

View 부분은 스프링 부트를 이용해서 타임리프를 사용하기로 했다. 타임리프 사용을 위해서는 먼저 설정이 필요하다.
build.gradle에 아래의 의존성을 주입한다.

implementation group: 'org.thymeleaf', name: 'thymeleaf'

application.properties에 타임리프 상세 설정을 한다.

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

타임리프 파일의 위치는 아래 사진처럼 src/main/resources 의 templates 디렉토리이다.

Git

https://github.com/JINJAEHO/vote
기존 레포지토리가 말썽이라 새로운 곳으로 옮김

profile
Java, Spring, SpringMVC, JPA, MyBatis

0개의 댓글