메모장 CRUD 실습

하마·2025년 3월 21일

Spring

목록 보기
16/22
post-thumbnail

0. Spring Boot Initialize


  • Name: Memo
  • Type: Gradle - Groovy
  • Ver: 3.3.10
  • JDK: Amazon Corretto 17.0.14
  • Packaging: Jar
  • Dependencies:
    • Spring Web
    • Lombok
    • Thymeleaf

1. 클래스 설계


1. Memo 클래스 설계


  1. 요구사항 분석
    • 각각의 메모는 식별자, 제목, 내용으로 구성되어 있음
    • Memo 객체 생성이 필요함

Memo

package com.example.memo.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class Memo {

  private Long id;
  private String title;
  private String contents;

}

2. DTO 클래스 설계


  • 요청/응답 데이터를 처리하는 DTO 객체를 생성함

MemoRequestDto

package com.example.memo.dto;

@Getter
public class MemoRequestDto {

  private String title;
  private String contents;

}

MemoResponseDto

package com.example.memo.dto;

@Getter
public class MemoResponseDto {

  private Long id;
  private String title;
  private String contents;

}

2. CRUD 구현


1. 메모 생성 API


MemoController 생성

package com.example.memo.controller;


@RestController
@RequestMapping("/memos")
public class MemoController {

  // DB를 사용하지 않기 때문에 Map 자료구조로 DB 대체 활용
  private final Map<Long, Memo> memoList = new HashMap<>();

  @PostMapping
  public MemoResponseDto createMemo(@RequestBody MemoRequestDto dto) {

    // 식별자가 1씩 증가하도록 만듦
    Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;

    // 요청받은 데이터로 Memo 객체 생성
    Memo memo = new Memo(memoId, dto.getTitle(), dto.getContents());

    // Inmemory에 Memo 저장
    // Inmemory: 실제 DB가 아닌 Map 자료구조를 사용하기 때문에 종료 시 없어지는 데이터라는 의미
    memoList.put(memoId, memo);

    return new MemoResponseDto(memo);

  }

}

@RestController : 데이터를 항상 JSON 형태로 통신하기 위해 사용
@RequestMapping : prefix 설정
@PostMapping : 생성이기 때문에 POST 사용
@RequestBody : 클라이언트로부터 JSON 데이터를 요청받았을 때, 파라미터로 데이터를 바인딩하기 위해 사용

2. 단건 메모 조회 API


MemoController 수정

package com.example.memo.controller;

@RestController
@RequestMapping("/memos")
public class MemoController {

  private final Map<Long, Memo> memoList = new HashMap<>();

  @GetMapping("/{id}")
  public MemoResponseDto findMemoById(@PathVariable Long id){

    Memo memo = memoList.get(id);
    return new MemoResponseDto((memo));

//    return new MemoResponseDto(memoList.get(id));

  }

}

@GetMapping : 조회이기 때문에 사용
-> @RequestMapping 으로 이미 "/memos" prefix가 정해져있기 때문에 식별자만 지정
@PathVariable : 식별자를 파라미터로 바인딩할 때 사용

3. 단건 메모 전체 수정 API


MemoController 수정

package com.example.memo.controller;

@RestController
@RequestMapping("/memos")
public class MemoController {

  private final Map<Long, Memo> memoList = new HashMap<>();

  @PutMapping("/{id}")
  public MemoResponseDto updateMemoById(
      @PathVariable Long id,
      @RequestBody MemoRequestDto dto
  ) {
    Memo memo = memoList.get(id);

    memo.update(dto);

    return new MemoResponseDto(memo);

  }

}

@PutMapping : 전체 수정을 위해 사용
@RequestBody : id뿐만 아니라 어떤 데이터를 수정할 지, 그 데이터도 요청받아야 함

Memo 수정

package com.example.memo.entity;

@Getter
@AllArgsConstructor
public class Memo {

  private Long id;
  private String title;
  private String contents;

  public void update(MemoRequestDto dto) {
    this.title = dto.getTitle();
    this.contents = dto.getContents();
  }

}

4. 단건 메모 삭제 API


MemoController 수정

package com.example.memo.controller;

@RestController
@RequestMapping("/memos")
public class MemoController {

  private final Map<Long, Memo> memoList = new HashMap<>();

  // 삭제이기 때문에 void
  @DeleteMapping("/{id}")
  public void deleteMemo(@PathVariable Long id) {
    memoList.remove(id);
  }

}

5. GitHub


3. 문제점


  • 실제 문제의 원인을 파악하기 어려움
    • 응답 코드가 세분화되어있지 않음
      • 성공 시 모두 200 OK
    • 적절한 예외가 발생하지 않음
      • 실패 시 모두 500 Error
  • 잘못된 정보가 전달 & 처리될 수 있음
  • 서버가 종료된 후 다시 켜지면 데이터가 모두 초기화됨
  • 모든 로직을 컨트롤러가 담당하고 있음

참고자료


Spring 입문 - 5주차

  • CRUD 실습

0개의 댓글