Java/자바 잡지식
자바 레코드 (Record) 란 무엇일까?
자바의 Record 란? 자바 17 에서 Stable 이 된 데이터 클래스다. 클래스 정의 시에 보일러 플레이트 코드를 줄이기 위해 탄생했다. 기능 불변 (final 처리) 클래스와 모든 필드가 final 처리 된다. 한번 생성하면 record 의 상태는 바뀌지 않는다. 간결한 메서드 자동 생성 getter, equals(), hashCode(), toString() 메서드를 자동으로 생성한다. 생성자 자동 생성 모든 필드를 매개변수로 사용하는 생성자를 자동으로 생성해준다. 예제 아래 코드는 1줄이지만, 클래스와 모든 필드가 final 처리되어 있다. 매개변수에 있는 field1 과 field2 가 필드가 된다. getter, equals(), hashCode(), toString() 메서드도 생성된 상..
자바 예외의 종류와 특징
예외의 종류와 특징 예외 처리에서 가장 큰 이슈는 체크 예외(checked exception)라고 불리는 명시적인 처리가 필요한 예외를 사용하고 다루는 방법이다. Error java.lang.Error 클래스의 서브 클래스들이 있다. 시스템에 비정상적인 상황이 발생했을 경우 사용되며, 자바 VM에서 발생시키는 것이므로 애플리케이션 코드에서 잡으려고 하면 안된다. OutOfMemoryError나 ThreadDeath같은 에러는 catch 블록으로 잡아봤자 아무런 대응 방법이 없다. 시스템 레벨에서 이뤄지는 에러기 때문에 애플리케이션에서는 이런 에러에 대한 처리를 신경쓸 필요가 없다. Exception과 체크 예외 java.lang.Exception 클래스와 그 서브 클래스로 정의되는 예외들은 에러와 달리 ..
자바 리플렉션 (Reflection) 이란?
자바 리플렉션 (Reflection) 이란? 실행 중인 자바 애플리케이션이 JRE (Java Runtime Environment) 를 검사, 수정, 상호작용할 수 있도록 하는 기능이다. 애플리케이션의 런타임 동작을 검사하거나 수정할 수 있다. 자바 리플렉션의 용도 (Use Case) 리플렉션의 대부분의 기능은 일반 애플리케이션 개발에는 크게 필요 없으며 프레임워크의 관점에서 접근할 때 크게 도움이 된다. ex) 프레임워크 이용자가 어떤 애노테이션을 적용했는지 알고 싶을 때는 리플렉션이 크게 도움이 된다. 클래스 구조 검사하기 객체의 클래스를 확인하고 어떤 메서드가 있는지 어떤 필드가 있는지 어떻게 구성됐는지에 대한 정보를 얻을 수 있다. 어떤 상수와 애노테이션이 선언되어 있는지 확인할 수도 있다. 우리가..
자바의 ThreadLocal 이란?
자바의 ThreadLocal 이란? 오직 같은 스레드에 의해서만 쓰이거나 읽혀질 수 있는 변수를 만들기 위한 클래스이다. 제네릭 타입의 객체 하나만 읽거나 쓰는 용도이다. 각각의 스레드가 독립적인 공간을 가지고 변수를 다룰 수 있게 만든다. 스레드는 독립적으로 초기화된 변수의 자체 복사본을 가질 수 있다. ThreadLocal 인스턴스는 보통 상태를 스레드에 연결하려고 하는 클래스의 비공개 정적 필드로 사용된다. 이 이유에 대해선 아래에서 설명한다. 주로 user ID 나 transaction ID 와 같은 것에 많이 쓰인다. 왜 ThreadLocal 은 private & static 하게 사용되는가? private 을 사용하는 이유 비공개로 선언해야 다른 클래스에서 해당 스레드의 ThreadLocal ..
자바 Stream 에 size() 혹은 length 프로퍼티가 없는 이유
Stream 에 size() 혹은 length 가 존재하지 않는 이유 아래의 개념을 알기 전에 앞서 스트림에서 평가(evaluation) 란 무엇인지 알아야 한다. Stream 은 게으르게 프로세스를 처리하도록 설계되어 있다. Stream 은 각 원소가 실제로 필요할 때까지 평가(evaluation) 하지 않는다. 큰 데이터 셋을 처리하는 경우, 이 접근 방식이 매우 효과적이다. 실제로 평가되기 전까지 데이터의 변환이 더 있을 것이라 가정하고 크기를 반환하는 size() 혹은 length 같은 프로퍼티를 제공하지 않는다. 대신 count() 메서드를 호출하면 스트림을 소모하여 전체 데이터 개수의 숫자를 반환한다.
자바 함수형 인터페이스 혹은 람다 인터페이스란?
함수형 인터페이스 혹은 람다 인터페이스 (Functional Interface, Lambda Interface) 란? 공식 API 문서 람다 인터페이스와 함수형 인터페이스는 같은 말이다. 단 하나의 추상 메서드만 가지는 인터페이스를 함수형 인터페이스라고 한다. 함수형 인터페이스를 구현하여 손쉽게 람다 표현식을 작성할 수 있다. Stream API 와 같이 사용하는 방식도 많이 이용된다. 자바에서는 자체적으로 많은 표준 함수형 인터페이스를 제공한다. 따로 만들기보단 제공하는 것을 이용하는 것이 좋다. 표준 함수형 인터페이스 살펴보기 Predicate 임의의 타입 T 의 인자를 받아 boolean 을 반환하도록 설계되어 있다. Predicate isPositive = num -> num > 0; Functi..
Java Stream API 에서 평가 (evaluation) 란?
스트림에서 평가(evaluation) 란? 스트림에서 종종 평가(evaluation) 라는 용어를 사용한다. 평가는 병렬 처리가 가능한 Stream 형태에서 Stream 이 아닌 다른 형태의 자바 객체로 바꾸는 행위를 말한다. toArray(), collect(), reduce(), forEach() 같이 Stream 타입이 아닌 자바 객체로 변환하고 이를 반환하는 것을 말한다. Stream 은 평가 전에는 계속 스트림 형태를 유지한다. findFirst(), anyMatch(), allMatch() 또한 평가(evaluation) 를 트리깅할 수 있다. 하지만, 오직 단락 조건 (short-circuiting condition) 이 맞을 때만 가능하다. 단락 조건 (short-circuiting con..
자바에서 상속이 갖는 단점들
상속이 갖는 단점들 상속은 객체지향 프로그래밍의 핵심 기능이지만, 몇가지 단점을 가지고 있다. 그래서 일반적으로는 합성(composition)을 사용하는 것이 권장된다. 강한 결합이 강제된다. 부모 클래스의 소스 코드를 그대로 내려받을 수 있다는 장점이 있지만, 그만큼 자식 클래스가 많아졌을 때 부모 클래스의 소스코드 변경이 힘들다는 말도 된다. 부모 클래스의 변화가 모든 자식 클래스에 영향을 미치게 된다. 변경하려면 자식 클래스의 구현들이 제대로 돌아갈 수 있을지 테스트를 많이 거쳐야 한다. 코드의 유지보수와 수정을 어렵게 만든다. 함부로 변경했다가 자식 클래스에서 쉽게 알아차리기 힘든 미묘한 버그를 만들어낼 수 있는 가능성도 생긴다. 접근자에 대한 제약이 강하게 걸린다. 초기에 public 으로 공개..
로컬과 운영 환경의 log4j 나누기
다른 경로의 log4j 사용하기 log4j.xml 은 설정에 따라 많은 정보를 로깅하기도, 꼭 필요한 정보를 로깅하기도 한다. level 태그의 value 프로퍼티를 INFO 로 바꾸면 아주 많은 로그를 띄운다. 운영 중인 프로젝트의 log4j 에 너무 많은 로그가 쌓이면 금방 용량이 꽉차게 되고 장애가 일어난다. 개발용 log4j.xml 과 운영용 log4j.xml 이 가끔 나누어질 필요가 있다. -Dlog4j.configuration="file:///D:/log4j/log4j_all_log.xml"톰캣을 실행할 때, VM 속성에 위와 같이 입력해주면, 특정 경로에 있는 log4j.xml 을 사용할 수 있다.
ObjectMapper (Jackson) 커스텀 직렬화 역직렬화 구현
ObjectMapper (Jackson) 커스텀 직렬화, 역직렬화 ObjectMapper 는 객체를 잘 직렬화해서 JSON 문자열로 만들어주거나, JSON 문자열을 잘 파싱해서 객체로 만들어준다. 그런데 사용자 정의 객체의 경우엔, 개발자가 직접 직렬화, 역직렬화 시켜줄 필요가 있다. 이럴 때 어떻게 확장할 수 있을까? 다음과 같은 코드로 확장하면 된다. @Bean public ObjectMapper objectMapper() { SimpleModule module = new SimpleModule(); module.addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer()); module.addDeserializer(LocalDateT..
자바 8 이상에서 날짜 올바르게 다루기
java.util.Date vs java.time.LocalDate 자바에서 날짜를 지원하는 대표적인 API 는 2가지가 있다. java.util.Date: Java 8 이전부터 존재한 API 이다. java.time.LocalDate: Java 8 부터 생긴 API 이다. java.util.Date 는 이름과 다르게 날짜 뿐 아니라 시간까지 다룬다. 반면, java.time.LocalDate 는 날짜만 다루는 역할을 하고, 시간까지 다루기 위한 java.time.LocalDateTime 이라는 API 가 따로 정의되어 있다. 위의 두개 객체 중에서 java.time 패키지에 있는 LocalDate 를 사용하는 것이 권장된다. 예전엔 날짜를 다루기 위해서 java.util.Date, java.util.C..
javadoc 한글 깨짐 문제 해결
문제 현상 ./gradlew javadoc 위 명령어로 javadoc 빌드를 했을 때, 아래와 같은 에러가 난다. error: unmappable character (0xEC) for encoding x-windows-949해결 방법 Javadoc 빌드 시 인코딩을 추가해주면 된다. Gradle 기준으로 gradle.build 에 아래의 내용을 추가하자. javadoc { options.addStringOption("locale","ko_KR"); options.addStringOption("encoding","UTF-8"); options.addStringOption("charset","UTF-8"); options.addStringOption("docencoding","UTF-8"); } 이제 다시 ..