포스트

2022-07-13-TIL

Today I Learned

파일 확장자 및 용량 검증

파일 업로드를 받을 때는 크기와 종류를 모두 검증해야 한다. 크기 제한이 없으면 큰 파일 하나로 디스크와 메모리를 채울 수 있고, 종류를 확인하지 않으면 서버에서 실행될 수 있는 파일이 올라올 수 있다.

용량은 Spring Boot 설정으로 먼저 막는다. Spring Boot 문서에 따르면 기본값은 파일 하나당 1MB, 요청 하나에 담긴 파일 데이터 합계 10MB이고, MultipartProperties가 노출하는 속성으로 바꿀 수 있다.

1
2
3
4
# 파일 하나의 최대 크기
spring.servlet.multipart.max-file-size=5MB
# 요청 전체(여러 파일 합계)의 최대 크기
spring.servlet.multipart.max-request-size=20MB

두 값의 차이는 단위다. max-file-size는 파일 하나, max-request-size는 멀티파트 요청 전체에 대한 제한이다. 파일 여러 개를 한 번에 받는다면 max-request-size를 max-file-size보다 크게 잡아야 한다.

확장자와 파일 종류는 코드로 검증한다. OWASP File Upload Cheat Sheet의 권고는 다음과 같다.

  • 업무에 필요한 확장자만 허용 목록(allowlist)으로 둔다. 차단 목록은 .jpg.php 같은 이중 확장자, .php%00.jpg 같은 널 바이트, .phtml, .jspx 같은 대체 확장자로 우회된다.
  • Content-Type 헤더는 클라이언트가 조작할 수 있으므로 그대로 믿지 않고 파일 내용으로 종류를 확인한다.
  • 저장할 파일 이름은 애플리케이션이 새로 만들고, 이름 길이와 허용 문자를 제한한다.
  • 파일은 웹 루트 밖이나 별도 서버에 저장한다.

  • https://passionha.tistory.com/214
  • https://zgundam.tistory.com/72
  • https://maxcomfem.tistory.com/54
  • https://bonoken.tistory.com/162
  • https://dailyheumsi.tistory.com/163
  • https://velog.io/@park2348190/MultipartProperties%EC%9D%98-max-file-size-max-request-size%EC%9D%98-%EC%B0%A8%EC%9D%B4

스레드 로컬 vs 레디스

둘 다 “요청 처리 중에 어떤 값을 들고 다니는” 용도로 언급되지만 범위가 전혀 다르다.

ThreadLocal은 스레드마다 독립적으로 초기화된 자기만의 값을 가지는 변수다. 같은 ThreadLocal을 여러 스레드가 써도 각자 자기 값만 본다. 그래서 한 요청을 한 스레드가 처리하는 서블릿 환경에서 로그인 사용자 정보나 트랜잭션 같은 요청 범위의 값을 메서드 파라미터로 넘기지 않고 꺼내 쓸 때 유용하다. 대신 값은 그 JVM의 그 스레드 안에만 있다.

Redis는 별도 서버에 있는 저장소라서 여러 애플리케이션 서버가 같은 값을 공유할 수 있다. 서버가 여러 대일 때 로그인 세션을 어느 서버로 요청이 가든 찾을 수 있게 하려면 Redis 같은 공유 저장소가 필요하다. 그 대신 매번 네트워크를 타므로 ThreadLocal보다 느리다.

구분ThreadLocalRedis
범위한 JVM의 한 스레드여러 서버가 공유
수명보통 요청 하나TTL을 정해 요청 너머까지
비용메모리 접근네트워크 왕복

ThreadLocal을 쓸 때 주의할 점은 스레드 풀이다. Javadoc에 따르면 각 스레드는 자기 복사본에 대한 참조를 스레드가 살아 있는 동안 유지한다. 톰캣처럼 스레드를 재사용하는 환경에서 요청이 끝날 때 remove()를 하지 않으면, 다음 요청이 이전 요청의 값을 보게 된다. 필터나 인터셉터의 마지막 단계에서 반드시 지운다.

  • https://javacan.tistory.com/entry/ThreadLocalUsage

몽고DB

MongoDB는 데이터를 JSON과 비슷한 문서(document) 형태로 저장하는 문서 데이터베이스다. 스키마가 유연해서 애플리케이션 코드의 객체 구조와 비슷하게 데이터를 모델링할 수 있고, 데이터 모델을 다운타임 없이 바꿔 갈 수 있다는 점을 내세운다. 반대로 RDB처럼 스키마가 데이터 형식을 강제하지 않으므로, 문서마다 필드가 달라지지 않도록 애플리케이션 쪽에서 관리해야 한다.

같이 저장해 둔 링크 두 개는 모니터링에 관한 글이다. 하나는 서버, 데이터베이스, 클라우드 서비스를 모니터링하는 SaaS인 Datadog을 소개하는 글이고, 다른 하나는 APM 제품 제니퍼를 도입해 WAS와 DB를 모니터링한 사례다. 사례 글은 도입 후 서버 장애 평균 대응 시간이 2~3시간에서 10분 이내로 줄었다고 적고 있다.

  • https://www.44bits.io/ko/keyword/datadog
  • https://jennifersoft.com/ko/blog/tech/2018-02-19/#:~:text=%EC%98%AC%ED%95%B4%20%EC%B4%88%20%EB%91%90%EB%B2%88%EC%A7%B8%20%EC%84%9C%EB%B9%84%EC%8A%A4%EA%B0%80,TPS%20%EA%B9%8C%EC%A7%80%20%EB%B0%9C%EC%83%9D%ED%95%98%EA%B3%A0%20%EC%9E%88%EB%8B%A4.
참고한 자료외부 출처 5

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다