๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โœ๏ธ Today I Learned(TIL)/๐ŸŒฑ ์ŠคํŒŒ๋ฅดํƒ€ ๋‚ด์ผ๋ฐฐ์›€์บ ํ”„

์ฃผํŠน๊ธฐ ์ž…๋ฌธ/์ˆ™๋ จ_Day 5

by carrot0911 2024. 12. 3.

์˜ค๋Š˜ ํ•œ ๊ณต๋ถ€

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ(Java) 1๋ฌธ์ œ ํ’€์ด & ๋ธ”๋กœ๊ทธ ์ •๋ฆฌ
  • ์Šคํ”„๋ง 5์ฃผ์ฐจ ๊ฐ•์˜ ๋“ฃ๊ธฐ
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

 

์˜ค๋Š˜ ์–ป์€ ๋‚ด์šฉ ์ •๋ฆฌ

CRUD ์‹ค์Šต

๋ฉ”๋ชจ๋ฅผ CRUD ํ•  ์ˆ˜ ์žˆ๋Š” Web Application

1. ๋ฉ”๋ชจ ์ƒ์„ฑ ๊ธฐ๋Šฅ C
2. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์กฐํšŒ ๊ธฐ๋Šฅ R
3. ๋ฉ”๋ชจ ์ „์ฒด ์ˆ˜์ • ๊ธฐ๋Šฅ U
4. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์‚ญ์ œ ๊ธฐ๋Šฅ D

1. ์š”๊ตฌ ์‚ฌํ•ญ ๋ถ„์„ ๋ฐ ์„ค๊ณ„

๋”๋ณด๊ธฐ

๋ฉ”๋ชจ์žฅ API ์š”๊ตฌ ์‚ฌํ•ญ

  • ํ†ต์‹  ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋Š” JSON์ด๋‹ค.
  • ๊ฐ๊ฐ ๋ฉ”๋ชจ๋Š” ์‹๋ณ„์ž(id), ์ œ๋ชฉ(title), ๋‚ด์šฉ(contents)์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
  • ๋ฉ”๋ชจ CRUD ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค.

HTTP API ์„ค๊ณ„

  • ๋กœ๊ทธ์ธ๊ณผ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์„ ์ œ์™ธํ•œ ๋Œ€๋ถ€๋ถ„์˜ API๋Š” CRUD ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์„ค๊ณ„ ์ˆœ์„œ
    • HTTP Method
      • POST : CREATE
      • GET : READ
      • PUT, PATCH : UPDATE
      • DELETE : DELETE
    • Restful API → URL Mapping
    • ์š”์ฒญ ๋ฐ ์‘๋‹ต๊ฐ’ ์„ค๊ณ„
      • HTTP Method + URL๋งŒ์œผ๋กœ ์–ด๋–ค API์ธ์ง€ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๋ฉ”๋ชจ ์ƒ์„ฑ
    • POST
    • /memos
  • ๋ฉ”๋ชจ ๋‹จ๊ฑด ์กฐํšŒ
    • GET
    • /memos/{id}
  • ๋ฉ”๋ชจ ์ˆ˜์ •(์ „์ฒด)
    • PUT
    • /memos/{id}
  • ๋ฉ”๋ชจ ์‚ญ์ œ
    • DELETE
    • /memos/{id}

2. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

๋”๋ณด๊ธฐ

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

  • IntelliJ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  • New Project๋ฅผ ํด๋ฆญํ•œ๋‹ค.
  • ์™ผ์ชฝ ๋ฉ”๋‰ด์—์„œ "Spring Boot"๋ฅผ ํด๋ฆญํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•œ๋‹ค.
  • ๋‹ค์Œ ์‚ฌํ•ญ์„ ๊ผญ ํ™•์ธํ•˜๊ธฐ!!
    • Name : memo
    • Language : Java
    • Build system : Gradle - Groovy
    • JDK : 17
  • Next๋ฅผ ํด๋ฆญํ•œ๋‹ค.
  • Dependencies๋ฅผ ์•„๋ž˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ  Create๋ฅผ ํด๋ฆญํ•œ๋‹ค.
    • Spring Web
    • Lombok
    • Thymeleaf

ํŽธ์˜ ๊ธฐ๋Šฅ ์„ค์ •

  • Auto Import
  • Editor Zoom : Mouse Wheel
  • Lombok

3. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ์—ฐ๋™

๋”๋ณด๊ธฐ

IntelliJ Git ์—ฐ๋™ ๋ฐฉ๋ฒ•

  • GitHub์—์„œ Repository(Studt_memo)๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ๋‹ค.
  • ๋ฉ”๋‰ด์— VCS๊ฐ€ ์žˆ๋‹ค.
  • VCS์—์„œ Create Git Repository๋ฅผ ํด๋ฆญํ•˜๊ณ  ํ”„๋กœ์ ํŠธ ํด๋”์— OK์„ ํด๋ฆญํ•˜๋ฉด Git์ด ์„ค์น˜๋œ๋‹ค.
  • ๋ฉ”๋‰ด์˜ Git์—์„œ Manage Remotes๋ฅผ ์„ ํƒํ•œ๋‹ค.
  • + ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ๋’ค GitHub Repository์˜ URL์„ ์ž…๋ ฅํ•œ๋‹ค.
  • ์ •์ƒ์ ์œผ๋กœ ์—ฐ๋™๋œ ๊ฒƒ์„ ํ™•์ธํ•œ๋‹ค.

