1. 이전 포스팅

 

https://growingsaja.tistory.com/974

 

[Kotlin][SpringBoot3] Kopring 서버 실습 08 - 다양한 api 구현해보기 - get, post, put, delete method With path variabl

1. 이전 포스팅 https://growingsaja.tistory.com/973 [Kotlin][SpringBoot3] Kopring 서버 실습 07 - 소스코드 중간점검 리펙토링 : Controller - Service - Repository - En 1. 이전 포스팅 https://growingsaja.tistory.com/972 2. 현 상황

growingsaja.tistory.com

 

 

 

 

 

2. 목표

 

 - 추가로 data class를 선언해, 더 많은 User 데이터를 저장하고 각 기능에 필요한 entity를 추가로 더 만들어 가져다 쓸 수 있도록 개선합니다.

    -> 필자의 경우, last Modified, created at 정보를 추가했고 + 데이터 조회에 쓰이는 entity 외에도 유저 정보 수정에 쓰이는 entity 작성

 

 

 

 

 

3. data class 수정

 

 기존 User data class에 값 추가

 신규로 UpdateUserInfo data class 추가

 

// vim entities/User.kt

package com.example.practicekopring.entities

import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.mapping.Document
import java.time.LocalDateTime

@Document(collection = "users")
data class User(
    @Id
    val id: String? = null,
    var username: String? = null,
    var email: String? = null,
    var lastModifiedAt_KST: String? = null,  // 데이터 최종 편집 일시 추가
    var lastModifiedAt: LocalDateTime? = null,
    var createdAt_KST: String? = null,  // 데이터 초기 생성 일시 추가
    var createdAt: LocalDateTime? = null
)

data class UpdateUserInfo(
    val id: String? = null,
    val username: String? = null,
    val email: String? = null
)

 

 

 

 

 

4. 소스코드 수정

 

// vim services/UserService.kt

package com.example.practicekopring.services

import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.repositories.UserRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId

@Service
class UserService(private val userRepository: UserRepository) {


    // ...
    

    // 5-1. 사용자 업데이트
    fun updateUserWithBody(user: UpdateUserInfo): User? {
        val existingUser = userRepository.findById(user.id ?: "")
        val userToUpdate = existingUser.get()
        userToUpdate.username = user.username ?: userToUpdate.username
        userToUpdate.email = user.email ?: userToUpdate.email
        // 작업 일시 저장
        val currentTime = LocalDateTime.now()
        userToUpdate.lastModifiedAt = currentTime
        // 한국 일시 string 저장
        userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ")  // 데이터 최종 편집 일시 설정  // 데이터 최종 편집 일시 설정
        return userRepository.save(userToUpdate)
    }

   
// ...

 

// vim controllers/UserController.kt

package com.example.practicekopring.controllers

import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.services.UserService
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.PathVariable
import java.time.LocalDateTime


@RestController
@RequestMapping("/api/v1/users")
class UserController(private val userService: UserService) {


    // ...


    // 5-1. 사용자 업데이트 body 버전
    @PostMapping("/update-with-body")
    fun updateUserWithBody(
        @RequestBody user: UpdateUserInfo
    ): User? {
        val updatedUser = userService.updateUserWithBody(user)
        return updatedUser
    }


// ...

 

 

 

 

 

5. 결과 확인

 

 

 

 

 

 

6. 전체 소스코드 참고

 

// vim repositories/UserRepository.kt

package com.example.practicekopring.repositories

import com.example.practicekopring.entities.User
import org.springframework.data.mongodb.repository.MongoRepository

// UserRepository 인터페이스는 User 엔터티와 관련된 데이터베이스 작업을 위한 Repository입니다.
interface UserRepository : MongoRepository<User, String> {
    fun findByUsername(username: String): User?
    fun findByEmail(email: String): User?
    fun findByUsernameContaining(keyword: String): List<User>
    fun findByEmailContaining(keyword: String): List<User>
    fun findAllByOrderByUsernameAsc(): List<User>
}

 

// vim services/UserService.kt

package com.example.practicekopring.services

import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.repositories.UserRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId

@Service
class UserService(private val userRepository: UserRepository) {

    // 1. 모든 사용자 조회
    fun getAllUsers(): List<User> {
        return userRepository.findAll()
    }

    fun createUser(username: String, email: String): User {
        val user = User(username = username, email = email)
        // 현재 일시 instant로 저장
        val currentTime = LocalDateTime.now()
        user.createdAt = currentTime
        // 한국 시간으로 변경해서 저장
        user.createdAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ")  // 데이터 최종 편집 일시 설정
        return userRepository.save(user)
    }

    fun getUserByUsername(username: String): User? {
        return userRepository.findByUsername(username)
    }

    // 3. 사용자 이메일로 조회
    fun getUserByEmail(email: String): User? {
        return userRepository.findByEmail(email)
    }

