본문 바로가기

Backend

[Spring Boot] 게시판 만들기(step1)

반응형

게시판 기능 

  • 글 작성하기
  • 전체 글 보기
  • 특정 글 클릭하기
  • 클릭한 글 수정, 삭제하기
    • 글 작성시 기입한 비밀번호와 일치해야한다.

  • controller : 웹 MVC에서 컨트롤러 역할 - url mapping 작업, view return, service와 연결 동작 작업
  • domain : 비지니스 도메인 객체 - 글 하나의 객체를 나타낸다. 게시글 정보 예를 들면, 제목,본문내용, 비밀번호, 날짜 등을 담을 수 있는 객체 역할을 수행한다.
  • service : 비지니스 로직에 필요한 함수들을 정의 - 글 작성, 수정, 삭제 등 작업 수행
    • * DB와 연결은 수행하지 않았지만, 추후 mysql과 연결시 동작할 수 있도록 현재는 map 자료구조에 저장하는 방식으로 구현

 

  • https://start.spring.io/  애플리케이션 패키지를 제작해주는 툴 이용
  • 사용 라이브러리 : Spring Web, Lombok, Thymeleaf, H2 Database(메모리 기반 데이터베이스 : DB동작 테스트 용도), Spring Data JPA(추후 사용예정)

  • 게시글 정보를 담게 될 객체
package project.NoticeBoard.domain;


import lombok.Data;

@Data
public class Content { // 게시글

    private int id; //user id
    private String title; //게시글 제목
    private String texts; //게시글 본문 내용
    private String writer; //게시자
    private String password; //게시글 비밀번호
    private String updateDate; //게시 날짜

}

 

  • controller 코드 : url 매핑하여 서비스 로직을 마친 이후 view로 리턴하게 동작
package project.NoticeBoard.controller;


import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import project.NoticeBoard.domain.Content;
import project.NoticeBoard.service.ContentService;

@Controller
@RequiredArgsConstructor
public class ContentController {
    private final ContentService contentService;

    @GetMapping(value = {"", "/"}) // 두 개정도로 다중매핑해보기
    public String home(Model model){
        model.addAttribute("contents", contentService.getAllContents());
        return "home";
    }

    @GetMapping("/content/write")
    public String writePage(){
        return "write-page";
    }

    @PostMapping("/content/write")
    public String writeContent(Content content){
        contentService.writeContent(content);
        return "redirect:/";
    }

    @GetMapping("/content/{id}")
    public String showContent(@PathVariable int id, Model model){
        model.addAttribute("content",contentService.getContent(id));
        return "content-page";
    }

    @PostMapping("/content/{id}")
    public String editContent(@PathVariable int id, Content content){
        contentService.editContent(id,content.getTexts(),content.getPassword());
        return "redirect:/";
    }

    @PostMapping("/content/delete/{id}")
    public String deleteContent(@PathVariable int id, Content content){
        contentService.deleteContent(id,content.getPassword());
        return "redirect:/";
    }

}
  • repository 코드 :  collection 중 map 자료구조를 활용하여 db 역할과 유사하게 동작하도록 구현
package project.NoticeBoard.repository;


import org.springframework.stereotype.Repository;
import project.NoticeBoard.domain.Content;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//step 1에서는 db 연결보단 컬렉션 중 map 자료구조를 활용해 메모리 영역 단에서 데이터를 저장하는 정도로만 할 예정
@Repository
public class ContentRepository {
    private static Map<Integer, Content> contents = new HashMap<>();

    /**
     * 저장,수정,삭제,조회 기능을 모두 map 자료구조 대상으로 진행 예정 (CRUD 기능 구현)
     */
    private static int sequence = 0;

    public void save(Content content){
        content.setId(++sequence);
        contents.put(content.getId(), content);
    }

    public void edit(int id, Content content){
        contents.put(id,content); //put 함수 활용 이유: 나중에 입력된 값으로 덮어 씌워지기 때문에
    }

    public void delete(int id){
        contents.remove(id);
    }

    public List<Content> findAll(){ //전체 불러오기
        return new ArrayList<>(contents.values());
    }

    public Content findById(int id){
        return contents.get(id);
    }


}
  • service 코드 : 컨트롤러에서 요청받은 동작들을 수행
package project.NoticeBoard.service;