IntelliJ์—์„œ Git Commit  & Push ํ•˜๊ธฐ

  • ์ขŒ์ธก Commit ํƒญ์„ ํด๋ฆญํ•˜๊ณ  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ™•์ธํ•œ ํ›„ ๋ณ€๊ฒฝ์‚ฌํ•ญ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ ์€ ํ›„ Commit์„ ํด๋ฆญํ•œ๋‹ค.
  • Commit์„ ํ–ˆ๋‹ค๋ฉด push๊นŒ์ง€ ๋งˆ๋ฌด๋ฆฌํ•œ ํ›„ GitHub์œผ๋กœ ๋Œ์•„๊ฐ€์„œ Commit & Push๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

๋ธ”๋กœ๊ทธ์˜ ๋„์›€์„ ์–ป์—ˆ๋‹ค....
https://velog.io/@zerokick/IntelliJ-IntelliJ-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-GitHub-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0

4. ํด๋ž˜์Šค ์„ค๊ณ„

๋”๋ณด๊ธฐ

Memo ํด๋ž˜์Šค ์„ค๊ณ„

  • ์š”๊ตฌ์‚ฌํ•ญ ๋ถ„์„
    • ๊ฐ๊ฐ์˜ ๋ฉ”๋ชจ๋Š” ์‹๋ณ„์ž(id), ์ œ๋ชฉ(title), ๋‚ด์šฉ(contents)์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
    • Memo ๊ฐ์ฒด ์ƒ์„ฑ์ด ํ•„์š”ํ•˜๋‹ค.
package com.example.memo.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;


@Getter
@AllArgsConstructor
public class Memo {

    // ์†์„ฑ (์‹๋ณ„์ž)
    /*
    ์‹๋ณ„์ž (id)
    Long ํƒ€์ž…์„ ์“ฐ๋Š” ์ด์œ  : int๋ณด๋‹ค ํ›จ์”ฌ ๋” ํฌ๊ณ , ๋ž˜ํผ ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— null ๊ฐ’์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.
    ๋ณดํ†ต ์‹๋ณ„์ž๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด์„œ Long ํƒ€์ž…์„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.
     */
    private Long id;
    // ์ œ๋ชฉ (title)
    private String title;
    // ๋‚ด์šฉ (contents)
    private String contents;

}

DTO ์„ค๊ณ„

  • ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ RequestDto๋กœ ๋ช…๋ช…ํ•œ๋‹ค.
  • ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ResponseDto๋กœ ๋ช…๋ช…ํ•œ๋‹ค.

1. Client์˜ ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์ค„ MemoRequestDto ํด๋ž˜์Šค ์ƒ์„ฑ

package com.example.memo.dto;

import lombok.Getter;

@Getter
public class MemoRequestDto {

    /*
    ์š”์ฒญ๋ฐ›์„ ๋ฐ์ดํ„ฐ๋Š” title, contents ์ž…๋‹ˆ๋‹ค. ๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.
     */
    // ์ œ๋ชฉ (title)
    private String title;
    // ๋‚ด์šฉ (contents)
    private String contents;

}

2. Client์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉํ•  MemoResponseDto ํด๋ž˜์Šค ์ƒ์„ฑ

package com.example.memo.dto;

import lombok.Getter;

@Getter
public class MemoResponseDto {

    /*
    ์ด ๋ถ€๋ถ„์€ ์ •์˜ํ•˜๊ธฐ ๋‚˜๋ฆ„์ด๋‹ค. ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค!
     */
    // ์‹๋ณ„์ž (id)
    private Long id;
    // ์ œ๋ชฉ (title)
    private String title;
    // ๋‚ด์šฉ (contents)
    private String contents;

}

5. ๋ฉ”๋ชจ ์ƒ์„ฑ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

Memo ์ƒ์„ฑ API ๊ตฌํ˜„

1. ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•  MemoList ์ƒ์„ฑ

  • Map์€ key, value ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
/*
์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž„์‹œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค.
์ดˆ๊ธฐํ™”๋ฅผ ํ•ด์ฃผ๋ฉด memoList๋ผ๋Š” ๋นˆ map ์ž๋กœ๊ตฌ์กฐ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
 */
private final Map<Long, Memo> memoList = new HashMap<>();

2. Memo ์ƒ์„ฑ ๋กœ์ง ์ž‘์„ฑ

package com.example.memo.controller;

import com.example.memo.dto.MemoRequestDto;
import com.example.memo.dto.MemoResponseDto;
import com.example.memo.entity.Memo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@RestController  // ๋ฐ์ดํ„ฐ๋ฅผ ํ•ญ์ƒ JSON ํ˜•ํƒœ๋กœ ํ†ต์‹ ์„ ํ•˜๊ธฐ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— @RestController๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
@RequestMapping ("/memos") // prefix URL์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
public class MemoController {
    /*
    ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž„์‹œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค.
    ์ดˆ๊ธฐํ™”๋ฅผ ํ•ด์ฃผ๋ฉด memoList๋ผ๋Š” ๋นˆ map ์ž๋กœ๊ตฌ์กฐ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
     */
    private final Map<Long, Memo> memoList = new HashMap<>();