    // 5. 사용자 업데이트
    fun updateUser(id: String, username: String, email: String): User? {
        val existingUser = userRepository.findById(id)
        if (existingUser.isPresent) {
            val userToUpdate = existingUser.get()
            userToUpdate.username = username
            userToUpdate.email = email
            // 작업 일시 저장
            val currentTime = LocalDateTime.now()
            userToUpdate.lastModifiedAt = currentTime
            // 한국 일시 저장
            userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ")  // 데이터 최종 편집 일시 설정
            return userRepository.save(userToUpdate)
        }
        return null
    }

    // 5-1. 사용자 업데이트
    fun updateUserWithBody(user: UpdateUserInfo): User? {
        val existingUser = userRepository.findById(user.id ?: "")
        val userToUpdate = existingUser.get()
        userToUpdate.username = user.username ?: userToUpdate.username
        userToUpdate.email = user.email ?: userToUpdate.email
        // 작업 일시 저장
        val currentTime = LocalDateTime.now()
        userToUpdate.lastModifiedAt = currentTime
        // 한국 일시 string 저장
        userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ")  // 데이터 최종 편집 일시 설정  // 데이터 최종 편집 일시 설정
        return userRepository.save(userToUpdate)
    }

    // 6. 사용자 삭제
    fun deleteUser(id: String) {
        userRepository.deleteById(id)
    }

    // 7. 사용자 카운트 조회
    fun getUserCount(): Long {
        return userRepository.count()
    }

    // 8. 사용자 이름으로 부분 일치 검색
    fun searchUsersByUsername(keyword: String): List<User> {
        return userRepository.findByUsernameContaining(keyword)
    }

    // 9. 사용자 이메일로 부분 일치 검색
    fun searchUsersByEmail(keyword: String): List<User> {
        return userRepository.findByEmailContaining(keyword)
    }

    // 10. 사용자 정렬 조회 (예: 이름 오름차순)
    fun getUsersSortedByName(): List<User> {
        return userRepository.findAllByOrderByUsernameAsc()
    }

    // 11. 특정 페이지의 사용자 조회 (페이징)
    fun getUsersByPage(page: Int, size: Int): Page<User> {
        val pageable: Pageable = PageRequest.of(page, size)
        return userRepository.findAll(pageable)
    }
}

 

// vim controllers/UserController.kt

package com.example.practicekopring.controllers

import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.services.UserService
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.PathVariable
import java.time.LocalDateTime


@RestController
@RequestMapping("/api/v1/users")
class UserController(private val userService: UserService) {

    // 1. 모든 사용자 조회
    @GetMapping("/")
    fun getAllUsers(): List<User> {
        return userService.getAllUsers()
    }

    // 2. 사용자 생성
    @PostMapping("/create")
    fun createUser(
        @RequestParam username: String,
        @RequestParam email: String
    ): User {
        return userService.createUser(username, email)
    }

    // 3. 사용자 이름으로 조회
    @GetMapping("/by-username")
    fun getUserByUsername(
        @RequestParam username: String
    ): User? {
        return userService.getUserByUsername(username)
    }

    // 4. 사용자 이메일로 조회
    @GetMapping("/by-email")
    fun getUserByEmail(
        @RequestParam email: String
    ): User? {
        return userService.getUserByEmail(email)
    }

    // 5. 사용자 업데이트
    @PutMapping("/{id}/update")
    fun updateUser(
        @PathVariable id: String,
        @RequestParam email: String,
        @RequestParam username: String
    ): User? {
        val updatedUser = userService.updateUser(id, username, email)
        return updatedUser
    }

    // 5-1. 사용자 업데이트 body 버전
    @PostMapping("/update-with-body")
    fun updateUserWithBody(
        @RequestBody user: UpdateUserInfo
    ): User? {
        val updatedUser = userService.updateUserWithBody(user)
        return updatedUser
    }

    // 6. 사용자 삭제
    @DeleteMapping("/{id}/delete")
    fun deleteUser(
        @PathVariable id: String
    ) {
        userService.deleteUser(id)
    }

    // 7. 사용자 카운트 조회
    @GetMapping("/count")
    fun getUserCount(): Long {
        return userService.getUserCount()
    }

    // 8. 사용자 이름으로 부분 일치 검색
    @GetMapping("/search-by-username")
    fun searchUsersByUsername(
        @RequestParam keyword: String
    ): List<User> {
        return userService.searchUsersByUsername(keyword)
    }

    // 9. 사용자 이메일로 부분 일치 검색
    @GetMapping("/search-by-email")
    fun searchUsersByEmail(
        @RequestParam keyword: String
    ): List<User> {
        return userService.searchUsersByEmail(keyword)
    }

    // 10. 사용자 정렬 조회 (예: 이름 오름차순)
    @GetMapping("/sorted")
    fun getUsersSortedByName(): List<User> {
        return userService.getUsersSortedByName()
    }

    // 11. 특정 페이지의 사용자 조회 (페이징)
    @GetMapping("/paged")
    fun getUsersByPage(
        @RequestParam page: Int,
        @RequestParam size: Int
    ): Page<User> {
        return userService.getUsersByPage(page, size)
    }
}

 

 

 

+ Recent posts