Java 44

콜백 패턴(Callback Pattern) 총정리: 동기(Blocking) vs 비동기(Non-blocking)

"헐리우드 원칙을 아시나요? '우리에게 전화하지 마세요. 우리가 당신에게 전화할게요(Don't call us, we'll call you).'"보통은 우리가 함수를 호출하고 결과값을 받습니다(return). 하지만 콜백 패턴에서는 우리가 함수에게 **"일이 끝나면 이 코드를 실행해줘"**라고 함수 자체를 파라미터로 넘깁니다.하지만 이 콜백이 "기다렸다가 실행되는지(동기)" 아니면 **"나를 놔두고 따로 실행되는지(비동기)"**에 따라 프로그램의 흐름이 완전히 달라집니다. 1. 방식 1: 동기 콜백 (Synchronous Callback) - "기다림의 미학"자바의 Stream이나 Template Callback 패턴에서 주로 쓰이는 방식입니다. 호출한 함수가 콜백을 모두 실행하고 끝날 때까지 제어권을 ..

널 객체 패턴(Null Object Pattern) 총정리

"고객 등급을 조회했는데 고객이 탈퇴해서 정보가 없으면(null) 어떡하지?""DB에서 조회했는데 데이터가 없으면 에러가 나나?"자바 개발자의 영원한 숙적 **NPE(NullPointerException)**를 피하기 위해 우리는 습관적으로 방어 로직을 짭니다. 하지만 코드 곳곳에 if (obj != null)이 도배되면 가독성이 떨어집니다.이를 해결하기 위해 **"아무 일도 하지 않는 객체"**를 만들어 null 대신 반환하는 것이 널 객체 패턴입니다.1. 문제 상황: 방어적 복사 (Defensive Check)가장 흔하지만, 가장 지저분한 방식입니다. null 체크를 호출하는 쪽(Client)에게 떠넘깁니다.Javapublic void printCustomerGrade(String name) { ..

인터프리터 패턴(Interpreter Pattern) 완벽 정리

"우리 회사만의 업무 규칙(DSL)을 만들고 싶어요.""사용자가 입력한 수식(10 + 20 - 5)을 계산하는 계산기를 만들어야 해요."단순한 문자열을 컴퓨터가 이해할 수 있는 동작으로 변환하려면 **문법(Grammar)**을 정의하고 이를 **해석(Interpret)**해야 합니다. 이때 문법 규칙 하나하나를 객체로 만들어 조립하는 것이 인터프리터 패턴입니다.하지만 규칙이 많아질수록 클래스가 폭발적으로 늘어나는 문제가 있습니다. 이를 해결하는 두 가지 방법을 비교해 봅니다.1. 방식 1: 클래스 기반 AST (GoF 정석) - "구조적이지만 무거움"가장 교과서적인 방식입니다. 문법의 각 요소(숫자, 더하기, 빼기 등)를 클래스로 정의하고, 이를 트리 구조(Abstract Syntax Tree, AST)..

메멘토 패턴(Memento Pattern) 완벽 정리

"게임에서 보스전을 앞두고 '저장'을 합니다. 죽으면 다시 불러와야 하니까요.""문서 작업을 하다가 실수로 내용을 지웠습니다. Ctrl+Z를 눌러 이전 상태로 되돌립니다."이 기능을 구현하려면 객체의 현재 상태(private 필드값)를 어딘가에 저장해야 합니다. 하지만 저장하기 위해 Getter/Setter를 남발하면 캡슐화가 깨집니다. 누군가 저장된 데이터를 멋대로 조작할 수도 있죠.이 딜레마를 해결하기 위해 "저장된 상태(메멘토)"를 누구에게 어디까지 보여줄 것인가를 결정하는 것이 이 패턴의 핵심입니다.1. 방식 1: 화이트박스 메멘토 (White-box Memento) - "순진한 방식"저장된 상태 객체(Memento)의 내부를 **공개(Public)**하는 방식입니다. 구현이 쉽지만, 상태를 관리..

플라이웨이트 패턴(Flyweight Pattern) 완벽 정리

"MMORPG 게임을 만드는데, 숲속에 나무를 100만 그루 심어야 합니다."나무 한 그루 객체가 Mesh(형태), Texture(질감), Position(좌표) 정보를 가지고 있는데 크기가 1KB라고 가정해 봅시다. 100만 그루면 1GB의 메모리가 필요합니다. 단순한 배경 때문에 서버나 클라이언트가 뻗어버리는 상황이죠.이때 "변하지 않는 정보(형태, 질감)"는 딱 하나만 만들어서 공유하고, "변하는 정보(좌표)"만 개별적으로 관리하면 어떨까요? 이것이 플라이웨이트 패턴의 핵심입니다.1. 핵심 개념: 두 가지 상태의 분리플라이웨이트 패턴을 이해하려면 객체의 데이터를 두 가지로 쪼개야 합니다.내부 상태 (Intrinsic State): 객체 내부에 저장되며 공유 가능한 정보. (예: 나무의 색깔, 텍스처..

방문자 패턴(Visitor Pattern) 완벽 정리

"쇼핑몰 아이템 클래스(책, 과일, 가전)가 이미 완성되어 있습니다. 그런데 갑자기 '배송비 계산' 로직을 추가하고, 그다음엔 'XML 변환' 로직을, 그다음엔 '할인 적용' 로직을 계속 추가해야 한다면?"기존 클래스(Book, Fruit)를 계속 수정하는 것은 OCP(개방-폐쇄 원칙) 위반입니다. 이때 데이터 구조(아이템)는 그대로 두고, 새로운 기능(방문자)만 따로 만들어서 끼워 넣는 것이 방문자 패턴입니다.하지만 이 패턴은 "구현이 너무 복잡하다"는 악명이 높았습니다. Java 최신 버전이 나오기 전까지는 말이죠. 1. 방식 1: 클래식 방문자 (Double Dispatch) - "GoF의 정석"객체지향 언어에서 오버로딩(Overloading)의 한계를 극복하기 위해 **두 번의 호출(Double ..

브리지 패턴(Bridge Pattern) 완벽 정리

"모양(Shape)에는 원과 사각형이 있습니다. 색상(Color)에는 빨강과 파랑이 있습니다."이 간단한 요구사항을 구현하기 위해 RedCircle, BlueCircle, RedSquare, BlueSquare 클래스를 만드는 순간 지옥문이 열립니다. 만약 Triangle 모양이 추가되고 Green 색상이 추가된다면? 클래스는 $3 \times 3 = 9$개가 됩니다. $M \times N$으로 클래스가 기하급수적으로 늘어나는 현상, 이것이 **클래스 폭발(Class Explosion)**입니다.이 문제를 해결하기 위해 **"모양"과 "색상"을 분리하고 다리로 연결(Bridge)**하는 것이 브리지 패턴의 핵심입니다. 1. 문제 상황: 상속을 통한 확장 (Inheritance) - "M × N의 저주"기..

중재자 패턴(Mediator Pattern) 완벽 정리

"비행기들이 서로 통신하며 착륙 순서를 정한다면 공항은 아수라장이 될 것입니다. 비행기는 오직 관제탑(Controller)하고만 교신해야 합니다."소프트웨어도 마찬가지입니다. 회원 서비스가 주문 서비스를 부르고, 주문 서비스가 다시 포인트 서비스를 부르고, 포인트가 메일을 보낸다면... 의존성이 거미줄처럼 꼬이게 됩니다(Spaghetti Code).이 복잡한 관계를 끊고 **"모든 대화는 나를 통하라"**고 정리해 주는 것이 중재자 패턴입니다. 하지만 이 중재자를 구현하는 방식은 크게 두 가지로 나뉩니다.1. 방식 1: 클래식 중재자 (Direct Reference) - "채팅방 스타일"GoF 디자인 패턴의 정석입니다. 중재자(Mediator)가 모든 참여자(Colleague)의 참조(Reference)..

퍼사드 패턴(Facade Pattern) 완벽 정리

"주문 버튼 하나를 눌렀을 뿐인데, 내부적으로는 재고 확인, 결제 요청, 포인트 차감, 이메일 발송, 배송 요청이 동시에 일어납니다."클라이언트(프론트엔드 또는 컨트롤러)가 이 복잡한 로직을 모두 알게 하면 결합도가 너무 높아집니다. 이를 해결하기 위해 건물의 정면(Facade) 처럼 복잡한 내부를 가리고 **"통합된 인터페이스 하나만 제공"**하는 것이 퍼사드 패턴입니다.하지만 이를 구현할 때, 자바 개발자는 Static Method의 유혹과 Spring Bean의 정석 사이에서 고민하게 됩니다. 1. 방식 1: 정적 퍼사드 (Static Helper) - "간편함"흔히 ~Util, ~Helper라는 이름으로 만드는 방식입니다. 객체 생성 없이 어디서든 호출할 수 있어 편리하지만, 객체지향적인 관점에서..

데코레이터 패턴(Decorator Pattern) 총정리

"커피 주문 시스템을 만드는데, 에스프레소에 물을 추가하면 아메리카노, 우유를 추가하면 라떼, 거기에 시럽을 추가하면 바닐라 라떼가 됩니다."이 모든 조합을 EspressoWithWaterAndMilkAndSyrup 같은 클래스로 상속받아 만들면 클래스 개수가 수백 개로 폭발합니다. 이를 해결하기 위해 객체에 장식(Decorate)을 덧입히듯 기능을 동적으로 추가하는 것이 데코레이터 패턴입니다.1. 방식 1: 클래식 데코레이터 (Object Wrapping) - "마트료시카 인형"GoF 디자인 패턴의 정석이자, Java I/O (InputStream)의 근간이 되는 방식입니다. 객체가 다른 객체를 감싸고, 그 객체가 또 다른 객체를 감싸는 양파 껍질 같은 구조를 가집니다.특징투명성: 데코레이터와 실제 객..