    /*
    ์‹ค์ œ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉํ•  Controller๋ฅผ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค.
    ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ์„ค์ •ํ•˜๊ธฐ ๋‚˜๋ฆ„์ด๋‹ค. ์ƒ์„ฑํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ์ง€ ์•Š์•„๋„ ๋˜๊ณ  ์ค˜๋„ ๋˜๋Š”๋ฐ, ๊ทธ๋•Œ ResponseDto ํ˜•ํƒœ๋กœ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค.
    ๊ทธ๋ฆฌ๊ณ  "์šฐ๋ฆฌ๋Š” MemoResponseDto๋ฅผ ์ „๋‹ฌํ•  ๊ฒƒ์ด๋‹ค."๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค.
     */
    @PostMapping  // ์ƒ์„ฑ์ด๊ธฐ ๋–„๋ฌธ์— ์‚ฌ์šฉํ•œ๋‹ค.
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto dto) {  // ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ”๋กœ ๋ฐ”์ธ๋”ฉ ํ•˜๋Š” ๋ฐฉ๋ฒ• : @RequestBody

        // ์‹๋ณ„์ž๊ฐ€ 1์”ฉ ์ฆ๊ฐ€ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
        Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;  // MemoList.keySet() ์ค‘์—์„œ ์ตœ๋Œ€๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ์ตœ๋Œ€๊ฐ’์—์„œ 1์”ฉ ์ฆ๊ฐ€ํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค.

        /*
        ์š”์ฒญ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋กœ Memo ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
        MemoRequestDto ํ˜•ํƒœ๋กœ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— Memo ๊ฐ์ฒด๋กœ ๋ฐ”๊ฟ”์ฃผ์–ด์•ผ ํ•œ๋‹ค.
         */
        Memo memo = new Memo(memoId, dto.getTitle(), dto.getContents());

        // Inmemory(Map) DB์— Memo๋ฅผ ์ €์žฅํ•œ๋‹ค.
        memoList.put(memoId, memo);

        /*
        ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
        ์‘๋‹ตํ•˜๋Š” ๋ฐ์ดํ„ฐ : MemoResponseDto ํ˜•ํƒœ
        ์š”์ฒญํ•˜๋Š” ๋ฐ์ดํ„ฐ : MemoRequestDto ํ˜•ํƒœ
         */
        return new MemoResponseDto(memo);
    }
}

postman ํ˜ธ์ถœ

  • 200 OK, ์กฐํšŒ๋œ Memo ์‘๋‹ต

6. ๋ฉ”๋ชจ ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

Memo ์กฐํšŒ API ๊ตฌํ˜„

1. Memo ์กฐํšŒ ๋กœ์ง ์ž‘์„ฑ

/**
 * ๋ฉ”๋ชจ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ
 * @param id - ์‹๋ณ„์ž
 * @return MemoResponseDto(memo) - ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
 */
@GetMapping("/{id}")  // ์กฐํšŒ์ด๊ธฐ ๋•Œ๋ฌธ์— @GetMapping ์‚ฌ์šฉํ•œ๋‹ค.
public MemoResponseDto findMemoById(@PathVariable Long id) {  // ์‹๋ณ„์ž๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ๋Š” @PathVariable์„ ์‚ฌ์šฉํ•œ๋‹ค.

    // memoList๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ get()์„ ํ†ตํ•ด์„œ key๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ์ €์žฅ๋˜์–ด ์žˆ๋Š” memo๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
    Memo memo = memoList.get(id);

    // ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
    return new MemoResponseDto(memo);
}

postman ํ˜ธ์ถœ

  • id์— ๋”ฐ๋ฅธ ๋ฉ”๋ชจ๋ฅผ ์‘๋‹ต๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • 200 OK, ์กฐํšŒ๋œ Memo ์‘๋‹ต

7. ๋ฉ”๋ชจ ์ˆ˜์ • ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

Memo ์ˆ˜์ • API ๊ตฌํ˜„

1. Memo ์ˆ˜์ • ๋กœ์ง ์ž‘์„ฑ

@PutMapping("/{id}")  // ์ „์ฒด ์ˆ˜์ •์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ @PutMapping์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹จ๊ฑด์„ ์ˆ˜์ •ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฝ๋กœ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
public MemoResponseDto updateMemoById(
        @PathVariable Long id,  // @PathVariable๋กœ id ๋ฐ”์ธ๋”ฉ
        @RequestBody MemoRequestDto dto  // ์–ด๋–ค ๋ฐ์ดํ„ฐ๋กœ ์ˆ˜์ •ํ•  ์ง€๋„ ์š”์ฒญ์„ ๋ฐ›์•„์•ผ ํ•œ๋‹ค. ์ œ๋ชฉ, ๋‚ด์šฉ์„ ๋ชจ๋‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
) {
    // ์‹ค์ œ๋กœ ๋™์ž‘ํ•  ๋กœ์ง
    Memo memo = memoList.get(id);
    // Memo ์ˆ˜์ • ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ
    memo.update(dto);

    // ๋ฐ”๋€ Memo๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์—…๋ฐ์ดํŠธ๋œ Memo๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
    return new MemoResponseDto(memo);
}

2. Memo ์ˆ˜์ • ๋ฉ”์„œ๋“œ ์ƒ์„ฑ

// update ๋ฉ”์„œ๋“œ
public void update(MemoRequestDto dto) {
    this.title = dto.getTitle();
    this.contents = dto.getContents();
}

postman ํ˜ธ์ถœ

  • 200 OK, ์ˆ˜์ • ํ›„ ๋ฐ์ดํ„ฐ ์‘๋‹ต

8. ๋ฉ”๋ชจ ์‚ญ์ œ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

Memo ์‚ญ์ œ API ๊ตฌํ˜„

1. Memo ์‚ญ์ œ ๋กœ์ง ์ž‘์„ฑ

