[Playground] Spring 기본 CRUD API

Daeya·6일 전

Playground

목록 보기
1/7

REST API로 메모 Create / Read / Update / Delete

GET /api/memos
POST /api/memos
PUT /api/memos/{id}
DELETE /api/memos/{id}

Playground라는 프로젝트를 만들고 메모 API를 먼저 만들었다.
Delete는 DB에서 행을 지우지 않고 soft delete (DEL_YN = 'Y')로 처리.


1. DBeaver에서 테이블 + CRUD 쿼리 확인

테이블

CREATE TABLE MEMO (
    ID          INT          NOT NULL PRIMARY KEY,
    TITLE       VARCHAR(200) NOT NULL,
    CONTENT     VARCHAR(500) NOT NULL,
    STATUS      VARCHAR(20)  NOT NULL DEFAULT 'READY',
    CREATED_AT  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UPDATED_AT  DATETIME     NULL,
    DEL_YN      CHAR(1)      NOT NULL DEFAULT 'N'
);

Read (목록)

SELECT ID      as 'id'
     , TITLE   as 'title'
     , CONTENT as 'content'
     , STATUS  as 'status'
  FROM MEMO
 WHERE DEL_YN = 'N'
 ORDER BY ID;

Create

INSERT INTO MEMO (ID, TITLE, CONTENT, STATUS)
VALUES (
  (SELECT COALESCE(MAX(ID), 0) + 1 FROM MEMO),
  'DBeaver에서 추가', '수동 INSERT 테스트', 'READY'
);

Update

UPDATE MEMO
   SET TITLE = '수정된 제목'
     , CONTENT = '수정된 내용'
     , STATUS = 'ING'
     , UPDATED_AT = CURRENT_TIMESTAMP
 WHERE ID = 1;

Delete (soft delete)

UPDATE MEMO
   SET DEL_YN = 'Y'
     , UPDATED_AT = CURRENT_TIMESTAMP
 WHERE ID = 4
   AND DEL_YN = 'N';

DELETE SQL이 아니라
삭제시, UPDATE DEL_YN = 'Y'
목록 조회 시 기본적으로 다 WHERE DEL_YN = 'N' 조건을 달아 삭제된 것은 안 보이게 함


2. MemoVO

private int id;
private String title;
private String content;
private String status;
private String createdAt;
private String updatedAt;
private String delYn;
// getter / setter

시작하는 단계에서 간소화 하고싶었지만,
기본적으로 거의 사용하는 createdAt, updatedAt, delYn은 습관처럼 추가하는 것이 좋을 것 같았다.


3. Mapper.xml

selectMemoList

<select id="selectMemoList" resultType="MemoVO">
    SELECT ID         AS "id"
         , TITLE      AS "title"
         , CONTENT    AS "content"
         , STATUS     AS "status"
         , CREATED_AT AS "createdAt"
         , UPDATED_AT AS "updatedAt"
         , DEL_YN     AS "delYn"
      FROM MEMO
     WHERE DEL_YN = 'N'
     ORDER BY ID
</select>

insertMemo

<insert id="insertMemo" parameterType="MemoVO">
    INSERT INTO MEMO (ID, TITLE, CONTENT, STATUS)
    VALUES (
        (SELECT COALESCE(MAX(ID), 0) + 1 FROM MEMO),
        #{title}, #{content}, #{status}
    )
</insert>

updateMemo

<update id="updateMemo" parameterType="MemoVO">
    UPDATE MEMO
       SET TITLE = #{title}
         , CONTENT = #{content}
         , STATUS = #{status}
         , UPDATED_AT = CURRENT_TIMESTAMP
     WHERE ID = #{id}
</update>

deleteMemo (soft delete)

<delete id="deleteMemo" parameterType="int">
    UPDATE MEMO
       SET DEL_YN = 'Y'
         , UPDATED_AT = CURRENT_TIMESTAMP
     WHERE ID = #{id}
       AND DEL_YN = 'N'
</delete>

4. Mapper.java

List<MemoVO> selectMemoList(MemoVO param);
void insertMemo(MemoVO param);
void updateMemo(MemoVO param);
void deleteMemo(int id);

5. Service

public List<MemoVO> selectMemoList() {
    return memoMapper.selectMemoList(new MemoVO());
}

public void insertMemo(String title, String content, String status) {
    MemoVO memo = new MemoVO();
    memo.setTitle(title);
    memo.setContent(content);
    memo.setStatus(status);
    memoMapper.insertMemo(memo);
}

public void updateMemo(int id, String title, String content, String status) {
    MemoVO memo = new MemoVO();
    memo.setId(id);
    memo.setTitle(title);
    memo.setContent(content);
    memo.setStatus(status);
    memoMapper.updateMemo(memo);
}

public void deleteMemo(int id) {
    memoMapper.deleteMemo(id);
}

6. Controller

@RestController
@RequestMapping("/api/memos")
public class MemoApiController {

    @Resource(name = "memoService")
    private MemoService memoService;

    @GetMapping
    public List<MemoVO> list() {
        return memoService.selectMemoList();
    }

    @PostMapping
    public void insert(@RequestBody MemoVO memo) {
        memoService.insertMemo(memo.getTitle(), memo.getContent(), memo.getStatus());
    }

    @PutMapping("/{id}")
    public void update(@PathVariable int id, @RequestBody MemoVO memo) {
        memoService.updateMemo(id, memo.getTitle(), memo.getContent(), memo.getStatus());
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable int id) {
        memoService.deleteMemo(id);
    }
}
메서드URL역할
GET/api/memos목록 조회
POST/api/memos생성
PUT/api/memos/{id}수정
DELETE/api/memos/{id}삭제 (soft)

7. Postman으로 확인

Read

GET http://localhost:8080/playground/api/memos

Create

POST http://localhost:8080/playground/api/memos

{
  "title": "새 메모",
  "content": "내용",
  "status": "READY"
}

Update

PUT http://localhost:8080/playground/api/memos/1

{
  "title": "수정 제목",
  "content": "수정 내용",
  "status": "ING"
}

Delete

DELETE http://localhost:8080/playground/api/memos/4

삭제 후 GET 다시 호출 → 해당 id는 목록에 안 나옴 (DB에는 DEL_YN = 'Y'로 남음)


정리

기능

  • GET /api/memos → 삭제 안 된 메모 목록
  • POST /api/memos → 메모 생성
  • PUT /api/memos/{id} → 메모 수정
  • DELETE /api/memos/{id} → soft delete

흐름 (요청 → DB)

Controller: HTTP 메서드 + URL
→ Service: MemoVO 조립
→ Mapper: select / insert / update / delete
→ XML: WHERE DEL_YN = 'N', soft delete는 UPDATE DEL_YN = 'Y'
→ DB

만든 순서 (DB → 요청)

  1. DBeaver: 테이블 + CRUD 쿼리
  2. MemoVO
  3. Mapper.xml: select / insert / update / delete
  4. Mapper.java
  5. Service
  6. Controller
  7. Postman: GET → POST → PUT → DELETE

참고

profile
Daeya

1개의 댓글

comment-user-thumbnail
어제

삭제정책은 고민할 부분이 많은 것 같습니다.. DEL_YN으로 처리하시는군요! 좋은 글 잘 읽고 갑니닷!

답글 달기