스프링(Spring), 스프링부트(SpringBoot)/스프링(Spring) 기초

static file 처리와 FileUpload, JUnit & Spring-Test

개발학생 2022. 10. 12. 20:02
반응형

*22년 4월 한 달간 한국이러닝협회의 '실전 개발자를 위한 Spring Framework'를 수강하고 정리한 내용입니다

 

 

1. static file 처리와 FileUpload

1) Static Resource 처리

(1) Static Web Resource 처리하기

- 서버의 처리가 필요 없는 static web resources는 요청 시 서버를 거치지 않고 곧바로 응답해야 함

- 특정 URL로 요청이 오면 static resource로 인식하고 바로 응답 수행

 

(2) <mvc:resources mapping = "/resources/**" location = "/WEB-INF/resources/" />

- mapping: HTTP 요청 URL

- location: 실제 응답할 파일이 있는 위치

 

예시) 요청: http://localhost:8080/hello/resources/scripts/jQuery.js

         응답: /WEB-INF/resources/scripts/jQuery.js

 

2) 파일 업로드

(1) 파일 업로드 시 HTML 파일

<form method="post" enctype="multipart/form-data">
....
</form>

 

(2) 멀티파트 지원 기능 사용을 위해, MultipartResolver를 스프링 설정으로 등록

- MultipartResolver는 encType이 multipart/form-data 형식으로 데이터가 전송되었을 경우,
  해당 데이터를 Spring MVC에서 사용할 수 있도록 변환해준다.

<bean id="multipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    		<property name="maxUploadSize" value="104857600" /><!-- 100MB -->
            <property name="defaultEncoding" value="UTF-8" />
</bean
프로퍼티 타입 설명
maxUploadSize long 최대 업로드 가능한 바이트 크기.
-1은 제한이 없음을 의미한다.기본값은 -1이다.
maxInMemorySize int 디스크에 임시 파일을 생성하기 전에 메모리에 보관할 수 있는 최대 바이트 크기.
기본값은 10240이다.
defaultEncoding String 요청을 파싱할 때 사용할 캐릭터 인코딩.
지정하지 않을 경우, HttpServletRequest.setCharacterEncoding() 메서드로 지정한 캐릭터 셋이 사용된다. 아무 값도 없을 경우, ISO-8859-1을 사용한다.

 

(3) Dependency 추가

- CommonsMultipartResolver는 Apache Commons FileUpload를 사용

<dependency>
	<groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

 

- Form 작성

<form method="post" enctype="multipart/form-data" action="/bbs/upload">
	<input type="text" name="name" />
    <input type="file" name"file" />
    <input type="submit" value="전송" />
</form>

 

(4) Controller File Upload Logic 추가

@RequestMapping("/upload")
public String doUpload(@RequestParam("name") String name,
					@RequestParam("file") MultipartFile file,
                    			Model model {
if (!file.isEmpty()) {
			File tmpFile = new File("c:\\",file.getOriginal Filename());
            file.transferTo(tmpFile);
}

Model.addAttribute("fileNamek", name);
return "upload_ok";
}

 

(5) MultipartFile의 주요 메소드

프로퍼티 설명
String getName() 파라미터 이름을 구한다.
String getOriginalFileName() 업로드한 파일의 이름을 구한다.
Boolean isEmpty() 업로드한 파일이 존재하지 않는 경우 true를 리턴한다.
Long getSize() 업로드한 파일의 크기를 구한다.
Byte[] getBytes()
throws IOException
업로드한 파일의 데이터를 구한다.
InputStream getInputStream()
throws IOException
업로드한 파일 데이터를 읽어오는 InputStream을 구한다.
InputStream의 사용이 끝나면 알맞게 종료해주어야 한다.
void transferTo(File dest)
throws IOException
업로드한 파일 데이터를 지정한 파일에 저장한다.

 

(6) Command 객체로 받아오기

- 일반 HttpServlerRequest와 동일하게 MultipartFile도 Command 객체로 받아올 수 있음

- 멤버변수의 타입이 MultipartFile로 선언되어야 함

private String name;
private MultipartFile file;

public String getName() {
		return name;
}
public void setName(String name) {
		this.name = name;
}

public MultipartFile getFile() {
		return file;
}

public void setFile(MultipartFile file) {
		this.file = file;
}

 

- 일반 HttpServlerRequest와 동일하게 MultipartFile도 Command 객체로 받아올 수 있음

- 멤버변수의 타입이 MultipartFile로 선언되어야 함

@RequestMapping("/doUpload")
public ModelAndView doUpload(UploadCommand command)
			throws illegalStateException, IOException {

MultipartFile uploadedFile = command.getFile();

if(!uploadedFile.isEmpty()) {
			File file = new File("c:\\", uploadedFile.getOriginalFilename());
}

ModelAndView view = new ModelAndView();
view.setViewName("test/fileUpload");
return view;

}

 

(7) 파일 저장 시 보안 사항

- 업로드 된 파일 이름을 그대로 사용해서 저장을 하게 되면, 추후 파일 다운로드 및 보안사항에 문제 발생

- 아래 표처럼, 파일 이름은 숨기고 실제 파일명은 난수화시켜 저장

Display File Name Real File NAme
Toad-trial.exe 812478112359871234
Eclipse.zip 1224433415312389711
Oracle.exe 18217481234781872

  * Display File Name과 Real file Name은 모두 Database에 저장되는 항목
  * 위의 파일들을 다운받으려면 Real File Name을 요청해야 한다.

 

2. JUnit

1) JUnit의 개요