@DeleteMapping("/{id}")  // ์‹๋ณ„์ž๋กœ id๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
public void deleteMemo(@PathVariable Long id) {

    // memoList์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ฐ’ ์‚ญ์ œ -> id์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ
    memoList.remove(id);
}

postman ํ˜ธ์ถœ

  • 200 OK, ์‘๋‹ต ๋ฐ์ดํ„ฐ ์—†์Œ
  • ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‘๋‹ต ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ

๋ฌธ์ œ์ 

  • ์‹ค์ œ ๋ฌธ์ œ์˜ ์›์ธ์„ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด ์ „๋‹ฌ ๋ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.
    • ์‘๋‹ต ์ฝ”๋“œ๊ฐ€ ์„ธ๋ถ„ํ™”๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค. (์„ฑ๊ณต ์‹œ ๋ชจ๋‘ 200k)
    • ์ ์ ˆํ•œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. (์‹คํŒจ ์‹œ ๋ชจ๋‘ 500 Error ๋ฐœ์ƒ → 500๋ฒˆ๋Œ€ Error๋Š” ์„œ๋ฒ„ Error์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹๋‹ค.)
    • ์„œ๋ฒ„๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„ ๋‹ค์‹œ ์ผœ์ง€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

 

๋ฉ”๋ชจ์žฅ ํ”„๋กœ์ ํŠธ

๋ฉ”๋ชจ์žฅ Use Case
๋ฉ”๋ชจ๋ฅผ CRUD ํ•  ์ˆ˜ ์žˆ๋Š” Web Application

1. ๋ฉ”๋ชจ ์ƒ์„ฑ ๊ธฐ๋Šฅ C
2. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์กฐํšŒ ๊ธฐ๋Šฅ, ์ „์ฒด ์กฐํšŒ ๊ธฐ๋Šฅ R
3. ๋ฉ”๋ชจ ์ „์ฒด ์ˆ˜์ • ๊ธฐ๋Šฅ, ์ œ๋ชฉ ์ˆ˜์ • ๊ธฐ๋Šฅ U
4. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์‚ญ์ œ ๊ธฐ๋Šฅ D

1. ์š”๊ตฌ์‚ฌํ•ญ ๋ถ„์„ ๋ฐ ์„ค๊ณ„

๋”๋ณด๊ธฐ

๋ฉ”๋ชจ์žฅ API ์š”๊ตฌ์‚ฌํ•ญ

  •  ํ†ต์‹  ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋Š” JSON์ด๋‹ค.
  • ๊ฐ๊ฐ์˜ ๋ฉ”๋ชจ๋Š” ์‹๋ณ„์ž(id), ์ œ๋ชฉ(title), ๋‚ด์šฉ(contents)์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
  • ์‘๋‹ต์„ ๊ฐ๊ฐ์˜ API์— ์•Œ๋งž๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ฉ”๋ชจ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. (CREATE)
    • ๋ฉ”๋ชจ ์ƒ์„ฑ ์‹œ ์ œ๋ชฉ, ๋‚ด์šฉ์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ(์‹๋ณ„์ž, ์ œ๋ชฉ, ๋‚ด์šฉ)๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
  • ๋ฉ”๋ชจ ์ „์ฒด ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. (READ)
    • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ํ•œ ๋ฒˆ์— ์‘๋‹ตํ•œ๋‹ค.
    • ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋น„์–ด์žˆ๋Š” ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์‘๋‹ตํ•œ๋‹ค.
  • ๋ฉ”๋ชจ ํ•˜๋‚˜๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. (READ)
    • ์กฐํšŒํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์กฐํšŒ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
    • ์กฐํšŒ๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • ๋ฉ”๋ชจ ํ•˜๋‚˜๋ฅผ ์ „์ฒด ์ˆ˜์ •(๋ฎ์–ด์“ฐ๊ธฐ)ํ•  ์ˆ˜ ์žˆ๋‹ค. (UPDATE)
    • ์ˆ˜์ •ํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •ํ•  ์š”์ฒญ ๋ฐ์ดํ„ฐ(์ œ๋ชฉ, ๋‚ด์šฉ)๊ฐ€ ๊ผญ ํ•„์š”ํ•˜๋‹ค.
  • ๋ฉ”๋ชจ ํ•˜๋‚˜์˜ ์ œ๋ชฉ์„ ์ˆ˜์ •(์ผ๋ถ€ ์ˆ˜์ •)ํ•  ์ˆ˜ ์žˆ๋‹ค. (UPDATE)
    • ์ˆ˜์ •ํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •ํ•  ์š”์ฒญ ๋ฐ์ดํ„ฐ(์ œ๋ชฉ)๊ฐ€ ๊ผญ ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
    • ์ˆ˜์ •๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • ๋ฉ”๋ชจ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. (DELETE)
    • ์‚ญ์ œํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์‚ญ์ œ๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.

HTTP API ์„ค๊ณ„

API ๋ช…์„ธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์ค‘์š”ํ•œ ์ด์œ 

  • ๋ช…์„ธ์„œ๋ฅผ ํ†ตํ•ด์„œ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ(๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž)์€ ๋ช…์„ธ์„œ๋งŒ ๋ณด๊ณ ๋„ ์‹ค์ œ๋กœ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
  • ์ƒ์„ธํ•˜๋ฉด ์ƒ์„ธํ• ์ˆ˜๋ก ์ข‹๋‹ค.

