aws component를 프로그래밍에 이용할 때 아래와 같이 sdk를 추가해 사용할 것이다s3와 appliation.yml에 들어갈 프로퍼티를 암호화하기 위해 aws parameter store를 사용할 예정이다// AWSimplementation("software.amazon.awssdk:s3:$awsVersion")implementation("software.amazon.awssdk:sts:$awsVersion")// Parameter Storeimplementation(platform("io.awspring.cloud:spring-cloud-aws-dependencies:$springCloudVersion"))implementation("io.awspring.cloud:spring-cloud-aw..
해당 이슈는 Postman 같은 똑똑한 클라이언트를 사용하지 않고 Windows or Mac 등 직접 파일 업로드 요청을 보낼 때 발생할 수 있는 문제다 내 경우엔 Windows 클라이언트가 C++로 짠 코드로 서버에 HTTP 요청을 보내 파일 업로드를 요청했다 파일 업로드 시 파일 이름이 한글인 경우 업로드된 파일 이름이 깨지는 상황이 발생했다 Windows 클라이언트 개발자에게 HTTP 요청을 전달받아 상황을 재현했다 업로드할 파일이 한글 파일명을 가지고 있었기에 아래와 같은 형태로 요청을 만들었다고 한다 ### POST http://localhost:8080/test/file-upload Accept: application/json Content-Type: multipart/form-data; bo..
"Data truncation: Data too long for column" causes 이 에러는 언제 발생하는가? 테이블 생성 시 선언한 데이터 크기를 벗어날 때 발생한다 또 하나가 있다, 데이터 타입의 크기를 줄이고자 할 때 기존에 줄이려는 크기를 초과하는 데이터가 있을 때도 발생한다 업무 중 요구사항으로 200자 제한이 있던 컬럼의 길이를 100자로 제한해야 한다는 것이 발생했다 단순한 코드, DB 작업으로 끝낼 수 있겠거니 생각하고 넘기려던 차에 혹시 모르니 GPT에게 물어봤다 질문은 varchar(200)으로 선언한 컬럼을 varchar(100)으로 줄일 수 있느냐, 그리고 이미 100자를 초과하는 데이터가 있는데도 문제없이 작동하느냐고 물었다 GPT는 당당하게 아래와 같이 답했다 GPT 왈..
자바에는 언어 차원에서 제공하는 수많은 예외들이 있다 언어 자체에서 제공되므로 잘 작성되어 있고 네이밍도 적절하며 문서화도 잘 되어있다 그런데도 불구하고 구글링을 하다 보면 커스텀 예외를 사용하는 경우들이 적지 않게 있다 어설픈 경우 다음과 같은 형태를 가질 것이고 이런 경우에는 커스텀한 이름을 붙인 것 외에 아무런 장점이 없다 토이 프로젝트를 진행하던 당시에는 이런 예외를 사용했으나 이제 와서 생각해 보면 어설프다고 밖에 할 수 없다 public class TokenException extends AuthenticationException { public TokenException(String message) { super(message); } public TokenException(String msg..
어느 날 고객사에서 Apache Commons Fileupload 이슈가 인입되었다 apache commons file upload library 1.5 버전 미만에서 RequestParts 개수 제한을 걸어두지 않아 Dos 공격이 가능하다 Apache Tomcat: Important: Apache Tomcat denial of service (CVE-2023-24998) Rapid7's VulnDB is curated repository of vetted computer software exploits and exploitable vulnerabilities. www.rapid7.com 이후로 팀원분이 내부 동작을 파악하고 간단하게 리뷰를 해주셨는데 들을 때는 그렇구나 하고 수동적으로 들어서 그런지 남..
Item71에서는 필요 없는 Checked Exception 사용을 피하라 말한다 앞선 Item70에서 신나게 단점에 대해 얘기했으니 Checked Exception의 장점을 알아보고자 한다 다음 질문을 참고해 보자 In Java, what are checked exceptions good for? Java's checked exceptions have gotten some bad press over the years. A telling sign is that it's literally the only language in the world that has them (not even other JVM languages like Groovy and... softwareengineering.stackexch..
이전 글에서 @RequestBody 바인딩 처리를 알아보았고 이번에는 @ModelAttribute 처리에 대해 알아보자 스프링 버전에 따라 라인 수가 달라질 수 있으니 사진 설명에 클래스#메서드 형태로 남겨놨다 어떤 메서드를 호출하는지에 주의해 흐름을 따라가보자, 테스트할 객체와 컨트롤러는 아래 더보기를 참고하면 된다 더보기 @XmlAccessorType(XmlAccessType.PROPERTY) @XmlRootElement(name = "data") @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @ToString public class TestRequest { @XmlElement(name = "xml_nam..
레거시 시스템을 살펴보면 도메인에도 @Data, @Setter가 달려있는 모습을 볼 수 있다 불변의 중요성이 커지면서 & 무분별한 setter로 인해 변경점 파악이 어려워 @Setter는 안티 패턴과 같이 여겨지고 있다 @Setter와 같은 역할을 하더라도 더 의미 있는 changeXX() 등의 네이밍이 권장되고 있다 그렇다면 레거시 시스템에서는 @Setter를 왜 썼을까?, 개인적인 생각에 다음과 같은 이유지 않았을까 싶다 1. setter와 이름만 다르지 역할은 같은 수 많은 메서드를 만들기 귀찮음 2. @RequestBody, @ModelAttribute 바인딩을 가장 쉽게 할 수 있는 방법이므로 언젠가 코드리뷰에서 DTO에서 매핑이 안 되던 문제가 나왔던 적이 있다 입사한 지 얼마 안 된 신입 시..
Item70에서는 복구할 수 있는 예외는 checked-exception, 프로그래밍 오류는 unchecked-exception을 사용하라 말한다 옛날 글이지만 지금 봐도 좋은 checked-exception 관련된 글을 찾았다 C# Lead Architect가 checked-exception 개념을 왜 C#에서 빼버렸는지에 대한 인터뷰 글이다 artima - The Trouble with Checked Exceptions Artima provides consulting and training services to help you make the most of Scala, reactive and functional programming, enterprise systems, big data, and tes..
이전 글에서 이어지는 내용으로 commitOrRollback의 세부 구현을 살펴보자 EventListener 구현체는 JpaEventListener를 구현하고 여기서는 공통 Transaction 작업만 처리해주면 된다 import java.util.function.Consumer; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.engine.spi.SharedSessionContractImplementor; public interface JpaEventListener { default void commitOrRollback( SharedSessionContractImplementor session, C..
도메인 주도 개발 혹은 MSA로 갈 때 연관 관계를 다루기 위해서는 객체 자체가 아닌 식별자를 저장하곤 한다 예시만 살짝 맛보기로 하기 위해 극단적으로 간단한 엔티티를 만들었다, Panda -> Bear에 대한 간접 참조를 갖는다 @Entity @NoArgsConstructor @Getter public class Panda { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Long bearId; @Builder public Panda(String name, Long bearId) { this.name = name; this.bearId = bearId; } } @Entity ..
Item69에서 예외는 진짜 예외 상황에서만 사용하라 말한다. 너무나 당연한 얘기를 왜 한 장에 할당해 설명했을까? 바로 다음과 같은 해괴한 방식으로 작성하는 녀석들이 있기 때문이다 try { int i = 0 ; while (true) { System.out.println(array[i++]); } } catch (ArrayIndexOutOfBoundsException e) { // doSomething... } 위 코드의 의도는 array로 선언한 배열의 인덱스를 하나씩 늘려가며 출력하는 것인데 배열의 마지막 요소까지 출력하기 위해 범위를 넘어갈 때 (즉 ArrayIndexOutOfBoundsException이 발생할 때) catch 블록에서 잡아서 별도의 처리를 하거나 하지 않거나 하는 방식으로 작..
Item68에서는 일반적으로 통용되는 명명 규칙을 따르라 말한다 자바 언어 자체의 네이밍 규칙은 첫 글자로 $, _, 문자만 올 수 있으며 그 이후로는 어떠한 Unicode 문자든지 올 수 있다는 단순한 규칙으로 이루어져 있다 다만 언어의 규칙(Rule)과 관습(Convention)은 다르며 관습이 조금 더 제한적인 형태로 나타난다 규칙과 관습에 대해 더 자세히 알아보고 싶다면 아래 두 글을 참고하자 1. https://www.theserverside.com/feature/Java-naming-conventions-explained 2. https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html 네이밍의 대표..
Item67에서는 최적화를 신중히 하라 말한다 덧붙여 최적화 격언 세 개를 소개하는데 모두 섣부른 최적화는 안 하는 것보다 못하다는 의미를 전달한다 섣부른 최적화라 부를 수 있는 것의 사전 조건은 잘 짜둔 구조를 헤쳐가면서 최적화를 하는 것을 의미한다 최적화라는 것은 성능 뿐만 아니라 리소스도 포함하므로 더 방대한 영역을 다룬다 최적화에 발이라도 담가보려면 자바 언어 자체의 동작 원리, JDK 버전이 올라가면서 달라져야 하는 코드 작성 방식, JVM의 메모리 구조 + 라이브러리 + GC 등등 선제 지식이 너무 많이 필요하다 자바를 사용해서 개발 하는 것조차 쉬운 일이 아니건만 최적화를 하려면 더 깊고 넓은 지식에다가 로우 레벨까지 빠삭해야 하니 웬만한 대기업이 아니고서야 최적화에 신경 쓸 여력도 별로 없..
Item66에서 네이티브 메서드는 신중히 사용하라 말한다 네이티브 메서드란 무엇이고 언제 사용하는가? 오라클의 문서를 보자 자바만으로는 프로그램을 작성할 수 없는 경우에 사용한다고 하는데 JNI가 필요한 상황은 다음과 같다 1. 언어 자체가 특정 기능을 지원하지 않는 경우 2. 다른 언어로 된 라이브러리를 사용하고 싶은 경우 3. C, C++에 비해 구린 성능 내 경험에서만 비추어보자면 일반적인 개발자가 JNI를 사용할 일은 거의 없을 것 같다 platform-dependent한 레벨까지 내려갈 일이 없다 메서드 선언 부에 native 키워드를 가지고 있는 놈들이 네이티브 메서드인데 많은 라이브러리를 뒤져봐도 흔히 보이지 않는다 또한 책에서 나온 GNU 다중 정밀 연산 라이브러리 같이 정말 특별한 라이브..
Item65에서는 리플렉션보다는 인터페이스를 사용하라 말한다 이유는 간단하다 메서드를 직접 호출하면 컴파일된 코드를 실행하는데 반해 리플렉션은 bytecode에서 metadata를 찾아야 하기 때문이다 책에서는 리플렉션을 사용할 때의 단점을 나열하는데 다음과 같다 1. 컴파일 타입 검사 불가 2. 장황한 코드 3. 성능 저하 단점들을 보니 리플렉션을 쓰지 말아야 할 이유만 생기는 것 같다 컴파일 타입 검사 불가는 정적 타입 언어를 사용하는 이유를 무색하게 하고 장황한 코드는 안 그래도 지저분한 자바를 더 지저분하게 만들며 C, C++에 비해 구린 성능의 자바를 더욱 구리게 만든다 위 사진에 달린 링크를 따라가 보면 현실에서 리플렉션이 유용한 단 하나의 이유는 프레임워크에서의 사용이라 한다 즉 자신이 만들..
Item64에서 객체는 인터페이스를 사용해 참조하라 말한다 프로그래밍 입문 단계에서도 흔히 접할 수 있는 말인데 그때 당시에는 왜 명확한 타입을 두고 상위 타입으로 뭉뚱그려 받을까라는 생각이 있었다 이제는 바로 그 점 때문에 사용한다는 걸 알지만 처음 들어서는 쉽게 이해할 수 없었다 인터페이스란 용어가 낯설어서 그러지 않았나 생각이 든다 좋은 책들을 보면 명확한 설명이 되어있긴 한데 확 와닿지는 않는다 이해하고 나면 그 책들만큼 정확하고 이해하기 쉬운 설명이 없는데 이해하기 까지가 어려운 게 문제다 이럴 땐 명확하지 않고, 올바르지 않은 의미더라도 자기만의 언어로 풀어서 생각해보는게 좋다 내가 쉽게 이해해보려 생각한 인터페이스란 최소의 기능을 담은 껍데기다 구현체의 표면에 인터페이스라는 껍데기를 덧씌우면..
Item63에서는 문자열 연결은 느리니 주의하라 말한다 String의 작동 방식을 이해하기란 쉽지 않고 제대로 이해하려면 로우 레벨까지 파봐야 하니 이 글에서는 깊게 다루지는 않고 수박 겉핥기 정도로만 다뤄보려 한다 모든 내용은 이 글을 참고한다, 본 글은 간략하게 정리하기 위함이고 제대로 알아보려면 첨부한 링크를 보는 걸 추천한다 문자열 연산을 알아보기 전에 선행해서 생각해볼 점으로 가독성과 성능이 있다 기본 루프를 사용할 것이냐 스트림을 사용할 것이냐 처럼 가독성과 성능 둘 사이의 트레이드오프를 이해하고 상황에 맞는 방식을 사용해야 한다 자바에서 문자열 연결 시에 사용할 수 있는 방법은 + 연산자 외에도 꽤 많다 연결해야 하는 인자가 적다면 아무래도 + 연산자가 제일 가독성이 좋을 테고 StringB..
Item62에서는 적절한 타입이 있다면 문자열 사용을 피하라 말한다 책에서는 예제로 ThreadLocal을 들었고, 제네릭을 버무려 type-safe한 모습으로 만들어냈다 이 보다 더 와닿을 예제로 웹개발 시에 모든 값을 타입과 상관없이 String 타입으로 받아버리는 것이 있다 자바 스프링을 사용한다면 ConversionService에 의해 대부분의 타입이 변환이 되는데도 불구하고 String으로 받아버리고 필요하다면 개발자가 직접 형변환을 때려주는 코드를 본 적이 있다 상당한 레거시 프로젝트였는데 자바17까지 깔짝이며 최첨단으로 공부하던 신입 개발자 눈에는 당최 이해할 수가 없는 형태였다 ConversionService 문서를 보면 3.0부터 지원이 됐다고 하는데 그럼에도 안 쓴 이유를 추측해보자면 ..
Item61에서는 wrapper 타입보다 primtivie 타입을 사용하라 말한다 책에 나온 아래 예시보다 눈에 확 들어오게 간단한 예시로 박싱 된 기본 타입을 쓰지 말아야 할 이유를 살펴보자 Comparator naturalOrder = (i, j) -> (i, j) ? -1 : (i == j ? 0 : 1); 자바에서 범용성을 높이기 위해 Generic type으로 다루려면 반드시 reference type이어야 한다 이 것이 wrapper 타입의 존재 이유다 그렇다면 wrapper만 두고 모든 것을 객체로 다뤄버리면 되지 않을까 싶지만 성능 상의 이유로 그러기는 또 쉽지 않단다 아래는 int의 wrapper type인 Integer로 값을 비교하는 경우를 나타낸 예시다 public static vo..