- 2/1 - 전체 게시글 목록 조회 API
- [ ] 제목, 작성자명(nickname), 작성 날짜를 조회하기
- [ ] 작성 날짜 기준으로 내림차순 정렬하기
- 💬 2/2 - 게시글 작성 API
- [ ] 토큰을 검사하여, 유효한 토큰일 경우에만 게시글 작성 가능
- [ ] 제목(500자 까지 입력 가능), 작성 내용을 입력하기(5000자 까지 입력 가능)
- [ ] (챌린지 과제) 이미지 업로드 가능
- 💬 2/5 - 게시글 조회 API
- 제목, 작성자명(nickname), 작성 날짜, 작성 내용을 조회하기 (검색 기능이 아닙니다. 간단한 게시글 조회만 구현해주세요.)
- 💬 2/6 - 게시글 수정 API
- 토큰을 검사하여, 해당 사용자가 작성한 게시글만 수정 가능
- 💬 2/7 - 게시글 삭제 API
- [ ] 토큰을 검사하여, 해당 사용자가 작성한 게시글만 삭제 가능
이제 이것들을 만들어야 한다. 빨리 끝내고 다음 인강을 들을 시간을 내자!!
package com.example.demo.model
import jakarta.persistence.*
import java.time.LocalDateTime
@Entity
@Table(name = "post")
class Post(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null,
@Column(name = "title", nullable = false)
var title: String,
@Column(name = "nickname", nullable = false)
var nickname: String,
@Column(name = "content", nullable = false)
var content: String,
@Column(name = "created_at", nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now()
)
들어가야 하는게 제목, 닉네임, 내용, 날짜이므로 이걸 넣고
package com.example.demo.dto
import java.time.LocalDateTime
data class PostDto(
val id: Long,
val title: String,
val nickname: String,
val content: String,
val createdAt: LocalDateTime
)
dto도 같은 내용들을 집어넣는다.
package com.example.demo.dto
data class PostCreateDto(
val title: String,
val nickname: String,
val content: String
)
만들때 필요한건 제목, 닉네임, 내용이고
package com.example.demo.dto
data class PostUpdateDto(
val title: String,
val content: String
)
수정은 제목과 내용
interface PostRepository : JpaRepository<Post, Long> {
fun findByTitleAndNickNameAndCreatedAt(title: String, nickName: String, createdAt: LocalDateTime): List<Post>
fun findAllByOrderByCreatedAtDesc(): List<Post>
}
이걸로 제목, 작성자명(nickname), 작성 날짜를 조회하기 이건 위에것, 작성 날짜 기준으로 내림차순 정렬하기 이건 밑이 담당한다.
그런데, dto를 수정하기로 했다.
data class PostDto(
val id: Long,
val title: String,
val nickname: String,
val content: String,
val createdAt: LocalDateTime
) {
companion object {
fun from(post: Post): PostDto {
return PostDto(
id = post.id!!,
title = post.title,
nickname = post.nickname,
content = post.content,
createdAt = post.createdAt
)
}
}
}
이러면 이제 서비스임플에서 일일이
override fun getAllPosts(): List<PostDto> {
val posts = postRepository.findAllByOrderByCreatedAtDesc()
return posts.map { post ->
PostDto(
id = post.id!!,
title = post.title,
nickname = post.nickname,
content = post.content,
createdAt = post.createdAt
)
}
}
이렇게 안하고
override fun getAllPosts(): List<PostDto> {
val posts = postRepository.findAllByOrderByCreatedAtDesc()
return posts.map { PostDto.from(it) }
}
이렇게 할수있다.
그리고 서비스도 fun getAllPosts(): List<PostDto>를 넣어준다.
interface PostService {
fun createPost(createPostRequest: PostCreateDto): Post
fun getPost(postId: Long): Post
fun getAllPosts(): List<PostDto>
fun updatePost(postId: Long, updatePostRequest: PostUpdateDto): Post
fun deletePost(postId: Long)
}
이제 리스트를 dto에서 가져오기 때문이다.
override fun createPost(createPostRequest: PostCreateDto, token: String): Post {
// 토큰 검사
val nickName = jwtPlugin.validateToken(token)
// 토큰에 담긴 닉네임으로 사용자 조회
val member = memberRepository.findByNickName(nickName.toString())
?: throw IllegalArgumentException("유효하지 않은 사용자입니다.")
// 제목과 내용의 길이 검사
if (createPostRequest.title.length > 500) {
throw IllegalArgumentException("제목은 500자를 초과할 수 없습니다.")
}
if (createPostRequest.content.length > 5000) {
throw IllegalArgumentException("내용은 5000자를 초과할 수 없습니다.")
}
// 게시글 작성
val post = Post(
title = createPostRequest.title,
nickname = member.nickName,
content = createPostRequest.content,
)
return postRepository.save(post)
}
이렇게 했는데 override가 빨갛다!
보니까 서비스에서
fun createPost(createPostRequest: PostCreateDto): Post 이게 작동 안하고 회색이였다.
fun createPost(createPostRequest: PostCreateDto, token: String): Post
토큰을 넣는다!
게시글 수정 API
- 토큰을 검사하여, 해당 사용자가 작성한 게시글만 수정 가능
override fun updatePost(postId: Long, updatePostRequest: PostUpdateDto, token: String): Post {
// 토큰 검사
val nickName = jwtPlugin.validateToken(token)
// 토큰에 담긴 닉네임으로 사용자 조회
val member = memberRepository.findByNickName(nickName.toString())
?: throw IllegalArgumentException("유효하지 않은 사용자입니다.")
// 게시글 조회
val post = postRepository.findById(postId)
.orElseThrow { IllegalArgumentException("해당 게시글이 존재하지 않습니다.") }
// 사용자 검사
if (post.nickname != member.nickName) {
throw IllegalArgumentException("본인이 작성한 게시글만 수정할 수 있습니다.")
}
// 게시글 수정
post.title = updatePostRequest.title
post.content = updatePostRequest.content
return postRepository.save(post)
}
이렇게 만들고
서비스에 토큰을 추가한다.
fun updatePost(postId: Long, updatePostRequest: PostUpdateDto, token: String): Post // 이 부분을 추가
@RestController
@RequestMapping("/posts")
class PostController(private val postService: PostService) {
@PostMapping
fun createPost(@RequestBody createPostRequest: PostCreateDto, @RequestHeader("Authorization") token: String): ResponseEntity<PostDto> {
val post = postService.createPost(createPostRequest, token)
val postDto = PostDto.from(post)
return ResponseEntity.ok().body(postDto)
}
@GetMapping("/{postId}")
fun getPost(@PathVariable postId: Long): ResponseEntity<PostDto> {
val post = postService.getPost(postId)
val postDto = PostDto.from(post)
return ResponseEntity.ok().body(postDto)
}
@GetMapping
fun getAllPosts(): ResponseEntity<List<PostDto>> {
val posts = postService.getAllPosts()
val postDtos = posts.map { PostDto.from(it) }
return ResponseEntity.ok().body(postDtos)
}
@PutMapping("/{postId}")
fun updatePost(@PathVariable postId: Long, @RequestBody updatePostRequest: PostUpdateDto, @RequestHeader("Authorization") token: String): ResponseEntity<PostDto> {
val post = postService.updatePost(postId, updatePostRequest, token)
val postDto = PostDto.from(post)
return ResponseEntity.ok().body(postDto)
}
@DeleteMapping("/{postId}")
fun deletePost(@PathVariable postId: Long, @RequestHeader("Authorization") token: String): ResponseEntity<Void> {
postService.deletePost(postId, token)
return ResponseEntity.noContent().build()
}
}