2. ๋ฉ”๋ชจ ์ƒ์„ฑ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. (CREATE)
    • ๋ฉ”๋ชจ ์ƒ์„ฑ ์‹œ ์ œ๋ชฉ, ๋‚ด์šฉ์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ(์‹๋ณ„์ž, ์ œ๋ชฉ, ๋‚ด์šฉ)๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 201 CREATED๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ์ƒ์„ฑ API ๊ตฌํ˜„(CREATE)

1. ๋ฉ”๋ชจ ์ƒ์„ฑ API ์ˆ˜์ •

@PostMapping  // ์ƒ์„ฑ์ด๊ธฐ ๋–„๋ฌธ์— ์‚ฌ์šฉํ•œ๋‹ค.
public ResponseEntity<MemoResponseDto> createMemo(@RequestBody MemoRequestDto dto) {  // ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ”๋กœ ๋ฐ”์ธ๋”ฉ ํ•˜๋Š” ๋ฐฉ๋ฒ• : @RequestBody, ๋ฉ”๋ชจ๋ฅผ ์ƒ์„ฑํ•˜๋Š” API์—์„œ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๊ธฐ ์œ„ํ•ด ResponseEntity๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

    // ์‹๋ณ„์ž๊ฐ€ 1์”ฉ ์ฆ๊ฐ€ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
    Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;  // MemoList.keySet() ์ค‘์—์„œ ์ตœ๋Œ€๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ์ตœ๋Œ€๊ฐ’์—์„œ 1์”ฉ ์ฆ๊ฐ€ํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค.

    /*
    ์š”์ฒญ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋กœ Memo ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    MemoRequestDto ํ˜•ํƒœ๋กœ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— Memo ๊ฐ์ฒด๋กœ ๋ฐ”๊ฟ”์ฃผ์–ด์•ผ ํ•œ๋‹ค.
     */
    Memo memo = new Memo(memoId, dto.getTitle(), dto.getContents());

    // Inmemory(Map) DB์— Memo๋ฅผ ์ €์žฅํ•œ๋‹ค.
    memoList.put(memoId, memo);

    /*
    ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
    ์‘๋‹ตํ•˜๋Š” ๋ฐ์ดํ„ฐ : MemoResponseDto ํ˜•ํƒœ
    ์š”์ฒญํ•˜๋Š” ๋ฐ์ดํ„ฐ : MemoRequestDto ํ˜•ํƒœ
     */
    return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.CREATED);
    /*
    MemoResponseDto๋งŒ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ ์‘๋‹ตํ•  HTTP Status ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋„ฃ์–ด์ค€๋‹ค.
    HTTP Status๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด 1xx, 2xx, 3xx, 4xx, 5xx๊นŒ์ง€ ์ด๋ฏธ Enum ๊ฐ’์œผ๋กœ ๋‹ค ๋งŒ๋“ค์–ด์ ธ์žˆ๋‹ค.
    ์‚ฌ์šฉํ•  ์‘๋‹ต์— ์ ์ ˆํ•œ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๋ฐ”๋žŒ์งํ•˜๋‹ค.
     */
}

postman ํ…Œ์ŠคํŠธ

  • ๋ฉ”๋ชจ ์ƒ์„ฑ
  • HTTP ์ƒํƒœ ์ฝ”๋“œ๋„ ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ๋ฉ”๋ชจ ๋ชฉ๋ก ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ ์ „์ฒด ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. (READ)
    • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ํ•œ ๋ฒˆ์— ์‘๋‹ตํ•œ๋‹ค.
    • ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋น„์–ด์žˆ๋Š” ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์‘๋‹ตํ•œ๋‹ค.
    • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ๋ชฉ๋ก ์กฐํšŒ API ๊ตฌํ˜„ (READ)

  • memoList๋ฅผ ์กฐํšŒํ•˜์—ฌ return ํƒ€์ž…์ธ List<MemoResponseDto>๋กœ ๋ณ€ํ™˜ํ•œ ํ›„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.
  • ๋ชจ๋“  ์‘๋‹ต์„ ResponseEntity๋กœ ํ†ต์ผํ•˜๋Š”๊ฒŒ ๋”์šฑ ์ข‹๋‹ค.
  • ex) ResponseEntity<List<MemoResponseDto>>
