Spring Todo-List 1 - 할 일 목록API spec & 구현

춤인형의 개발일지·2024년 12월 26일

Spring실습

목록 보기
14/40

24/12/26

To-do List만들기

  1. API 설계 (spec 정하기)
    - 필요한 기능
    - HTTP method, (url)path
    - 요청 시 데이터 / 응답 시 데이터
  2. 개발 (백엔드)
    1. DTO 만들기 (가장 쉬움)
    2. 컨트롤러 (여기까지가 API spec을 보고 그대로 작성할 수 있는 것)
    3. 엔티티 설계 (어려움)
    4. 엔티티, 리포지토리 구현 (쉬움)
    5. 서비스 구현

API spec

  • 생성
    post | /Todos

    • Request (request Body)
      • content String 할일 목록
    • Response
      - content String 할일 목록
      - Id Long 할일 목록 ID
      ex)
      {
      "content" : "푹잦기"
      }
  • 조회
    Get | /Todos

    • Request : 전체 조회니까 x
    • Response
      - List<String> 할일 목록들
      ex)
      {
      "content" : [
      "푹자기",
      "잘자기",
      "먹기"
      ]
      }
  • 수정
    Post | /Todos/{TodoId}

    • Request
      • path : Long TodoId
      • body : content String 할일목록
    • Response
      • content String 할일목록
      • id Long 할일 목록 id
  • 삭제
    Delete | /Todos/{TodoId}

    • Request
      • path : Long TodoId
    • Response
      • id Long 할일목록id

구현하기

  1. DTO만들기
//요청데이터
public record TodoRequest(
        Long titleId,
        String content
) {
}
//응답데이터
public record TodoResponse(
        String content,
        Long id) {
}
  1. 컨트롤러
    일단, 오류가 나든말든 함수까지 싹다 적자
@RestController
public class TodoRestController {

    private TodoService todoService;

    public TodoRestController(TodoService todoService) {
        this.todoService = todoService;
    }

	//생성
    @PostMapping("/todos")
    public TodoResponse create(@RequestBody TodoRequest todoRequest){
        return todoService.create(todoRequest);
    }

	//조회
    @GetMapping("/todos")
    public List<TodoResponse> get(){
        return todoService.read();
    }

	//수정
    @PutMapping("/todos/{todoId}")
    public TodoResponse update(@PathVariable Long todoId, @RequestBody TodoRequest todoRequest){
        return todoService.update(todoId, todoRequest);
    }


	//삭제
    @DeleteMapping("/todos/{todoId}")
    public void delete(@PathVariable Long todoId){
        todoService.delete(todoId);
    }
}
  1. 엔티티 설계
    엔티티에 꼭 있어야하는 것
  2. id
  3. getter, id뺀 생성자, 기본 생성자, getter
@Entity
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String content;

    public Todo() {
    }

    public Todo(String content) {
        this.content = content;
    }

    public Long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}
  1. 컨트롤러에 있는 서비스 구현
@Service
public class TodoService {

    private TodoRepository todoRepository;

	public TodoService(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }
}
  1. 리포지토리 구현
import org.springframework.data.jpa.repository.JpaRepository;

public interface TodoRepository extends JpaRepository<Todo, Long>
{
}

이제부터 crud 개발이다.

  • 생성
public TodoResponse create(TodoRequest todoRequest) {
        Todo save = todoRepository.save(new Todo(todoRequest.content()));
        return new TodoResponse(save.getContent(), save.getId());
    }

.save()를 사용하면 자동으로 id값이 저장된다. 꼭 save를 할때는 내가 원하는 output값의 오브젝트를 생성해줘야한다.

  • 조회
public List<TodoResponse> read() {
        List<Todo> todoList = todoRepository.findAll();
        return todoList.stream().map(content -> new TodoResponse(content.getContent(), content.getId())).toList();
    }

모든 데이터들을 찾아서 map 를 사용해서 전부다 List안으로 넣어준다.

-수정

@Transactional
    public TodoResponse update(Long todoId, TodoRequest todoRequest) {
        Todo todo = todoRepository.findById(todoId).orElseThrow();
        todo.setContent(todoRequest.content());
        return new TodoResponse(todoRequest.content(), todoId);
    }

아이디를 찾아서, 그 아이디를 사용자가 요청한 데이터로 바꾸고, 그걸 저장한다. 라는 구성을 가지고 있다.
저장한다 라는 것은 save함수를 사용해야 하는데 그걸 대신해주는 아이가 @Transactional이다. `쉽게 이야기하면, 내가 바꾼 내용들을 적용시켜주겠다는 이야기이다.

-삭제

public void delete(Long todoId) {
        Todo todo = todoRepository.findById(todoId).orElseThrow();
        todoRepository.delete(todo);
    }

orElseThrow()예외처리를 하지 않았을 때 생기는 문제점은
1. optional 관리가 어려움
2. 최상위객체에 대해 상속받는 경우, 제목이 없는 내용물이 될 수 있음


0개의 댓글