스프링-aws s3 사용 이미지 업로드 예제-(2)코드 작성

이진우·2023년 8월 2일
0

스프링 학습

목록 보기
8/41

저번 포스트에서 세팅을 완료했었다.

저번에 완료된 세팅을 기반으로 스프링 코드를 작성하여 보겠다.

build.gradle에 세팅

implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.12.445'

또는

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

이런 식으로 세팅한다.

이제부터 작성할 코드는 둘 중에 아무거나 추가해도 상관없다.

application.properties

cloud.aws.credentials.accessKey=fasdfd..(저번에 IAM에서 받은 accessKey)
cloud.aws.credentials.secretKey=K96x...(저번에 IAM에서 받은 scretKey)
cloud.aws.s3.bucketName=ff..(저번에 만든 bucket이름)
cloud.aws.region.static=ap-northeast-2
cloud.aws.stack.auto=false

상황 설명

Member에 자기만의 이미지를 저장하는 식의 상황을 가정하고 실습하여 보겠다.

config

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {
    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;
    @Value("${cloud.aws.credentials.secretKey}")
    private String secretKey;
    @Value("${cloud.aws.s3.bucketName}")
    private String bucketName;
    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    public AmazonS3Client amazonS3Client(){
        BasicAWSCredentials basicAWSCredentials=new BasicAWSCredentials(accessKey,secretKey);

        return (AmazonS3Client) AmazonS3ClientBuilder.standard().withRegion(region).withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials)).build();
    }
}

주어진 accessKey와 secreyKey,region을 활용해서 AmazonS3Client를 빈에 등록하는 코드이다

Domain

Image:부모이미지 클래스
@Entity
@Getter
@Table(name = "image")
@DiscriminatorColumn
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Image {
   @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

   protected String originalName;

   protected String storedName;

   protected String accessUrl;

    private final static String[] extensionArr={"jpg","jpeg","bmp","gif","png"};
    //accessurl을 설정
    public void setAccessUrl(String accessUrl){
        this.accessUrl=accessUrl;
    }
    //이미지 파일의 확장자를 추출하는 메서드
    public String extractExtension(String originalName){
        int index=originalName.lastIndexOf('.');
        return originalName.substring(index+1);
    }
    public String generateStoreName(String originalName){
        String extension=extractExtension(originalName);
        if(!checkValidation(extension)) throw new RuntimeException(extension+" 은 지원하지 않는 확장자입니다");
        return UUID.randomUUID()+"."+extension;
    }
    //이미지 파일의 확장자를 통하여 유효한 이미지 파일인지 확인하는 메서드
    public boolean checkValidation(String extension){
        return Arrays.stream(extensionArr).anyMatch(value->value.equals(extension));
    }
}

3가지 요소가 필요하다

1)originalName:파일의 원본 이름

2)storedName:파일의 원본 이름이 중복될수 있으므로 새로운 이름을 만듦

3)accessUrl:s3에 의해서 저장된 이미지의 링크가 들어간다.

MemberImage
@Entity
@Getter
@Table(name = "memberImage")
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class MemberImage extends Image{
    @ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.PERSIST)
    @JoinColumn(name = "member_id")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Member member;

    public MemberImage(MultipartFile file){
        this.originalName=file.getOriginalFilename();
        this.storedName=generateStoreName(originalName);
        this.accessUrl="";
    }
    public void initMember(Member member){
        if(this.member==null) this.member=member;
    }
}

여러 이미지를 가질 수 있게 Member와 MemberImage는 다대 일 관계로 설정하였고

MemberImage의 생성자에 파일 매개 변수를 넣는다면 Image의 originalName과 storedName은 자동으로 설정, accessUrl은 일단 빈칸으로 냅둔다.

Repository

MemberRepository
import com.s3.s3practice.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member,Long> {
    public Member findByName(String name);
}

MemberRepository에서 member이름으로 member를 찾을 수 있게 하였다.

Service

ImageService
@Service
@RequiredArgsConstructor
public class ImageService {
    private final AmazonS3Client amazonS3Client;

    @Value("${cloud.aws.s3.bucketName}")
    private String bucketName;

    public String saveImage(MultipartFile file, String storedName) {
        try{
            ObjectMetadata metadata=new ObjectMetadata();
            metadata.setContentType(file.getContentType());
            metadata.setContentLength(file.getInputStream().available());

            amazonS3Client.putObject(new PutObjectRequest(bucketName,storedName,file.getInputStream(),metadata).withCannedAcl(CannedAccessControlList.PublicRead));
            return amazonS3Client.getUrl(bucketName,storedName).toString();
        }catch (IOException e){
            throw new RuntimeException(e);
        }
    }

}

위의 코드가 실질적으로 s3에 저장하는 코드이다.
https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3.html
여기서 putObject에 어떤 파라미터가 들어가는지 어떤 종류가 있는지 확인이 가능하고 실습이 가능하다!
위 코드에서 saveImage는 결국 이미지가 저장된 URL을 리턴한다.

@Service
@RequiredArgsConstructor
public class MemberService {
    private final ImageService imageService;

    // 회원의 프로필을 설정하는 로직
    @Transactional
    public void saveImage(MultipartFile file, Member member) {
        Image image =new MemberImage(file);
        String accessUrl=imageService.saveImage(file,image.getStoredName());
        image.setAccessUrl(accessUrl);
        member.saveImage(List.of((MemberImage)image));
    }

    public MemberShowDto showMember(Member member){
        MemberShowDto dto=new MemberShowDto(member.getName(),member.getImages().get(0).getAccessUrl());
        return dto;
    }

}