@GetMapping  // ๋’ค์— ์•„๋ฌด๊ฒƒ๋„ ์ ์ง€ ์•Š๊ณ , ๊ด„ํ˜ธ๋„ ์ ์ง€ ์•Š์œผ๋ฉด ์ƒ๋‹จ์˜ @RequestMapping์ด Mapping๋œ๋‹ค.
public ResponseEntity<List<MemoResponseDto>> findAllMemos() {  // ์ „์ฒด ์กฐํšŒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์š”์—†๋‹ค.

    // init List ์ดˆ๊ธฐํ™”
    List<MemoResponseDto> responseList = new ArrayList<>();  // List๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ดˆ๊ธฐํ™”ํ•ด์ค˜์•ผ ํ•œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” new ํ•ด์„œ ์ธ์Šคํ„ด์Šคํ™” ํ•  ์ˆ˜ ์—†๋‹ค.


    /*
    HashMap<Memo> -> List<MemoResponseDto>
    ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ Map์œผ๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋‹ค. -> HashMap์— Memo๊ฐ€ ์ €์žฅ๋œ๋‹ค.
    ์ „์ฒด ์กฐํšŒํ•ด์„œ List<MemoResponseDto> ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
     */
    for (Memo memo : memoList.values()) {  // memoList์˜ ๋ชจ๋“  Memo๋ฅผ ๊บผ๋‚ธ๋‹ค. ๊บผ๋‚ด์ง„ Memo๋งŒํผ memo์— ๋“ค์–ด๊ฐ„๋‹ค. ํ•˜๋‚˜์”ฉ ๋“ค์–ด๊ฐ€๋ฉด์„œ ๋ฐ˜๋ณต๋ฌธ์ด ์‹คํ–‰๋œ๋‹ค.
        MemoResponseDto responseDto = new MemoResponseDto(memo);  // memo๊ฐ€ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๋€๋‹ค.

        responseList.add(responseDto);  // responseList์— ์ƒ์„ฑ๋œ MemoResponseDto๋ฅผ ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€ํ•œ๋‹ค.
    }

    /*
    Map To List
    ์ŠคํŠธ๋ฆผ ์‚ฌ์šฉํ•ด์„œ ์ข€ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„
    ์œ„์— ์žˆ๋Š” ์ฝ”๋“œ์™€ ๊ฒฐ๊ตญ ๊ฒฐ๊ณผ๋Š” ๋˜‘๊ฐ™๋‹ค.
    stream์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์ต์ˆ™ํ•ด์ง„๋‹ค๋ฉด ๊ทธ๋•Œ ์‚ฌ์šฉํ•  ๊ฒƒ!
     */
    //responseList = memoList.values().stream().map(MemoResponseDto::new).toList();

    return new ResponseEntity<>(responseList, HttpStatus.OK);  // ๋ชจ๋“  ์‘๋‹ต๊ฐ’์„ ResponseEntity๋กœ ํ†ต์ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค!

}

postman ํ…Œ์ŠคํŠธ

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
    • default ๋นˆ ๋ฐฐ์—ด์ด ์‘๋‹ต๋œ๋‹ค.
    • ResponseEntity๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„, ์„ฑ๊ณต์‹œ Default 200 OK๋กœ ์‘๋‹ตํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
    • ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์‘๋‹ต๋œ๋‹ค.

4. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ ํ•˜๋‚˜๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. (READ)
    • ์กฐํšŒํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์กฐํšŒ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.
    • ์กฐํšŒ๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 404 NOT FOUND๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ๋‹จ๊ฑด ์กฐํšŒ API ๊ตฌํ˜„ (READ)

  • ์‹๋ณ„์ž(id)๋ฅผ ํ†ตํ•ด Memo๋ฅผ ์กฐํšŒํ•œ๋‹ค.
/**
 * ๋ฉ”๋ชจ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ
 * @param id - ์‹๋ณ„์ž
 * @return MemoResponseDto(memo) - ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
 */
@GetMapping("/{id}")  // ์กฐํšŒ์ด๊ธฐ ๋•Œ๋ฌธ์— @GetMapping ์‚ฌ์šฉํ•œ๋‹ค.
public ResponseEntity<MemoResponseDto> findMemoById(@PathVariable Long id) {  // ์‹๋ณ„์ž๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ๋Š” @PathVariable์„ ์‚ฌ์šฉํ•œ๋‹ค.

    // memoList๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ get()์„ ํ†ตํ•ด์„œ key๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ์ €์žฅ๋˜์–ด ์žˆ๋Š” memo๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.
    Memo memo = memoList.get(id);

    // ResponseEntity๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋™์ ์œผ๋กœ ์‘๋‹ตํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
    if (memo == null) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    // ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
    return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.OK);
}

postman ํ…Œ์ŠคํŠธ

  • ์‹๋ณ„์ž๋กœ ์กฐํšŒ๋˜๋Š” Memo๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
  • ์‹๋ณ„์ž๋กœ ์กฐํšŒ๋˜๋Š” Memo๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ

5. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์ „์ฒด ์ˆ˜์ • ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ ํ•˜๋‚˜๋ฅผ ์ „์ฒด ์ˆ˜์ •(๋ฎ์–ด์“ฐ๊ธฐ)ํ•  ์ˆ˜ ์žˆ๋‹ค. (UPDATE)
    • ์ˆ˜์ •ํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •ํ•  ์š”์ฒญ ๋ฐ์ดํ„ฐ(์ œ๋ชฉ, ๋‚ด์šฉ)๊ฐ€ ๊ผญ ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.
    • ์ˆ˜์ •๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 404 NOT FOUND๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ๋‹จ๊ฑด ์ „์ฒด ์ˆ˜์ • API ๊ตฌํ˜„ (UPDATE)

@PutMapping("/{id}")  // ์ „์ฒด ์ˆ˜์ •์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ @PutMapping์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹จ๊ฑด์„ ์ˆ˜์ •ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฝ๋กœ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
public ResponseEntity<MemoResponseDto> updateMemoById(
        @PathVariable Long id,  // @PathVariable๋กœ id ๋ฐ”์ธ๋”ฉ
        @RequestBody MemoRequestDto dto  // ์–ด๋–ค ๋ฐ์ดํ„ฐ๋กœ ์ˆ˜์ •ํ•  ์ง€๋„ ์š”์ฒญ์„ ๋ฐ›์•„์•ผ ํ•œ๋‹ค. ์ œ๋ชฉ, ๋‚ด์šฉ์„ ๋ชจ๋‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
) {
    // ์‹ค์ œ๋กœ ๋™์ž‘ํ•  ๋กœ์ง
    Memo memo = memoList.get(id);

    // ResponseEntity๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋™์ ์œผ๋กœ ์‘๋‹ตํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
    if (memo == null) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    // ํ•„์ˆ˜ ๊ฐ’์„ ๊ฒ€์ฆํ•ด์ค€๋‹ค.
    if (dto.getTitle() == null || dto.getContents() == null) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);  // ํ•„์ˆ˜ ๊ฐ’์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— BAD_REQUEST๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
    }

    // memo ์ˆ˜์ •
    memo.update(dto);

    // ๋ฐ”๋€ Memo๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์—…๋ฐ์ดํŠธ๋œ Memo๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
    return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.OK);
}

