Spring Framework (11) 회원 삭제 및 파일 업로드 - Day 58

jaehoon ahn·2025년 12월 10일

Spring boot

목록 보기
9/20
post-thumbnail

회원 삭제


CREATE TABLE "MEMBER" (
	"MEMBER_NO" NUMBER NOT NULL,
	"MEMBER_EMAIL" NVARCHAR2(50) NOT NULL,
	"MEMBER_PW" NVARCHAR2(100) NOT NULL,
	"MEMBER_NICKNAME" NVARCHAR2(10) NOT NULL,
	"MEMBER_TEL" CHAR(11) NOT NULL,
	"MEMBER_ADDRESS" NVARCHAR2(300) NULL,
	"PROFILE_IMG" VARCHAR2(300) NULL,
	"ENROLL_DATE" DATE DEFAULT SYSDATE NOT NULL,
	"MEMBER_DEL_FL" CHAR(1) DEFAULT 'N' NOT NULL,
	"AUTHORITY" NUMBER DEFAULT 1 NOT NULL
);

⇒ 사용자는 바로 삭제하는 것이 아닌, MEMBER_DEL_FL(Delete Flag)를 수정함으로써,

스케줄러를 통해서 1달정도? 데이터를 갖고있다가 삭제를 해준다.

<update id="secession">
		UPDATE MEMBER
		SET MEMBER_DEL_FL = "Y"
		WHERE MEMBER_NO = #{memberNo}
	</update>

SessionStatus

**@SessionAttributes({"loginMember"})** // SessionStatus 사용하기 위함
@Controller
@RequestMapping("myPage")
@Slf4j
public class MyPageController {

	public String secession(@RequestParam("memberPw") String memberPw,
				@SessionAttribute("loginMember") Member loginMember, SessionStatus status, RedirectAttributes ra) {
		status.setComplete(); // 세션 비우기 (로그아웃 상태 변경)
		.
		.
	}
}

⇒ status는 @SessionAttributes와 함께 사용해야 한다.

input type = “file”

 <input type="file" name="uploadFile" />

enctype

[form태그의 enctype 속성]

          enctype 이란??
          - 데이터를 서버로 전송할 때 데이터의 형태(인코딩)를 지정하는 속성
          - 이미지를 제출할 때 처리하는 타입

          * application/x-www-form-urlencoded (기본값)
           - URL 인코딩된 "문자열" 로 서버에 제출

          * multipart/form-data  (무조건 POST에서만 동작)

           - 제출되는 여러 데이터 타입에 맞춰서 인코딩하여 제출
            문자열 -> String
            숫자   -> String -> int/double(Spring이 처리)
            파일   -> 2진 데이터

          * text/plain
           - 텍스트로 서버에 제출
  1. 클라이언트가 클라이언트의 컴퓨터에 있는 이미지를 업로드
  2. 서버가 클라이언트가 제출한 이미지를 받아서 서버 컴퓨터/호스팅 서비스(현재는 내 컴퓨터)

⇒ c드라이브에 uploadFiles에 클라이언트가 전달한 이미지를 저장할 것!

  • 클라이언트가 이미지 보여달라고 요청
    • 클라이언트가 프로필 업로드 요청 → c:/uploadFiles/profile/…에 존재할 것

    • img 태그 src “” 안에 들어가는 것이 이미지를 보여줘야되는 요청 경로

    • 하지만, c:/uploadFiles/profile/.. 경로를 그대로 쓰면 안된다.
      - 프로필 이미지를 화면에서 조회하는 요청은 /myPage/profile/마동석.jpg로 시작하는 요청으로 매핑해준다
      - → img src=”/myPage/profile/마동석.jpg”
      - /myPage/profile/ 이 요청을 c:/uploadFiles/profile/ 이 경로와 연결을 해서, 해당 c드라이브에서 찾아서 보여주면 된다.
      - ⇒ 경로 매핑과정 필요
      - 사용자가 게시판 이미지를 업로드 → c:/uploadFiles/board/에 저장
      - img src = ”/board/image/짱구.png” 게시판 이미지를 조회하고 싶다는 요청
      - /board/image/짱구.png ↔ c:/uploadFiles/board/ 경로와 연결을 해줘야 한다.

      ⇒ 해당 내용들을 FileConfig에 작성해줘야 한다.

      ⇒ Multipart Resolver 정의

      ⇒ config.properties에 작성하여 보안 강화

