2026.09.08

Memory Calendar 개발(6) - 인증 사용자 기준 Note CRUD 구현

지난 편에서는 JWT를 검증하고 보호된 API에 접근하는 흐름을 구성했다. 이번에는 인증 정보를 실제 기능에 연결해 메모를 작성하고 관리할 수 있도록 했다.

Note는 사용자의 기록을 저장하는 공간이면서, 이후 AI가 일정 정보를 추출할 때 사용할 원본 데이터이기도 하다.

1. Note 도메인 구성

메모에 필요한 정보는 간단하게 구성했다.

  • user: 메모 작성자
  • content: 메모 내용
  • createdAt, updatedAt: 생성·수정 시각

한 사용자가 여러 메모를 작성할 수 있으므로 각 Note가 User를 참조하도록 했다. User에는 List<Note>를 추가하지 않았다. 현재는 Repository에서 사용자별 메모를 조회하면 충분했기 때문이다.

메모 생성은 작성자와 내용을 함께 전달하는 정적 팩토리 메서드로 구성했다.

public static Note of(User user, String content) {
    return new Note(user, content);
}

작성자는 JWT 인증 정보에서 가져온 사용자 ID로 연결한다. 이렇게 생성한 메모는 로그인한 사용자의 기록으로 저장된다.

2. 사용자 소유권 확인

로그인한 사용자라도 다른 사람의 메모에 접근할 수 있어서는 안 된다. 그래서 메모를 조회할 때 현재 사용자 ID를 조건에 포함했다.

Optional<Note> findByIdAndUserId(Long noteId, Long userId);

이 조회 조건을 단건 조회뿐 아니라 수정과 삭제에도 사용했다.

  • 메모 ID와 현재 사용자 ID가 모두 일치해야 조회된다.
  • 수정과 삭제는 자신의 메모를 조회한 뒤 진행한다.
  • 존재하지 않거나 다른 사용자의 메모라면 404 / NOTE_001을 반환한다.

JWT로 요청한 사용자를 확인하고, 조회 조건으로 메모의 소유권까지 확인하도록 구성한 것이다.

3. 메모 CRUD 구현

API는 작성·목록·단건 조회·수정·삭제로 나눴다.

POST   /api/notes
GET    /api/notes?page=0&size=20
GET    /api/notes/{noteId}
PATCH  /api/notes/{noteId}
DELETE /api/notes/{noteId}

DB 상태를 변경하는 작업에는 @Transactional을 적용했다.

  • 생성: 인증된 사용자와 메모 내용을 연결해 저장한다.
  • 수정: 조회한 Note의 내용을 변경하고 JPA Dirty Checking으로 반영한다.
  • 삭제: 자신의 메모인지 확인한 뒤 삭제한다.

생성과 수정 요청에는 내용 검증도 추가했다.

@NotBlank(message = "메모 내용은 필수입니다.")

빈 문자열이나 공백만 전달하면 400 Bad Request로 처리한다.

4. Slice 기반 목록 조회

메모 목록은 나중에 무한 스크롤로 보여주는 것을 고려했다. 전체 메모 개수보다 다음에 가져올 데이터가 있는지가 중요해 Slice를 사용했다.

목록 응답은 다음 정보를 담는다.

  • content: 메모 목록
  • page, size: 현재 페이지와 요청 크기
  • hasNext: 다음 페이지 존재 여부

최근에 작성한 메모부터 볼 수 있도록 createdAt DESC로 정렬했다. 현재는 page와 size를 사용하는 offset 방식으로 시작하고, 데이터 규모가 커지면 Cursor Pagination을 검토할 예정이다.

5. 동작 확인

기본 기능과 함께 잘못된 요청, 다른 사용자의 접근도 확인했다.

  • 생성 201, 조회·수정 200, 삭제 204
  • 빈 메모 내용은 400
  • 존재하지 않거나 다른 사용자의 메모는 404 / NOTE_001
  • 인증 없이 요청하면 401