postman ํ…Œ์ŠคํŠธ

  • ์‹๋ณ„์ž(id)๋กœ ์ƒ์„ฑ๋œ ๋ฉ”๋ชจ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
  • ์‹๋ณ„์ž(id)๋กœ ์ƒ์„ฑ๋œ ๋ฉ”๋ชจ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
  • title๋งŒ ์ „์†ก ๋˜๋Š” ๊ฒฝ์šฐ
  • contents๋งŒ ์ „์†ก ๋˜๋Š” ๊ฒฝ์šฐ

6. ๋ฉ”๋ชจ ๋‹จ๊ฑด ์ œ๋ชฉ ์ˆ˜์ • ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ ํ•˜๋‚˜์˜ ์ œ๋ชฉ์„ ์ˆ˜์ •(์ผ๋ถ€ ์ˆ˜์ •)ํ•  ์ˆ˜ ์žˆ๋‹ค. (UPDATE)
    • ์ˆ˜์ •ํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์ˆ˜์ •ํ•  ์š”์ฒญ ๋ฐ์ดํ„ฐ(์ œ๋ชฉ)์ด ๊ผญ ํ•„์š”ํ•˜๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 400 BAD REQUEST๋กœ ์„ค์ •ํ•œ๋‹ค.
    • ์ˆ˜์ •๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์‘๋‹ต๋œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.
    • ์ˆ˜์ •๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 404 NOT FOUND๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ๋‹จ๊ฑด ์ œ๋ชฉ ์ˆ˜์ • API ๊ตฌํ˜„ (UPDATE)

@PatchMapping("/{id}")  // ์ผ๋ถ€ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— @PatchMapping์ด ํ•„์š”ํ•˜๋‹ค.
public ResponseEntity<MemoResponseDto> updateTitle(
        @PathVariable Long id,
        @RequestBody MemoRequestDto dto
) {
    Memo memo = memoList.get(id);

    // NullPointerException ๋ฐฉ์ง€
    if (memo == null) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    // ํ•„์ˆ˜ ๊ฐ’์„ ๊ฒ€์ฆํ•ด์ค€๋‹ค. ์ œ๋ชฉ์€ ํ•„์ˆ˜์ง€๋งŒ ๋‚ด์šฉ์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค.
    if (dto.getTitle() == null || dto.getContents() != null) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);  // ํ•„์ˆ˜ ๊ฐ’์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— BAD_REQUEST๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
    }

    // ์ œ๋ชฉ๋งŒ ์ˆ˜์ •ํ•œ๋‹ค.
    memo.updateTitle(dto);

    // ๋ฐ”๋€ Memo๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ MemoResponseDto ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์—…๋ฐ์ดํŠธ๋œ Memo๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
    return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.OK);

}

postman ํ…Œ์ŠคํŠธ

  • ์‹๋ณ„์ž์˜ ๋ฉ”๋ชจ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
  • ์‹๋ณ„์ž์˜ ๋ฉ”๋ชจ๊ฐ€ ์žˆ๊ณ  title์ด ์žˆ๋Š” ๊ฒฝ์šฐ
  • ์‹๋ณ„์ž์˜ ๋ฉ”๋ชจ๊ฐ€ ์žˆ๊ณ  contents๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ

7. ๋ฉ”๋ชจ ์‚ญ์ œ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ฉ”๋ชจ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. (DELETE)
    • ์‚ญ์ œํ•  memo์— ๋Œ€ํ•œ ์‹๋ณ„์ž id๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.
    • ์‚ญ์ œ๋  ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 404 NOT FOUND๋กœ ์„ค์ •ํ•œ๋‹ค.
    • ์‘๋‹ต ๋ฐ์ดํ„ฐ๋Š” ์—†์–ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.
      • ์‘๋‹ต ์ƒํƒœ์ฝ”๋“œ๋Š” 200 OK๋กœ ์„ค์ •ํ•œ๋‹ค.

๋ฉ”๋ชจ ๋‹จ๊ฑด ์‚ญ์ œ API ๊ตฌํ˜„ (DELETE)