import lombok.RequiredArgsConstructor;
import org.springframework.cglib.core.Local;
import org.springframework.stereotype.Service;
import project.NoticeBoard.domain.Content;
import project.NoticeBoard.repository.ContentRepository;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ContentService {

    private final ContentRepository contentRepository;

    public void writeContent(Content content){  //게시글 작성 (본문추가 + 게시글번호 부여)
        LocalDateTime now = LocalDateTime.now();
        String formattedDate = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm::ss"));
        content.setUpdateDate(formattedDate);

        contentRepository.save(content);
    }

    public void editContent(int id, String texts, String password){ //게시글 수정 (시간변경, 본문 수정)
        Content content = contentRepository.findById(id);
        if(!content.getPassword().equals(password)){
            return;
        }
        content.setTexts(texts);
        LocalDateTime now = LocalDateTime.now();
        String formattedDate = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm::ss"));
        content.setUpdateDate(formattedDate);
        contentRepository.edit(id,content);
    }

    public void deleteContent(int id, String password){ //비밀번호 확인 후 삭제
        Content content = contentRepository.findById(id);
        if(!content.getPassword().equals(password)){
            return;
        }
        contentRepository.delete(id);
    }

    public List<Content> getAllContents(){ //전체조회
        return  contentRepository.findAll();
    }

    public Content getContent(int id){ //한건조회
        return contentRepository.findById(id);
    }
}

  • 어노테이션 정리 
    • @Controller : Spring MVC 의 컨트롤러를 선언하는데 사용이 된다. HTTP요청을 처리하고 응답을 반환하는 클래스를 선언할 때 이용한다. 
    • @RequiredArgsConstructor : Lombok 라이브러리 중 하나로, 주로 클래스 내부의 final 필드값의 생성자를 자동으로 생성해준다.
    • @Getmapping : HTTP GET request에 대해서 매핑시킬 때 사용한다. 괄호 안에 지정된 엔드포인트를 작성하면 GET요청이 왔을 때, 해당 메소드가 실행된다.
    • @Postmapping : HTTP POST request에 대해서 매핑시킬 때 사용한다. 괄호 안에 지정된 엔드포인트를 작성하면 POST요청이 왔을 때, 해당 메소드가 실행된다.  
    • @PathVariable : RESTful 웹서비스에서 URL 경로의 일부를 변수로 사용하는 경우가 있는데, 예를 들면 /users/{id}와 같은 경로에서 매핑이 될 때, 인자값 식별하기 위해 활용한다.
    • @Data : Lombok 라이브러리 중 하나로, 보통 클래스 내 필드의 Getter,Setter 등 메소드를 자동생성시키기 위해 활용한다.
    • @Repository : 데이터베이스를 액세스하는 클래스를 정의할 때 활용한다. 
    • @Service : 비지니스 로직을 담당하는 클래스에 작성하고, 서비스 컴포넌트임을 표시한다.
      • * @Controller, @Repository, @Service는 어노테이션 내부에 @Component가 공통으로 존재한다. application context에서 component scan 대상이 되는 클래스들을 찾아 빈에 등록시킨다. 

 

UI는 다른 블로그를 참고하고 GPT에게 물어보며 제작한 상황이다. 학교 교과과정으로 HTML,CSS,JS를 배웠지만 익숙해질 때까진 시간이 더 걸릴 예정이다.. 



https://velog.io/@kimdy0915/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8Spring-Boot%EB%A1%9C-%EA%B2%8C%EC%8B%9C%ED%8C%90-%EB%B2%A1%EC%97%94%EB%93%9C-%EC%84%9C%EB%B2%84-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

스프링 부트(Spring Boot)로 게시판 벡엔드 서버 만들기

Spring Boot를 기반으로 CRUD(Create, Read, Update, Delete) 기능이 포함된 REST API를 만들어보려고 한다.데이터베이스는 h2 DB를 연결하고 Lombok과 JPA를 이용해서 게시글 데이터를 저장하고 조회할 것이다.그

velog.io

https://chb2005.tistory.com/62

 

[Spring Boot] CRUD 게시판 (DB 사용 X, 회원 기능 X)

기능 글 작성 전체 글 보기 글 보기 글 수정 글 삭제 글 수정 및 삭제 시에는 비밀번호가 일치해야 함 프로젝트 구조 및 설명 domain : 비지니스 도메인 객체 content 객체 생성 repository : DB와 연결되

chb2005.tistory.com

 

반응형