MemberService에서는 들어온 이미지를 s3에 저장후 accessUrl을 받아와서 image에 세팅하고 member와 연관관계를 맺어주는 saveImage 메서드와

Member를 파라미터로 받아서 member의 이름과 member의 이미지의 url링크를 가져오는 showMember라는 메서드가 있다.

Controller

MemberController
import com.s3.s3practice.domain.Member;
import com.s3.s3practice.dto.MemberShowDto;
import com.s3.s3practice.repository.MemberRepository;
import com.s3.s3practice.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/member")
public class MemberController {
    private final MemberService memberService;
    private final MemberRepository memberRepository;

    @PostMapping("/save")
    @ResponseStatus(HttpStatus.CREATED)
    public void saveMember(String name){
        Member member=new Member();
        member.setName(name);
        memberRepository.save(member);
    }


    @PostMapping("/save/image")
    @ResponseStatus(HttpStatus.OK)
    public void saveImage(@ModelAttribute MultipartFile file,String name) {
        Member member = memberRepository.findByName(name);
        memberService.saveImage(file, member);
    }

    @GetMapping("/show/member")
    @ResponseStatus(HttpStatus.OK)
    public MemberShowDto showmember(String name){
        Member member=memberRepository.findByName(name);
        return memberService.showMember(member);
    }
}

1)saveMember:말 그대로 Member의 이름을 받으면 memberrepository에 저장한다

2)saveImage:Member의 이름과 사진을 함께 보내면 그 이름을 가진 Member에 사진을 저장하는 로직

3)showmember:Member의 이름을 입력하면 멤버에 저장된 이름과 사진이 저장된 링크를 보내주는 로직

Dto

MemberShowDto
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class MemberShowDto {
    private String name;
    private String accessUrl;
}

이게 위 Controller의 MemberShowDto이다.

Postman을 통해서 테스트

1)
일단 jinu라는 이름을 가진 Member를 저장하였다.

2)
이렇게 보냈을 때 저장이 되었는지 확인해본다.

잘 들어왔고 사진을 클릭해서 확인해도 내가 보낸 사진이 맞다!

3)
이렇게 주소를 보내면 예상한대로 Member의 이름과 member의 사진이 저장된 accessUrl이 반환된다!

주의 할점 및 에러

다음 포스팅에 쓰겠지만
id 'org.springframework.boot' version '2.7.6'

스프링 부트 버젼 2.7.6 은 이렇게 잘만되는데 그 이상은

2023-08-02 00:40:23.165  WARN 19812 --- [nio-8080-exec-4] s.w.m.s.StandardServletMultipartResolver : Failed to perform cleanup of multipart items

java.io.UncheckedIOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.delete(DiskFileItem.java:431) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationPart.delete(ApplicationPart.java:53) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.springframework.web.multipart.support.StandardServletMultipartResolver.cleanupMultipart(StandardServletMultipartResolver.java:134) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.DispatcherServlet.cleanupMultipart(DispatcherServlet.java:1251) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1108) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:555) ~[tomcat-embed-core-9.0.78.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.29.jar:5.3.29]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) ~[tomcat-embed-core-9.0.78.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.29.jar:5.3.29]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.29.jar:5.3.29]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.29.jar:5.3.29]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.29.jar:5.3.29]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:661) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:427) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:357) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:294) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:373) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:237) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:319) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.io.IOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	... 43 common frames omitted

2023-08-02 00:40:23.165 ERROR 19812 --- [nio-8080-exec-4] o.apache.coyote.http11.Http11Processor   : Error processing request

java.io.UncheckedIOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.delete(DiskFileItem.java:431) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationPart.delete(ApplicationPart.java:53) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.Request.recycle(Request.java:475) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.io.IOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	... 13 common frames omitted

2023-08-02 00:40:23.174 ERROR 19812 --- [nio-8080-exec-4] o.a.coyote.http11.Http11NioProtocol      : Error reading request, ignored

java.io.UncheckedIOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.delete(DiskFileItem.java:431) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationPart.delete(ApplicationPart.java:53) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.Request.recycle(Request.java:475) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.CoyoteAdapter.log(CoyoteAdapter.java:494) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:420) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.io.IOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	... 13 common frames omitted

2023-08-02 00:40:23.180 ERROR 19812 --- [nio-8080-exec-4] org.apache.tomcat.util.net.NioEndpoint   : Error running socket processor

java.io.UncheckedIOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.delete(DiskFileItem.java:431) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.core.ApplicationPart.delete(ApplicationPart.java:53) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.Request.recycle(Request.java:475) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.CoyoteAdapter.log(CoyoteAdapter.java:494) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.catalina.connector.CoyoteAdapter.checkRecycled(CoyoteAdapter.java:517) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.http11.Http11Processor.recycle(Http11Processor.java:1417) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.release(AbstractProtocol.java:1129) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:1090) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.78.jar:9.0.78]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: java.io.IOException: Cannot delete C:\Users\LG PC\AppData\Local\Temp\tomcat.8080.15271313134344516925\work\Tomcat\localhost\ROOT\upload_b24af6ad_8b90_4288_992b_2b4343c125bd_00000002.tmp
	... 14 common frames omitted

2023-08-02 00:41:28.458  INFO 19812 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-08-02 00:41:28.460  INFO 19812 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-08-02 00:41:28.475  INFO 19812 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code 130

이런 에러가 뜬다. 어디에서? 윈도우에서만!

그래도 실행은 무리없이 되니 참고 가던지 버젼을 다운시키던지, 아니면 제가 못찾은 방법을 찾던지 하는게 유일한 해결책인것 같다. 혹시 찾으면 알려달라!

profile
기록을 통해 실력을 쌓아가자

0개의 댓글