@DeleteMapping("/{id}")  // ์‹๋ณ„์ž๋กœ id๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
public ResponseEntity<Void> deleteMemo(@PathVariable Long id) {  // ๋Œ€๋ฌธ์ž Void๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.

    // memoList์˜ key๊ฐ’์— id๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์‚ญ์ œํ•œ๋‹ค.
    if (memoList.containsKey(id)) {
        memoList.remove(id);  // memoList์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ฐ’ ์‚ญ์ œ -> id์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ

        return new ResponseEntity<>(HttpStatus.OK);
    }

    // id ๊ฐ’์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ NOT_FOUND๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}

postman ํ…Œ์ŠคํŠธ

  • ์‚ญ์ œํ•  Memo๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ
  • ์‚ญ์ œํ•  Memo๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ

ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์ 

  • ์‹ค์ œ ๋ฌธ์ œ์˜ ์›์ธ์„ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด ์ „๋‹ฌ ๋ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.
    • ์‘๋‹ต ์ฝ”๋“œ๊ฐ€ ์„ธ๋ถ„ํ™”๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค. (์„ฑ๊ณต ์‹œ ๋ชจ๋‘ 200 OK)
    • ์ ์ ˆํ•œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. (์‹คํŒจ ์‹œ ๋ชจ๋‘ 500 Error ๋ฐœ์ƒ)

๋ฌธ์ œ์ 

  • Controller์— ์ฑ…์ž„์ด ๋„ˆ๋ฌด ๋งŽ๋‹ค. (์š”์ฒญ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ์‘๋‹ต, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋“ฑ)
  • ์„œ๋ฒ„๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„ ๋‹ค์‹œ ์ผœ์ง€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

 

์˜ค๋Š˜ ํ•˜๋ฃจ ์ •๋ฆฌ

์Šคํ”„๋ง 5์ฃผ์ฐจ ๊ฐ•์˜๋ฅผ ๋“ฃ๋Š”๋‹ค๊ณ  ์‹œ๊ฐ„์ด ๋‹ค ๊ฐ„ ํ•˜๋ฃจ์˜€๋‹ค...
์‹ค์Šต ๋ถ€๋ถ„์„ ๋†“์น˜์ง€ ์•Š๊ณ  ๋“ฃ๊ธฐ ์œ„ํ•ด์„œ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌ์™€ ํ•จ๊ป˜ ์ง„ํ–‰ํ–ˆ๋Š”๋ฐ ์‹œ๊ฐ„์ด ์ƒ๊ฐ๋ณด๋‹ค ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ ค์„œ ์˜ค๋Š˜ ํ•˜๋ฃจ๋ฅผ ์Šคํ”„๋ง ๊ฐ•์˜ ๋“ฃ๊ณ  ์ •๋ฆฌํ•˜๋Š”๋ฐ ๋‹ค ์‚ฌ์šฉํ–ˆ๋‹ค. ๋ฌผ๋ก  ์ •๋ฆฌ์™€ ํ•จ๊ป˜ ํ•˜๋ฉด์„œ ์ดํ•ด๋˜๋Š” ๋ถ€๋ถ„๋„ ๋งŽ์ด ์ƒ๊ฒผ๊ณ  ๋ญ”๊ฐ€ ์‚ด์ง ์Šคํ”„๋ง์— ๋Œ€ํ•œ ๋А๋‚Œ์ด ์žกํžˆ๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.
๋‚ด์ผ 6์ฃผ์ฐจ ๊ฐ•์˜๊นŒ์ง€ ๋ชจ๋‘ ๋“ฃ๊ณ  ๋‚˜๋ฉด ์Šคํ”„๋ง ๊ฐœ์ธ ๊ณผ์ œ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๋ฌด์กฐ๊ฑด ๋‚ด์ผ 6์ฃผ์ฐจ ๊ฐ•์˜๋ฅผ ๋‹ค ๋“ฃ๊ณ  ์ •๋ฆฌ๊นŒ์ง€ ์™„๋ฃŒํ•œ ํ›„์— ๋ชฉ์š”์ผ๋ถ€ํ„ฐ๋Š” ๊ฐœ์ธ ๊ณผ์ œ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ค€๋น„ํ•˜๊ณ  ์‹ถ๋‹ค!! ๊ทธ๋ž˜์•ผ ๋‹ค์Œ ์ฃผ ํ™”์š”์ผ๊นŒ์ง€ ์–ด๋А ์ •๋„ ์™„๋ฒฝํ•ด์ง„ ๊ณผ์ œ๋ฌผ์„ ์ œ์ถœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค!

์˜ค๋Š˜์€ ๋ญ”๊ฐ€ ํ‰์†Œ๋ณด๋‹ค ์ง‘์ค‘์ด ๋” ์ž˜๋œ ํ•˜๋ฃจ์—ฌ์„œ ์‹œ๊ฐ„ ๊ฐ€๋Š” ์ค„ ๋ชจ๋ฅด๊ณ  ํ•˜๋ฃจ๋ฅผ ๋ณด๋ƒˆ๋Š”๋ฐ ๋‚ด์ผ๋„ ๊ฐ•์˜์— ์ง‘์ค‘ํ•ด์„œ ์‹ค์Šต๊ณผ ์ •๋ฆฌ๋ฅผ ํ•จ๊ป˜ ํ•˜๋‹ค ๋ณด๋ฉด ํ•˜๋ฃจ๊ฐ€ ๊ธˆ๋ฐฉ ์ง€๋‚˜๊ฐˆ ๊ฒƒ ๊ฐ™์€ ๋А๋‚Œ์ด๋‹ค. 

๋‚ด์ผ ํ•˜๋ฃจ๋„ ์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ•ด ๋ณด์ž!!!!! ์Šคํ”„๋ง.. ๊ฐ์„ ์žก๊ณ  ๋งŒ๋‹ค!!

๋‚ด์ผ ๊ณ„ํš

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ(Java) 1๋ฌธ์ œ ํ’€์ด & ๋ธ”๋กœ๊ทธ ์ •๋ฆฌ
  • ์Šคํƒ ๋‹ค๋“œ๋ฐ˜ ์ˆ˜์ค€๋ณ„ ํ•™์Šต ๋“ฃ๊ธฐ
  • ์Šคํ”„๋ง 6์ฃผ์ฐจ ๊ฐ•์˜ ๋“ฃ๊ธฐ
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

+ ์ถ”๊ฐ€์ ์ธ ๊ณต๋ถ€ ๊ณ„ํš์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค~~