항해99/개발일지

20220124 개발일지 #게시판 만들기(멀티페이지)

paran21 2022. 1. 25. 00:36

오늘은 이번주 개인과제인 게시판만들기를 다시 시작했다.

지난주 토요일에 개인 과제를 진행하면서 단일페이지(index.html)를 구현하지 못해서, 멀티 페이지로 구현하였다.

기본적으로 https://gonyda.tistory.com/3?category=803529 을 참고했다.

 

github: https://github.com/paran22/springprac

 

1. 개발환경 구축

  • IntelliJ
  • Java 8
  • Gradle
  • MySQL

2. 라이브러리

  •  JPA
  • Thymeleaf
  • Lombok
  • DevTools

3. 설정

  • application.properties
    spring.datasource.url=엔드포인트:3306/myboard
    spring.datasource.username=
    spring.datasource.password=
    spring.jpa.hibernate.ddl-auto=update
    spring.mvc.hiddenmethod.filter.enabled=true​

4. 기본 구조

5. 기능 구현

Controller

  • thymeleaf를 사용
  • 모든 return은 페이지 호출이거나, service를 통해 기능 구현 후 "redirect:/"
  • Model을 사용해서 필요한 값을 html로 전달
  • 모든 기능은 entity가 아니라 dto를 통함
@Controller
@AllArgsConstructor
public class BoardController {
    private BoardService boardService;


    //기본페이지 : board/list 페이지를 호출
    //전체 게시글 목록보기
    @GetMapping("/")
    public String list(Model model) {
        List<BoardDto> boardList = boardService.getBoardlist();
        model.addAttribute("boardList", boardList);
        return "board/list";
    }

    //게시글 작성 페이지 호출
    @GetMapping("/post")
    public String write() {
        return "board/write";
    }

    //게시글 등록하기
    @PostMapping("/post")
    public String write(BoardDto boardDto) {
        boardService.savePost(boardDto);
        return "redirect:/";
    }

    //게시글 상세보기
    @GetMapping("/post/{id}")
    public String detail(@PathVariable("id") Long id, Model model) {
        BoardDto boardDto = boardService.getBoard(id);
        model.addAttribute("boardDto", boardDto);
        return "board/detail";
    }

    //게시글 수정하기 페이지 호출
    @GetMapping("/post/edit/{id}")
    public String edit(@PathVariable("id") Long id, Model model) {
        BoardDto boardDto = boardService.getBoard(id);
        model.addAttribute("boardDto", boardDto);
        return "board/update";
    }

    //게시글 수정하기
    @PutMapping("/post/edit/{id}")
    public String update(BoardDto boardDto) {
        boardService.savePost(boardDto);
        return "redirect:/";
    }

    //게시글 삭제하기
    @DeleteMapping("/post/{id}")
    public String delete(@PathVariable("id") Long id) {
        boardService.deletePost(id);
        return "redirect:/";
    }
}

Entity

  • 처음에는 Setter와 생성자로 코드를 짜려고 했는데, 수정하기를 service에서 제대로 구현하지 못해서 참고한 블로그의 코드를 참고해서 builder로 구현했다.
  • TimeEntity를 상속한다.
@NoArgsConstructor
@Getter
@Entity
public class BoardEntity extends TimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(length = 10, nullable = false)
    private String writer;

    @Column(length = 100, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;
    
    @Builder
    public BoardEntity(Long id, String title, String content, String writer) {
        this.id = id;
        this.writer = writer;
        this.title = title;
        this.content = content;
    }

}

TimeEntity

  • 작성시간과 수정시간을 위한 Entity
@Getter
@MappedSuperclass //entity가 자동으로 칼럼으로 인식
@EntityListeners({AuditingEntityListener.class}) //자동업데이트
public class TimeEntity {
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

Application

  • TimeEntity를 사용하기 위해서는 @EnableJpaAuditing 어노테이션을 반드시 표시해야 한다.
@EnableJpaAuditing
@SpringBootApplication
public class BoardApplication {

    public static void main(String[] args) {
        SpringApplication.run(BoardApplication.class, args);
    }

}

Repository

  • JpaRepository를 상속하여 repository에서 Jpa를 사용할 수 있다.
  • 작성시간 최신순으로 정렬하기 위해 메소드 작성
public interface BoardRepository extends JpaRepository<BoardEntity, Long> {

    //최신순으로 정렬
    List<BoardEntity> findAllByOrderByCreatedDateDesc();
}

Dto

