본문 바로가기

전체 글

(32)
7. 다 쓴 객체 참조를 해제하라 자바같은 가비지 컬렉션을 가진 언어에서는 메모리 누수를 찾기가 매우 어렵다.객체 참조를 하나라도 살려두면 가비지 컬렉터는 그 객체뿐 아니라 그 객체가 참조하는 모든 객체를 회수하지 못 한다. 이를 해결하는 방법은 간단하다. 해당 참조를 다 썻을 때 null 처리 해주면 된다. public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { this.elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { this.ensureCapa..
6. 불필요한 객체 생성을 피하라 다음은 정규표현식을 활용한 예제이다. static boolean isRomanNumera(String s) { return s.matches("^(?-.)M* ....; } 성능을 개선하려면 필요한 인스턴스를 클래스 초기화과정에서 생성해 캐싱하여, 나중에 해당 인스턴스를 재사용한다.이 방식은 쉬운 방식이지만 성능이 중요한 곳에서는 반복적으로 사용하기 적합치 않다. 이 메서드가 내부에서 만드는 인스턴스는 한 번 쓰이고 버려져 곧바로 가비지 컬렉션 대상이 된다. public class RomanNumerals { private static final Pattern ROMAN = Patterm.compile( "^(?-.)M* .... ); static boolean isRomanNumeral(String s..
5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. public class SpellChecker { // 유연하지 않고 테스트하기 어렵다. private final Lexicon dictionary = ...; public SpellChecker(Lexicon dictionary) { this.dictionary = Objects.requireNonNull(dictionary); } }​ 클래스가 여러 자원 인스턴스를 지원해야 하며, 클라이언트가 원하는 자원을 사용해야 한다. 이 조건을 만족하는 패턴이 있으니, 바로 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다. public class SpellChecker { // 유연하지 않고 테스..
4. 인스턴스화를 막으려거든 private 생성자를 사용하라 가끔 정적 메서드와 정적 필드만을 담은 클래스가 필요할 경우가 있다. 유틸리티 클래스를 만들 때 주로 사용되는데, 이런 클래스들은 인스턴스화 되는 것을 되도록 막아야 한다. 자바에서는 생성자를 개발자가 작성하지 않아도, 내부적으로 생성자를 제공해준다. 그렇기에 이를 막기 위해서는 private로 생성자를 임의로 명시해주는 것이 좋다. 또한 이 방식은 상속을 불가능하게 만든다. 상속을 받으려면 해당 부모 클래스의 생성자를 호출할 수 있어야 하는데, private 선언을 통해 부모 클래스를 상속할 길이 막혀버린다. public class Utility { private Utility() { throw new AssertionError(); } } 결론 유틸리티 클래스들을 정적 메서드로 채우게 된다면 생성자는..
3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 싱글턴(singleton)이란 인스턴스를 오직 하나만 생성할 수 있는 클래스이다. 싱글턴을 만드는 방식은 둘 중 하나다. 두 방식 모두 private으로 감추고, 인스턴스에 접근할 수 있는 수단으로 public static 멤버를 하나 만든다. public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() {...} public void leaveTheBuilding() {...} } 생성자는 INSTANCE 를 초기화할 때 한 번만 호출된다. 그렇기에 전체 시스템에서 해당 클래스는 하나만 생성됨을 보장할 수 있게된다.(단 향후 배울 리플랙션에서 private 생성자를 호출하는 법을 알게된다.) 해당 코드의 장점..
2. 생성자에 매개변수가 많다면 빌더를 고려하라 정적 팩토리와 생성자에는 똑같은 제약이 있다. 매개변수가 많을 때 적절히 대응하기 어렵다는 점이다. 옛 프로그래머들은 이럴 때 점층적 생성자 패턴(telescoping constructor pattern)을 주로 사용했다. public class NutritionFacts { private final int servingSize; // required private final int servings; // required private final int calories; // optional private final int fat; // optional public NutritionFacts(int servingSize, int servings) { this(servingSize, servings, 0)..
02. 카프카의 구성요소 카프카의 주요 구성 요소는 다음 5가지다. 프로듀서 : 데이터 생산자이며 브로커에 메시지를 보내는 애플리케이션 메시지 : 카프카에서 데이터를 다루는 최소 단위 브로커 : 데이터 수신 및 전달하는 서비스 컨슈머 : 브로커에게 메시지를 전달받는 애플리케이션 토픽 : 메시지를 종류별로 관리하는 스토리지. 브로커에 배치되어 관리된다. 프로듀서와 컨슈머는 특정 토픽을 지정하여 메시지를 송수신한다. 프로듀서 -> 브로커 -> 컨슈머의 흐름에서, 프로듀서 -> 브로커는 PUSH형 / 브로커 -> 컨슈머는 PULL형으로 이루어진다. PULL형의 장점은 컨슈머 고장 시 브로커에 미치는 영향이 적으며, 컨슈머의 증감에 효율적으로 대응할 수 있게 된다. 카프카의 브로커에서 분산 처리를 위한 관리 도구로 주키퍼가 필요하다. ..
01. 카프카의 개요 아파치 카프카(Apache Kafka)는 여러 대의 분산 서버에서 대량의 데이터를 처리하는 분산 메시징 시스템이다. 카프카는 대량의 데이터를 높은 처리량과 실시간으로 취급하기에 다음 4가지 특성을 가지고 있다. - 확장성 : 여러 서버로 확장(scale out) 구성할 수 있어 데이터 양에 따라 시스템 확장이 가능하다. - 영속성 : 수신한 데이터를 디스크에 유지할 수 있어 언제라도 데이터를 읽을 수 있다. - 유연성 : 연계할 수 있는 제품이 많아 제품이나 시스템을 연결하는 허브 역할을 할 수 있다. - 신뢰성 : 메시지 전달을 보증하므로 데이터 분실에 대한 걱정을 하지 않아도 된다. 링크드인에서 카프카를 발표하기 전, 카프카와 비슷한 제품이 있었지만 모두 링크드인에서 요구하는 사항에는 일치하지 않았다..