Dev/Java 25

[Reactive Programming] 리액티브 시스템과 리액티브 프로그래밍

리액티브 시스템(Reactive System) 리액티브란 사전적 의미로 어떤 이벤트나 상황이 발생했을 때, 적절하게 행동하는 것을 의미한다.  따라서 리액티브 시스템이란 반응을 잘 하는 시스템이라고 정의할 수 있고, 이는 클라이언트의 요청에 즉각적으로 응답함으로써 지연 시간을 최소화하는 시스템이라고 할 수 있다.  리액티브 선언문(The Reactive Manifesto) 리액티브 선언문이란 리액티브 시스템 구축을 위한 일종의 설계 원칙이자 리액티브 시스템의 특징이다. 이는 아래 그림 하나로 명확하게 설명할 수 있다. 방법(Means)주요 통신 수단으로 무엇을 사용할 것인지 표현한 것으로, 위 그림처럼 비동기 메시지 기반(Message Driven)의 통신을 사용할 것임을 뜻한다. 이는 구성요소들 간의 ..

Dev/Java 2024.06.25

[Effective Java : Item 90] 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라

개요 Serializable을 구현하기로 결정했다는 것은, 언어의 정상 메커니즘인 생성자 사용을 우회하여 인스턴스를 생성할 수 있게 된다는 것이다. 이로 인해, 버그와 보안 문제가 발생할 가능성이 일어날 가능성이 커지는데, 직렬화 프록시 패턴(serializable proxy pattern)을 통해 이를 크게 줄일 수 있다.   직렬화 프록시 패턴 사용법 * Proxy의 사전적 정의는 "대리", "대리인"을 의미 직렬화 프록시 패턴을 간략하게 요약하자면, 직렬화된 코드를 그대로 클래스의 인스턴스로 생성하는 것이 아니라, 그 클래스와 논리적 상태가 동일한 중첩 클래스를 설계해 방어적 생성을 하는 것이다.  직렬화 프록시 패턴을 구현하는 방법은 다음과 같다. 바깥 클래스의 논리적 상태를 정밀하게 표현하는 중..

Dev/Java 2024.05.22

[Effective Java : Item 86] Serializable을 구현할지는 신중히 결정하라

개요 특정 클래스의 인스턴스를 직렬화하고 싶다면 Serializable을 구현하도록 클래스 선언에 implements Serializable만 붙이면 된다. Serializable 내부적으로 구현이 강제되는 메서드 또한 존재하지 않아 쉽게 적용할 수 있다고 생각될 수 있으나, 실상은 직렬화를 구현한다는 것은 훨씬 복잡하고 값비싼 일이다.  Serializable 구현 시 주의할 점 1. 릴리스한 뒤에는 수정하기 어렵다.Serializable을 구현하면 직렬화된 바이트 스트림 인코딩도 하나의 공개 API가 되는 셈이다. 따라서 릴리스가 된 뒤에는 이 직렬화 형태도 영원히 지원해야 한다. 또한 커스텀 직렬화 형태를 사용하지 않고 자바의 기본 직렬화를 사용한다면 최초 직렬화 당시 클래스의 내부 구현 방식에 묶..

Dev/Java 2024.05.08

[Effective Java : Item 83] 지연 초기화는 신중히 사용하라

지연 초기화(lazy initialization) 지연 초기화란?- 필드의 값이 처음 필요할 때까지 초기화를 늦추는 기법- 정적 필드와 인스턴스 필드 모두 사용 가능- 주로 최적화 용도로 사용, 초기화 시 발생하는 위험한 순환 문제를 해결하는 효과도 존재 지연 초기화의 양면성지연 초기화는 무조건 좋은 것이 아니라 경우에 따라 다른 양면성이 존재한다. - 클래스 혹은 인스턴스 생성 시의 초기화 비용 감소- 반면 지연 초기화하는 필드에 접근하는 비용은 증가- 필드를 초기화하는 비용, 횟수 등에 따라 지연 초기화 시 오히려 성능이 감소하는 경우도 있다. 즉, 인스턴스가 해당 필드를 잘 사용하지 않지만, 초기화 비용이 큰 경우에는 지연 초기화 도입을 고려할 필요성이 있다. 또한 멀티스레드 환경에서는 지연 초기화..

Dev/Java 2024.04.09

[Effective Java : Item 77] 예외를 무시하지 말라

개요 검사 예외 및 비검사 예외에 동일하게 적용되는 원칙이다. 아주 자명한 사실이지만, 사람들이 자주 어기고 있는 원칙 중 하나라고 한다. API 설계자가 메서드 선언에 예외를 명시하는 이유는, 그 메서드를 사용할 때 발생할 수 있는 문제에 대해 적절한 조치를 취해달라고 말하는 것이다. 다음의 코드와 같이 예외를 무시하는 방법은 아주 간단하다. try-catch 문으로 코드를 묶고, catch에 아무런 조치를 하지 않으면 된다. try { ... } catch (SomeException e) { } 문제 상황에 잘 대처하기 위해 예외가 존재하는데, 위처럼 catch 블록을 비워두면 예외가 존재할 이유가 없어진다. 예외를 무시해도 되는 경우 예외를 무시해도 괜찮을 경우도 있다. 예를 들어, FileInpu..

