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보다 느리다.
| 구분 | ThreadLocal | Redis |
|---|---|---|
| 범위 | 한 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.
댓글
아직 댓글이 없습니다