OOP 7

Java 불변 객체와 방어적 복사: record로 안전한 도메인 만들기

Java 17 기준으로 불변 객체가 왜 중요한지, 방어적 복사로 캡슐화를 지키는 방법, record 활용과 얕은/깊은 복사 차이를 실무 관점에서 정리합니다.도입 (문제 상황)컬렉션이나 날짜 같은 값을 “그냥 getter로 꺼내줬는데”, 어느 순간부터 데이터가 몰래 바뀌어 버린 경험이 있으실 거예요. 특히 멀티스레드 환경이나 캐시, 이벤트 기반 처리에서는 이런 변경이 재현도 어렵고 원인 파악도 더 어렵습니다. 이럴 때 가장 강력한 방어막이 **불변 객체(Immutable Object)**와 **방어적 복사(Defensive Copy)**입니다.핵심 개념: Java 불변 객체가 중요한 이유 + 방어적 복사불변(Immutable)이 주는 실무적 이점불변 객체는 “한 번 만들어지면 상태가 바뀌지 않는 객체”입니..

JAVA 2026.02.26

Java 실무에서 자주 쓰는 디자인 패턴 5가지 (Strategy, Factory, Builder, Singleton, Observer)

Java 실무에서 자주 쓰는 디자인 패턴 5가지 (Strategy, Factory, Builder, Singleton, Observer)Java 17 기준으로 실무에서 가장 자주 마주치는 5가지 디자인 패턴을 “왜 쓰는지” 중심으로 정리하고, 바로 실행 가능한 간결한 예제로 감을 잡아봅니다.도입 (문제 상황)기능은 돌아가는데, 요구사항이 조금만 바뀌면 여기저기 if/else가 늘어나고 클래스가 비대해지는 경험을 해보셨을 거예요. “이 정도는 그냥 하드코딩해도 되지 않나?” 싶다가도, 다음 스프린트에 바로 후회하게 되죠. 실무에서 자주 쓰는 디자인 패턴 5가지는 이런 변경 비용을 줄이기 위한 최소한의 도구 세트에 가깝습니다.핵심 개념: Java 실무에서 5가지 패턴이 중요한 이유디자인 패턴은 “정답 코드”..

JAVA 2026.02.26

Java SOLID 원칙 — 코드로 이해하기 (Before/After 예제와 과도한 적용의 함정)

한줄 설명(meta description): Java 17 기준으로 SOLID 5원칙을 Before/After 코드로 빠르게 체감하고, 실무에서 과도한 추상화로 망하는 포인트까지 정리합니다.도입 (문제 상황)리팩토링을 하다 보면 “이 클래스는 책임이 너무 많다”, “확장에 닫혀 있다” 같은 피드백을 종종 받게 됩니다. 그런데 SOLID를 머리로는 알겠는데, 막상 코드로 바꾸려면 어디부터 손대야 할지 막막하실 때가 있어요. 이 글은 각 원칙을 Before/After 코드로 바로 체감하고, 과도한 적용으로 복잡도만 늘어나는 함정까지 함께 짚어봅니다.핵심 개념 (Java SOLID 원칙을 ‘왜’ 적용하는가)SOLID는 “정답 설계”가 아니라, 변경이 생겼을 때 안전하게 고칠 수 있는 코드로 가는 체크리스트에 ..

JAVA 2026.02.25

Java 인터페이스 vs 추상 클래스 실전 구분법 (default 메서드, 다중 구현 패턴까지)