- Java에서 독립된 단위 테스트(Unit Test)를 지원해주는 프레임워크

- 보이지 않고 숨겨진 단위 테스트를 끌어내어 정형화시켜, 단위 테스트를 쉽게 만들어줌

 

* 단위 테스트(Unit Test)란?
  -> 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차,

       즉, 모든 함수와 메소드에 대한 테스트 케이스(Test Case)를 작성하는 절차

 

2) Junit의 특징

- TDD의 창시자인 Kent Beck과 디자인 패턴 책의 저자인 Erich Gamma가 작성

- 단정(assert) 메소드로 테스트 케이스의 수행 결과 판별

   예) assertEquals(예상 값, 실제 값)

- jUnit4부터는 테스트를 지원하는 어노테이션 제공

어노테이션(Annotation) 설명
@Test @Test가 선언된 메소드는 테스트 수행하는 메소드가 됨
JUnit은 각각의 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 원칙으로 하므로, @Test마다 객체를 생성함
@Ignore @Ignore가 선언된 메소드는 테스트를 실행하지 않게 함
@Before @Before가 선언된 메소드는 @Test가 선언된 메소드가 실행되기 전에 반드시 실행됨
@Test 메소드에서 공통으로 사용하는 코드를 @Before 메소드에 선언하여 사용하면 됨
@After @After가 선언된 메소드는 @Test가 선언된 메소드가 실행된 후 실행됨
@BeforeClass @BeforeClass 어노테이션은 @Test가 선언된 메소드보다 먼저 한 번만 수행되어야 할 경우에 사용
@AfterClass @AfterClass 어노테이션은 @Test가 선언된 메소드보다 나중에 한 번만 수행되어야 할 경우에 사용

- 각 @Test 메소드가 호출할 때 마다 새로운 인스턴스를 생성하여 독립적인 테스트가 이루어지도록 함

 

3) 테스트 결과를 확인하는 단정(assert) 메소드

*이외에도 다양한 assert 메소드 존재

: http://junit.sourceforge.net/javadoc/org/junit/Assert.html

assertEquals(a, b); 객체 a와 b의 값이 일치함을 확인한다.
assertArrayEquals(a, b); 배열 a와 b가 일치함을 확인한다.
assertSame(a, b); 객체 a와 b의 레퍼런스가 일치함을 확인한다.(==연산자)
assertTrue(a); 조건 a가 참인지 확인한다.
assertNotNull(a); 객체 a가 null이 아님을 확인한다.

 

3. Spring-Test

- Spring-Test에서 테스트를 지원하는 어노테이션(Annotation)

@RunWith(SpringJUnit4ClassRunner.class) - JUnit 프레임워크의 테스트 실행방법을 확장할 때 사용
- SpringJUnit4ClassRunner라는 클래스를 지정해주면 JUnit이 테스트 진행 도중에 ApplicationContext를 만들고 관리하는 작업을 진행해줌
- 각각의 테스트별로 객체가 생성되더라도 싱글톤(Singleton)의 ApplicationContext를 보장함
@ContextConfiguration - 스프링 빈(Bean) 설정 파일의 위치를 지정할 때 사용
@Autowired - 스프링 DI에서 사용됨 (특별함)
- 해당 변수에 자동으로 빈(Bean)을 매핑해줌
- 스프링 빈(Bean) 설정 파일을 읽기 위해 굳이 GenericXmlApplicationContext를 사용할 필요 없음
반응형