Dev/Java 2024.04.01

[Effective Java : Item 69] 예외는 진짜 예외 상황에만 사용하라

개요 try { int i = 0; while(true) range[i++].climb(); } catch (ArrayIndexOutOfBoundsException e) { } 위의 코드는 배열의 원소를 끔찍한 방식으로 순회하고 있는 코드이다. 무한루프를 돌며 순회하다가, 배열의 끝에 도달해 ArrayIndexOutOfBoundsException이 발생하면 끝을 내는 방식이다. 전혀 직관적이지 않다는 사실 하나만으로도 코드를 이렇게 작성하면 안 된다는 이유가 충분하다. 아래는 일반적인 관용구를 사용하여 작성한 방법이다. for (Mountain m : range) m.climb(); 왜 예외를 사용하는 방식으로 반복문을 종료하도록 하였을까? 저자는 아마도 잘못된 추론을 근거로 성능을 높여보려 시도한 흔적..

Dev/Java 2024.03.29

[Effective Java : Item 60] 정확한 답이 필요하다면 float와 double은 피하라

개요 float와 double은 부동소수점 숫자를 표현되는 데 사용되는 데이터 형식으로, 넓은 범위의 수를 '근사치'로 빠르게 계산할 수 있다. 부동 소수점 형식은 유한한 비트 수로 실수를 표현하는데, 이로 인해 정밀도 손실이 발생하기 때문이다. 따라서 아주 정확한 계산이 필요한 금융 관련 계산에는 절대 사용하면 안 된다. 다음의 예제를 살펴보자. System.out.println("1.03 - 0.42 = " + (1.03 - 0.42)); 1.03 달러에서 42센트를 사용한 예제이다. 이를 실행하면 다음과 같은 결과를 얻는다. 기대한 값인 0.61이 아닌 0.6100000000000001 을 출력한다. 심지어 특수한 사례도 아니다. 좀 더 구체적인 사례로 살펴보자. double funds = 1.00..

Dev/Java 2024.03.21

[Effective Java : Item 59] 라이브러리를 익히고 사용하라

개요 static Random rnd = new Random(); static int random(int n) { return Math.abs(rnd.nextInt()) % n; } 위 코드는 0부터 n보다 작은 정수 중 하나를 출력하는 간단한 메서드이다. 괜찮은 듯 보이지만 세 가지 문제점을 내포하고 있다. 1. n이 그리 크지 않은 2의 제곱수라면 같은 수열이 반복된다. 2. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다. n값이 크면 현상이 더 두드러진다. 3. 지정한 범위 바깥의 수가 종종 튀어나올 수 있다. rnd.nextInt()는 Integer.MIN_VALUE 를 반환할 수 있는데, 이를 Math.abs()로 절대값으로 반환하고자 하면 오버플로우가 발생하기 때문이다...

Dev/Java 2024.03.20

[Effective Java : Item 58] 전통적인 for 문보다는 for-each 문을 사용하라

for 문 // for 문으로 컬렉션 순회 for (Iterator i = c.iterator(); i.hasNext(); ) { Element e = i.next(); ... // 부수적인 동작 } // for 문으로 배열 순회 for (int i = 0; i < a.length; i++) { ... // 부수적인 동작 } 위 코드는 for 문으로 컬렉션과 배열을 순회하는 코드이다. 이러한 순회 방식은 while 보다는 낫지만, 몇 가지 단점이 존재한다. 단점 1. 가독성 반복자와 인덱스 변수는 가독성을 해친다. 또한 원소만 필요한 경우 원소 반환 목적 외에는 의미가 없는 코드이다. 2. 휴먼 에러 반복자와 인덱스가 많은 빈도로 등장하여 변수를 잘못 사용할 가능성이 높아진다. 또한 컴파일러가 잘못 사용..

Dev/Java 2024.03.18

[Effective Java : Item 55] 옵셔널 반환은 신중히 하라

개요 자바 8 이전, 즉 Optional이 존재하기 이전에는 메서드가 특정 조건에서 값을 반환하지 못할 때 취할 수 있는 두 가지 선택지가 있었다. 하지만 각각 가지고 있는 허점이 존재했다. 1. 예외를 던진다. 예외는 되도록 진짜 예외인 상황에서만 사용해야 하고, 예외가 발생할 때 스택 추적 전체를 캡쳐하므로 다소 비용이 크다. 2. null을 반환한다. 별도의 null 처리를 해야 한다. 그렇지 않다면 언젠가 null이 발생한 근원지와는 상관없는 곳에서 NullPointException이 발생할 것이다. 위같은 문제를 해결하기 위해 Optional이 등장했다. Optional Optional는 null이 아닌 T 타입 참조를 하나 담거나, 아무것도 담지 않을 수 있다. 또한 Optional는 위와 같..

Dev/Java 2024.03.14
반응형