본문 바로가기
포트폴리오

친환경 쇼핑몰 프로젝트 구축하기: 백엔드 상품 관리 기능 구현 - 엔티티, 리파지토리, 서비스와 이미지 저장 방식 적용 (4)

by 플라퉁 2023. 6. 26.
728x90
반응형

 

 

 

 

이번에는 백엔드 상품 등록 및 변경 기능을 구현해보겠습니다.

 

먼저 상품 엔티티를 등록합니다.

 

import javax.persistence.*

@Entity
@Table(name = "products")
data class Product(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Long? = null,
        val name: String,
        val description: String,
        val price: Float,
        val imageUrl: String? = null
)

 

 

 

 

리파지토리 구현

 

import com.hsproject.envmarket.products.Product
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface ProductRepository: JpaRepository<Product, Long> {
    fun findByName(name: String): List<Product>
}

 

 

 

 

서비스 구현

 

import com.hsproject.envmarket.products.Product
import com.hsproject.envmarket.repository.ProductRepository
import org.springframework.stereotype.Service
import javax.persistence.EntityNotFoundException

@Service
class ProductService(private val productRepository: ProductRepository) {

    fun getAllProducts(): List<Product> = productRepository.findAll()

    fun getProductById(productId: Long): Product =
            productRepository.findById(productId).orElseThrow { EntityNotFoundException("Product not found") }

    fun getProductByName(productName: String): List<Product> {
        val products = productRepository.findByName(productName)
//        if (products.isNotEmpty()) {
//            return products
//        } else {
//            throw EntityNotFoundException("Product not found")
//        }
        return products
    }

    fun insertProduct(product: Product): Product {
        if (product.id == null || !productRepository.existsById(product.id)) {
            return productRepository.save(product)
        }
        throw Exception("Product already exist")
    }

    fun updateProduct(product: Product): Product {
        if (product.id == null || !productRepository.existsById(product.id)) {
            throw EntityNotFoundException("Product not found")
        }
        return productRepository.save(product)
    }
}

 

 

 

 

컨트롤러 구현

 

import com.hsproject.envmarket.products.Product
import com.hsproject.envmarket.service.ProductService
import com.hsproject.envmarket.service.StorageService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile

@RestController
@RequestMapping("/products")
@CrossOrigin("*")
class ProductController(private val productService: ProductService, private val storageService: StorageService) {

    //상품 전체 조회
    @GetMapping
    fun getAllProducts(): ResponseEntity<List<Product>> {
        val products = productService.getAllProducts()
        return ResponseEntity.ok(products)
    }

    // 상품 하나 조회
    @GetMapping("/{productId}")
    fun getProductById(@PathVariable productId: Long): ResponseEntity<Product> {
        val product = productService.getProductById(productId)
        return ResponseEntity.ok(product)
    }

    // 상품 이름으로 검색
    @GetMapping("/search")
    fun getProductByName(@RequestParam searchName: String): ResponseEntity<List<Product>> {
        val searchProduct = productService.getProductByName(searchName)
        return if (searchProduct.isNotEmpty()) {
            ResponseEntity.ok(searchProduct)
        } else {
            ResponseEntity.status(HttpStatus.NOT_FOUND).body(emptyList())
        }
    }

    //상품 등록
    @PostMapping("/enroll")
    fun productEnroll(
            @RequestParam("file") file: MultipartFile,
            @RequestParam("name") name: String,
            @RequestParam("description") description: String,
            @RequestParam("price") price: Float
    ): ResponseEntity<Product> {
        val imageUrl = storageService.storeFile(file)
        val product = Product(name = name, description = description, price = price, imageUrl = imageUrl)
        val savedProduct = productService.insertProduct(product)
        return ResponseEntity.ok(savedProduct)
    }

    //상품 이미지 업데이트
    @PostMapping("/{productId}/image")
    fun uploadImage(
            @PathVariable productId: Long,
            @RequestParam("file") file: MultipartFile
    ): ResponseEntity<Product> {
        val product = productService.getProductById(productId)
        val imageUrl = storageService.storeFile(file)
        val updatedProduct = product.copy(imageUrl = imageUrl)
        productService.updateProduct(updatedProduct)
        return ResponseEntity.ok(updatedProduct)
    }
}

 

 

 

 

스토리지 서비스 구현

 

import com.hsproject.envmarket.config.StorageProperties
import lombok.extern.slf4j.Slf4j
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import org.springframework.util.StringUtils
import org.springframework.web.multipart.MultipartFile
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

@Slf4j
@Service
class StorageService(private val storageProperties: StorageProperties) {

    val logger: Logger = LoggerFactory.getLogger(StorageService::class.java)

    private val uploadDir: Path = Paths.get(storageProperties.uploadDir)

    init {
        Files.createDirectories(uploadDir)
    }

    fun storeFile(file: MultipartFile): String {
        try {

            logger.info("경로 {}" , uploadDir)
            val filename = StringUtils.cleanPath(file.originalFilename!!)
            logger.info("파일 이름: {}", filename)

            val targetLocation = uploadDir.resolve(filename)
            logger.info("타겟 위치: {}", targetLocation)

            Files.createDirectories(uploadDir)
            Files.copy(file.inputStream, targetLocation, StandardCopyOption.REPLACE_EXISTING)
            logger.info("파일 저장 성공")

            val fileUrl = "/img/$filename"
            logger.info("저장된 파일 URL: {}", fileUrl)

            return fileUrl

        } catch (e: Exception) {
            logger.error("파일 저장 실패", e)
            throw e
        }
    }

}

 

 

 

 

이미지 파일을 저장할때 스토리지에 저장하고 불러올때는 DB의 url을 저장하여 불러내는 방식입니다.

 

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration

@Configuration
@ConfigurationProperties(prefix = "storage")
data class StorageProperties(
        var uploadDir: String = ""
)

 

이렇게 경로를 설정해줍니다. 해당경로는 application.yml에 프론트 UPLOAD PATH로 설정하여 

 

지정해주면 해당 폴더에서 URL로 찾을 수 있습니다.

 

 

 

자 다음에는 프론트에서 상품등록을 구현해보겠습니다.

 

 

 

 

 

728x90
반응형

댓글