@Value

  • @Value : properties에 매핑된 키를 통해 value를 가져오는 어노테이션
@Value("${spring.servlet.miltipart.file-size-threshold}")

config.properties

# (참고)
# 1MB = 1024KB
# 1KB = 1024B

# 파일을 디스크에 쓸 때까지의 임계값
# 기본값 : 0B
# 50MB로 임계값을 변경
# => 임계값을 초과하면 그때부터 디스크에 업로드
# -> 업로드되는 파일의 크기 50MB 까지는 메모리에 임시로 저장하다가
# 초과시 디스크(HDD, SDD)에 저장
# 클라이언트가 이미지를 올리겠다고 요청을 보내면, 서버 컴퓨터 하드에 저장할 지 말지를 결정해야함
# 클라이언트가 요청을 보냈다고 해서 하드에 바로 넣어버리면 서버 컴퓨터에 부하가 일어남
# RAM에 저장하다가 임계값이 넘어버리면 그때 HDD, SDD에 저장
# 임계값은 바이트 단위로 저장

spring.servlet.miltipart.file-size-threshold=52428800
# file-size-threshold = 파일사이즈의 임계값을 의미 => 52428800 = 50MB

# 임계값이 초과가 되면, 디스크에 저장 -> 어느 경로에 저장할 지 정할 수 있음
# 즉, 파일의 임시 저장 경로를 지정
spring.servlet.multipart.location=C:/uploadFiles/temp/

# HTTP 요청당 최대 크기 지정
# 기본값 : 10MB
# => 50MB로 변경
spring.servlet.multipart.max-request-size=52428800

# 개별 파일당 최대 크기
# 기본값 : 1MB
# 10MB로 변경
spring.servlet.multipart.max-file-size=10485760

FileConfig.java

package edu.kh.project.common.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.unit.DataSize;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import jakarta.servlet.MultipartConfigElement;

@Configuration
@PropertySource("classpath:config.properties")
// 외부에 있는 properties를 가져오는 것
public class FileConfig implements WebMvcConfigurer {
	// WebMvcConfigurer : Spring MVC 프레임워크에서 제공하는
	// 인터페이스 중 하나로, 스프링 구성을 커스터마이징하고
	// 확장하기 위한 메서드를 제공함.
	// 주로 웹 애플리케이션의 설정을 조정하거나 추가하는데 사용됨

	// 파일 업로드 임계값
	// @Value : properties에 매핑된 키를 통해 value를 가져오는 어노테이션
	@Value("${spring.servlet.miltipart.file-size-threshold}")
	private long fileSizeThreshold; // 52428800

	// 임계값 초과시 파일의 임시 저장경로
	@Value("${spring.servlet.multipart.location}")
	private String location; // C:/uploadFiles/temp/
	// 요청당 파일 최대 크기
	@Value("${spring.servlet.multipart.max-request-size}")
	private long maxRequestSize; // 52428800

	// 개별 파일당 최대 크기
	@Value("${spring.servlet.multipart.max-file-size}")
	private long maxFileSize; // 10485760

	// 요청 주소에 따라
	// 서버 컴퓨터의 어떤 경로에 접근할 지 설정하는 메서드

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// ResourceHandlerRegistry :
		// Spring MVC에서 정적 리소스(이미지, CSS, JS 등)
		// 요청을 처리하기 위해 사용하는 클래스