Java 17 기준으로 인터페이스와 추상 클래스를 언제 선택해야 하는지, default 메서드 활용과 다중 구현 패턴을 실전 관점에서 정리합니다.도입 (문제 상황)기능 확장을 하다 보면 “이건 인터페이스로 빼야 할까, 추상 클래스로 묶어야 할까?” 같은 질문을 자주 하게 됩니다. 특히 기존 코드에 공통 로직이 생기거나, 여러 구현체가 섞이기 시작하면 선택이 더 어렵습니다. 오늘은 실무에서 바로 쓰는 구분 기준과 default 메서드, 다중 구현 패턴을 함께 정리해 봅니다.핵심 개념: Java 인터페이스와 추상 클래스, 무엇이 다를까요?인터페이스와 추상 클래스는 둘 다 “구현을 강제한다”는 공통점이 있지만, 설계 의도가 다릅니다.인터페이스는 “이 타입은 이런 능력(계약)을 가졌다”를 표현하기 좋습니다. 구..

JAVA 2026.02.16

Java 상속 vs 조합(Composition) — 실무에서의 선택 가이드

Java에서 extends 상속이 실무에서 왜 위험해질 수 있는지, 조합 우선 원칙과 상속을 써야 할 때의 기준을 예제 코드로 정리합니다. 기능이 비슷해 보여서 extends로 빠르게 붙였는데, 몇 달 뒤 “이 클래스만 예외 처리” 같은 요구가 들어오면서 수정이 폭발한 경험 있으실 거예요. 상속은 한 번 얽히면 풀기 어렵고, 특히 라이브러리 클래스 상속은 예상 못한 동작 변경으로 이어지기도 합니다. 그래서 실무에서는 “상속보다 조합(Composition) 우선”을 자주 원칙으로 둡니다.핵심 개념: Java에서 extends가 위험해지는 지점과 조합 우선 원칙상속은 is-a 관계를 코드로 고정하는 도구입니다. 문제는 요구사항이 바뀌면 is-a가 쉽게 무너진다는 점이에요. 예를 들어 “알림”이 처음엔 이메일..

JAVA 2026.02.16

Java 접근 제어자와 캡슐화 — public/private/protected/default 제대로 쓰기

Java 접근 제어자 범위와 캡슐화의 목적을 실무 관점에서 정리하고, getter/setter 남용을 피하는 방법과 불변 객체 기본 패턴을 예제로 설명합니다. 클래스를 만들다 보면 “일단 public으로 열어두고 나중에 정리할까?”라는 유혹이 자주 생깁니다. 그런데 시간이 지나면 필드가 여기저기서 직접 수정되고, 원인을 찾기 어려운 버그가 늘어나요. 접근 제어자와 캡슐화는 이런 상황을 초기에 막아주는 가장 값싼 안전장치입니다.핵심 개념 (Java 접근 제어자와 캡슐화가 중요한 이유)캡슐화의 핵심은 “데이터(상태)를 숨기고, 의미 있는 동작(행위)만 공개한다”는 겁니다. 비유하자면 자동차 엔진룸을 운전자가 직접 만지게 두는 대신, 페달/핸들처럼 안전한 인터페이스만 제공하는 것과 비슷해요. 접근 제어자는 그..

JAVA 2026.02.15

Java 클래스와 객체 — 왜 나눠야 할까? (설계 기초부터 생성자·this·네이밍까지)

Java 17 기준으로 클래스와 객체를 왜 분리해서 생각해야 하는지, 생성자와 this의 역할, 실무에서 통하는 클래스/필드/메서드 네이밍 컨벤션까지 한 번에 정리합니다. 코드가 커질수록 “그냥 변수 몇 개와 함수 몇 개면 되는데, 왜 굳이 클래스로 나눠야 하지?”라는 생각이 들 때가 있어요. 특히 DTO, 도메인, 서비스가 뒤섞이면 객체지향이 오히려 복잡해 보이기도 합니다. 클래스와 객체를 제대로 구분해서 설계하면, 복잡함이 줄고 변경에 강해집니다.핵심 개념 — Java에서 클래스와 객체를 분리해 생각해야 하는 이유클래스는 **설계도(타입)**이고, 객체는 그 설계도로부터 만들어진 **실체(인스턴스)**입니다. 이 구분이 중요한 이유는 단순히 “문법”이 아니라, **변경을 어디에 가둬둘지(캡슐화)**를..

JAVA 2026.02.14