







@Transactional(rollbackFor = [Exception::class])
    suspend fun createContentsMulti(dto: ContentsDTO.CreateMultiReqDTO, fileConvertUtil: FileConvertUtil, signDTO: SignDTO): List<ContentsDTO> {
        val resList = mutableListOf<ContentsDTO>()

        val deferredList = dto.modelList!!.map { elem ->
            GlobalScope.async {
                val modelS3FileName = UUID.randomUUID().toString()
                var modelS3TempPath = modelTempPrefix + modelS3FileName

                elem.model?.let {
                    val model = elem.model!!
                    val fileName = elem.model!!.originalFilename

                    try {
                        if (fileConvertUtil.isNotGlb(fileName!!)) {
                            logger.info("Not GLB: ${fileName} converting...")
                            fileConvertUtil.convert(model, modelS3TempPath, ContentsFileFormatType.GLB2)
                        } else {
                            logger.info("GLB: ${fileName} uploading...")
                            s3Service.upload(model, modelS3TempPath)
                        }

                        elem.modelInfo?.let {
                            val modelInfo = elem.modelInfo!!
                            modelInfo.modelS3TempPath = modelS3TempPath

                            val createdDto = withContext(coroutineContext) {
                                createContents(modelInfo, signDTO)
                            }

                            resList.add(createdDto!!)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
        }

        runBlocking {
            withTimeoutOrNull(Duration.ofSeconds(uploadTimeout).toMillis()) {
                deferredList.awaitAll()
            }
        }
        return resList
    }

@PostMapping("/multi")
    fun createContentsMulti(@ModelAttribute @Valid dto: ContentsDTO.CreateMultiReqDTO,
                            @AuthenticationPrincipal signDTO: SignDTO): DeferredResult<ResponseEntity<CommonMsg>> {
        val delayedResult = DeferredResult<ResponseEntity<CommonMsg>>()
        val scope = CoroutineScope(Dispatchers.Default)

        scope.launch {
            val contentsDTOList = contentsService.createContentsMulti(dto, fileConvertUtil, signDTO)

            delayedResult.setResult(CommonMsg.ok(converter.dtoToCreateResList(contentsDTOList)))
        }

        return delayedResult
    }

이 서비스 함수하고 컨트롤러 함수를 분석해서 여러 파일들을 s3에 업로드 하는 동안