		// URL 요청 패턴을 서버의 실제 파일 경로와 연결하여
		// 클라이언트가 특정 경로로 정적파일에 접근할 수 있도록 설정
		// 어떤 요청이 왔을 때 실행될지 정하는 것
		registry.addResourceHandler("/myPage/file/**").addResourceLocations("file:///C:/uploadFiles/test/");
		// 즉, /myPage/files/에 요청이 오면 C:/uploadFiles/test와 연결하겠다는 의미
		// -> 클라이언트가 /myPage/file/** 패턴으로 이미지를 요청할 때
		// 서버 폴더 경로 중 C:/uploadFiles/test/로 연결하겠다.
	}

	@Bean
	// MultipartResolver 설정
	public MultipartConfigElement configElement() {
		// MultipartConfigElement
		// 파일 업로드를 처리하는데 사용되는 MultipartConfigElement를
		// 구성을 하고 반환을 해주는 것(옵션 설정하는데 사용)
		// 업로드 파일의 최대 크기, 임시 저장경로 등등을 설정할 수 있게 해주는 객체
		MultipartConfigFactory factory = new MultipartConfigFactory();

		// 파일 업로드 임계값
		factory.setFileSizeThreshold(DataSize.ofBytes(fileSizeThreshold));
		// long타입으로 byte를 넣어야 함

		// 임시 저장 폴더 경로
		factory.setLocation(location);

		// HTTP 요청당 파일 최대 크기
		factory.setMaxRequestSize(DataSize.ofBytes(maxFileSize));

		// 개발 파일당 최대 크기
		factory.setMaxFileSize(DataSize.ofBytes(maxFileSize));

		return factory.createMultipartConfig();
	}

	// MultipartResolver 객체를 생성하여 Bean으로 등록
	// -> 위에서 만든 MultipartConfigElement를 자동으로 이용할 것
	@Bean
	public MultipartResolver multipartResolver() {
		// MultipartResolver : MultipartFile을 처리해주는 해결사
		// -> MultipartResolver는 클라이언트로부터 받은 multipart 요청을 처리하고,
		// 그 중 업로드된 파일을 추출하여 MultipartFile 객체로 제공하는 역할
		StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
		return multipartResolver;
	}
}

MyPageController.java

// 파일 테스트 화면으로 이동
	@GetMapping("fileTest")
	public String fileTest() {
		return "myPage/myPage-fileTest";
	}
.
.
@PostMapping("file/test1") // /myPage/file/test1 POST 요청 매핑
	public String fileUpload1(@RequestParam("uploadFile") MultipartFile uploadFile, RedirectAttributes ra) {
		// 파일이기 때문에, String 등이 아닌 MultipartFile 타입으로 정의한다

		String path = null;
		try {
			path = service.fileUpload1(uploadFile);
			// /myPage/file/파일명.jpg

			// 파일이 실제로 서버 컴퓨터에 저장이 되어
			// 웹에서 접근할 수 있는 경로가 반환되었을 때
			if (path != null) {
				ra.addFlashAttribute("path", path);
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.info("파일 업로드 예제1 중 예외 발생");
		}

		return "redirect:/myPage/fileTest";
	}

MyPageService.java

/**
	 * 파일 업로드 테스트1
	 */
	@Override
	public String fileUpload1(MultipartFile uploadFile) throws Exception {
		// uploadFile에 파일이 업로드 됐는지부터 확인
		if (uploadFile.isEmpty()) {
			// 업로드한 파일이 없을 경우(즉, 껍데기만 넘어온 경우)
			return null;
		}

		// 업로드한 파일이 있을 경우
		// C:/uploadFiles/test/파일명으로 서버에 저장
		uploadFile.transferTo(new File("C:/uploadFiles/test/" + uploadFile.getOriginalFilename()));
		// 하기와.jpg로 해당 경로에 저장하겠다는 의미

		// 웹에서 해당 파일에 접근할 수 있는 경로를 만들어 반환
		// 이미지가 최종 저장된 서버 컴퓨터상의 경로
		// C:/uploadFiles/test/파일명
		
		// 클라이언트가 브라우저에 해당 이미지를 보기위해 요청하는 경로
		// <img src="경로">
		// /myPage/file/파일명.jpg -> <img src="/myPage/file/파일명.jpg">
		
		return "/myPage/file/" + uploadFile.getOriginalFilename();
	}

⇒ 서버 컴퓨터인 C:/uploadFiles/test에 저장이 된것을 확인할 수 있다.

0개의 댓글