  • toEntity 메소드와 builder를 사용하여 Dto를 통해 entity를 만듦.
@Getter
@Setter
@ToString
@NoArgsConstructor
public class BoardDto {
    private Long id;
    private String writer;
    private String title;
    private String content;
    private LocalDateTime createdDate;
    private LocalDateTime modifiedDate;


    public BoardEntity toEntity(){
        BoardEntity boardEntity = BoardEntity.builder()
                .id(id)
                .writer(writer)
                .title(title)
                .content(content)
                .build();
        return boardEntity;
    }

    @Builder
    public BoardDto(Long id, String title, String content, String writer, LocalDateTime createdDate, LocalDateTime modifiedDate) {
        this.id = id;
        this.writer = writer;
        this.title = title;
        this.content = content;
        this.createdDate = createdDate;
        this.modifiedDate = modifiedDate;
    }
}

Service

  • 게시글 저장하기와 수정하기는 같은 메소드를 사용한다.
  • 게시글 목록보기와 상세보기는 repository를 사용하여 Entity를 불러오고 builder를 사용해서 Dto로 전달한다.
@AllArgsConstructor
@Service
public class BoardService {
    private BoardRepository boardRepository;


    //게시글 저장하기
    //게시글 수정하기
    @Transactional
    public Long savePost(BoardDto boardDto) {
        return boardRepository.save(boardDto.toEntity()).getId();
    }

    //게시글 목록보기
    @Transactional
    public List<BoardDto> getBoardlist() {
        List<BoardEntity> boardEntityList = boardRepository.findAllByOrderByCreatedDateDesc();
        List<BoardDto> boardDtoList = new ArrayList<>();
        for (BoardEntity boardEntity : boardEntityList) {
            BoardDto boardDto = BoardDto.builder()
                    .id(boardEntity.getId())
                    .title(boardEntity.getTitle())
                    .content(boardEntity.getContent())
                    .writer(boardEntity.getWriter())
                    .createdDate(boardEntity.getCreatedDate())
                    .build();

            boardDtoList.add(boardDto);
        }
        return boardDtoList;
    }

    //게시글 보기
    @Transactional
    public BoardDto getBoard(Long id) {
        //repository를 이용해서 id가 일치하는 것 찾기
        Optional<BoardEntity> boardEntityWrapper = boardRepository.findById(id);
        //optional 타입 객체에서 엔티티 가져오기
        BoardEntity boardEntity = boardEntityWrapper.get();

        BoardDto boardDto = BoardDto.builder()
                .id(boardEntity.getId())
                .title(boardEntity.getTitle())
                .content(boardEntity.getContent())
                .writer(boardEntity.getWriter())
                .createdDate(boardEntity.getCreatedDate())
                .build();

        return boardDto;
    }

    //게시글 삭제하기
    @Transactional
    public void deletePost(Long id) {
        boardRepository.deleteById(id);
    }

 

처음에는 단일 페이지 구현을 못해서, Thymeleaf를 사용하여 멀티 페이지를 구현했다.

Thymeleaf 설정 부분이 햇갈려서 좀 헤맸는데, defendency에 추가하고 나면 특별히 설정할 부분은 없다.

controller에서는 전달 방법과 return값만 구조를 그려주고 기능 자체는 Service에서 구현하는 느낌이었다.

controller에서 model로 필요한 데이터를 List 객체로 보내주고 HTML에서 Thymeleaf 문법을 사용하여 받는다.

또한, HTML에는 없는 Put과 Delete API를 사용하기 위해 HTML에서 hidden을 사용할 수 있다.

 

여기서는 사용하지 않았지만, 데이터만 받아 페이지를 변경하기 위해 ajax를 Thymeleaf와 함께 사용할 수 있다.

 

 


개인 과제 진행하면서 이해가 안되는 부분이 많았고, JAVA 문법으로 표현하기 어려운 부분도 있었다.

그래도 큰 틀은 마무리 하면서 controll-service-entity/dto/repository를 연결하는 부분이 조금 이해가 된 것 같다.

 

너무 이해가 안가는 부분에서 시간을 끌기 보다는 우선 강의 진도를 빨리 빼면서 일단 많이 써보고 해보는 게 중요할 것 같다.

내일 배포 부분 마무리하고, 그룹 과제하면서 spring 강의 진행하면 될 것 같다.

'항해99 > 개발일지' 카테고리의 다른 글

20220126 개발일지 #게시판 만들기(원페이지)  (0) 2022.01.26
20220125 개발일지 #서버시간 변경하기  (0) 2022.01.25
20220122 개발일지  (0) 2022.01.23
20220121 개발일지  (0) 2022.01.21
20220120 개발일지(WIL)  (1) 2022.01.21