Home
게임과 개발사이
Cancel

개인 프로젝트 MSA 전환 - (6) Circuit Breaker와 Fallback을 활용한 장애 복구

MSA 환경에서 하나의 서비스 장애가 전체 시스템에 영향을 미치는 상황을 방지하기 위해 Circuit Breaker 패턴이 자주 사용됩니다. 이번 포스팅에서는 Spring Cloud + Resilience4j를 사용하여 장애 발생 시 자동으로 우회하거나, 예외를 처리하는 구조를 어떻게 구성했는지 정리해보겠습니다. ✅ Circuit Breaker란...

개인 프로젝트 MSA 전환 - (5) Config Server를 활용한 설정 관리

MSA 구조에서 각 서비스는 독립적으로 배포되고 실행되기 때문에, 서비스마다 설정 파일(application.yml)을 따로 관리해야 합니다. 하지만 서비스가 많아질수록 설정 파일의 중복, 불일치, 보안 이슈 등 다양한 문제가 생깁니다. 이번 포스팅에서는 Spring Cloud Config Server를 도입해 설정 파일을 중앙에서 일괄 관리...

개인 프로젝트 MSA 전환 - (4) OpenFeign을 활용한 서비스 간 통신 구현

MSA 구조에서는 서비스들이 독립적으로 운영되기 때문에, 서로 간에 데이터를 주고받을 일이 굉장히 많습니다. 이번 글에서는 서비스 간 통신을 훨씬 더 쉽게 만들어주는 OpenFeign을 활용해서, 실제로 어떻게 구현했는지 정리해보려 합니다. ✅ MSA 환경에서의 서비스 간 통신 MSA에서는 다음과 같은 다양한 방식으로 다른 서비스에 요청...

개인 프로젝트 MSA 전환 - (3) Service Discovery + Api Gateway 적용

MSA 구조에서는 각 서비스들이 독립적으로 존재하기 때문에,이들 간의 원활한 통신을 위해 Service Discovery와 API Gateway가 필요합니다. 서비스 디스커버리는 각 서비스의 위치를 찾는 방법을 제공하고, API 게이트웨이는 클라이언트와 서비스 간의 통신을 관리합니다. 이 두 가지를 요소를 MSA에 적용해보겠습니다. ✅ Serv...

개인 프로젝트 MSA 전환 - (2) 멀티 모듈 구성

기존 제 프로젝트는 단일모듈로 구성되어 있었고 이를 멀티모듈로 구성하여 MSA로 전환해보겠습니다. ✅ 멀티 모듈 이란? 멀티 모듈은 여러 개의 모듈을 하나의 프로젝트로 관리하는 방법입니다. 여러 개의 모듈을 하나의 프로젝트로 관리하면, 각 모듈을 독립적으로 관리할 수 있습니다. 즉, MSA 구조에서는 각 마이크로서비스를 하나의 모듈로...

개인 프로젝트 MSA 전환 - (1) MSA에 대해 알아보자

MSA를 개인적으로 공부하며, 제 개인 프로젝트인 가계부 웹을 MSA로 전환해보기로 했습니다. 현재 가계부 웹은 모놀리식으로 구성되어 있습니다. 아래는 제 가계부 웹의 ERD 입니다. ✅ Monolithic Architecture 모놀리식 아키텍처는 모든 기능과 서비스를 하나의 단일 애플리케이션으로 통합하여 개발하는 아키텍처 패턴입니다...

Redis Lettuce SETNX 정리

분산락을 구현하기 위해 Redis의 SETNX는 자주 사용된다. 어떤 상황에서 적용하면 좋은지, 어떤식으로 사용하는지 정리해보겠다. ✅ SETNX란? SETNX는 Redis의 명령어 중 하나로, SET Not Exists의 약자이며, 키가 존재하지 않을 때만 값을 설정하는 명령어이다. 즉, 키가 존재하지 않을 때만 값을 설정하고, 키가 존재...

HikariCP + Tibero Network Timeout 해결하기

이 글은 간혈적으로 발생하던, Tibero Connection의 Network Timeout 이슈로 문제 정의부터 해결한 과정을 담았습니다. ✅ 개발 환경 SpringBoot 2.6.2 Tibero 6.0 HikariCP 4.0.3 Java 8 ✅ 문제 상황 📌 증상 서비스에서 간헐적으로 DB 연결 대기가 15분 이...

VisualVM SSH 터널링 후 모니터링하기i

VisualVM을 사용하여 SSH 터널링을 설정하고, 원격 서버의 JVM을 모니터링하는 방법을 알아보겠습니다. 이 포스팅은 다음과 같은 경우에 유용할 것으로 예상됩니다. 원격 서버의 포트를 외부로 열지 못할 경우 원격 서버의 SSH에 접속할 수 있는 경우 ✅ jar 옵션 추가 -Dcom.sun.management.jmxremote \...

HikariCP 설정

✅ Connection Pool이란? Connection Pool은 데이터베이스 연결을 미리 생성해 두고, 요청이 들어올 때마다 미리 생성해 둔 연결을 제공하는 기술이다. 데이터베이스 연결은 생성하는 데 시간이 오래 걸리기 때문에, 매 요청마다 연결을 생성하면 성능이 저하된다. Connection Pool은 이러한 문제를 해결하기 위해 연결을...

Spring WebFlux의 주요 개념, Netty와 Tomcat의 차이 및 실용적 적용

현대의 웹 애플리케이션은 고성능과 확장성을 필수로 요구하는데, 이를 효과적으로 지원하기 위해 Spring WebFlux가 등장했다. WebFlux는 Spring 5부터 도입된 리액티브 프로그래밍 기반의 웹 프레임워크로, 비동기 및 논블로킹 방식으로 동작하여 더 많은 요청을 처리할 수 있는 확장성을 제공한다. 이는 전통적인 Spring MVC와는 상...

도메인 엔티티, 영속성 엔티티 꼭 분리해야 되는가

✅ 개요 클린 아키텍처의 관점에선 도메인과 엔티티를 분리하는 것은 중요한 설계 전략이다. 분리하면 시스템의 결합도를 낮추고 재사용성을 높일 수 있지만, 실제 개발에서는 이들 엔티티를 분리한 뒤 다시 통합하게 되는 경우도 있다. 이번 포스팅에서는 개인 프로젝트에서 실제 도메인 엔티티와 영속성 엔티티를 분리한 이유와 다시 통합하는 이유를 정리해보겠...

Kafka vs RabbitMQ

현대 웹 애플리케이션은 성능과 확장성 요구가 커지고 있습니다. 비동기 처리와 이벤트 기반 아키텍처는 이를 해결하는 중요한 방식입니다. 동기 처리보다 비동기 처리는 대규모 트래픽과 복잡한 로직 처리에 더 적합합니다. 이 글에서는 비동기 처리의 필요성과 RabbitMQ, Apache Kafka를 사용해 성능과 확장성을 개선하는 방법을 설명합니다. ...

Linux 자주 쓰는 명령어 정리

리눅스를 사용하면서 자주 사용하는 명령어를 정리해보았습니다. ✅ 리눅스 명령어 정리 📌 파일 및 디렉토리 관련 # 현재 디렉토리 확인 pwd # 디렉토리 이동 cd [디렉토리명] # 디렉토리 생성 mkdir [디렉토리명] # 파일 생성 touch [파일명] # 파일 복사 cp [원본파일명] [복사파일명] # 파일 이동 mv [원본파일명...

인덱스 설계와 쿼리 튜닝의 트레이드오프

데이터베이스 성능 최적화는 하지만 최적화를 추구하다 보면 다른 측면에 부정적인 영향을 미칠 수 있다. 인덱스 설계와 쿼리 튜닝은 성능 개선에 핵심적인 역할을 하지만,이 과정에서 비용, 복잡성, 유지보수성 측면에서 트레이드오프가 발생할 수 있다. 이번 글에서는 인덱스 설계와 쿼리 튜닝 과정에서 생기는 트레이드오프를 알아보자. ✅ 데이터베이스...

서버 모니터링 구축[Docker, Prometheus, Grafana, Loki]

모니터링 시스템 구축을 하는 사람들에게 도움이 되고자 작성합니다. 모든 내용을 친절하게 설명하지는 않습니다.. 상황에 따라 요구사항과 구현 방법이 달라질 수 있으며, 이 글은 모니터링 시스템 구축에 초점을 맞추므로, 부수적인 설명은 간략하게 다루겠습니다. 먼저 완성시 최종 Grafana 대시보드를 보여드리겠습니다. 여유가 되신다면 서버 스...

Docker-Compose 명령어 정리

도커컴포즈를 사용하면서 자주 사용하는 명령어를 정리해보았습니다. ✅ 도커 명령어 정리 📌 도커 컴포즈 실행 docker-compose up -d -d: 백그라운드 실행 -f: 컴포즈 파일 지정 -p: 프로젝트 이름 지정 --build: 이미지 빌드 --force-recreate: 컨테이너 강제 재생성 --no-d...

AWS EC2 스왑메모리 할당

AWS EC2 인스턴스에 스왑메모리를 할당하는 방법을 알아보자. 프리티어 기준으로 RAM 1GB까지 사용이 가능하다. 서버를 가동하다보면 메모리 부족으로 인한 서버 다운이 발생할 수 있는데, 이때 스왑메모리를 할당하여 메모리 부족을 방지할 수 있다. ✅ 스왑 공간 크기 계산 RAM 크기 권장 스왑 ...

Spring Security FilterChain 등록시 주의사항

webIgnorePatterns + FilterChain을 등록할 때 주의할 점을 알아보자. ✅ 문제 상황 // 필터 빈 등록 @Component class JwtAuthenticationFilter extends OncePerRequestFilter { } // 필터 등록 .addFilterBefore(jwtAuthenticatio...

Docker 명령어 정리

도커를 사용하면서 자주 사용하는 명령어를 정리해보았습니다. ✅ 도커 명령어 정리 📌 도커 컨테이너 실행 docker run -d -p 8080:8080 --name container_name image_name -d: 백그라운드 실행 -p: 포트 매핑 --name: 컨테이너 이름 image_name: 이미지 이름 con...

Component + MockBean 사용시 주의사항

개발하던 중 갑자기 특정 도메인의 모든 테스트 코드가 불통이 됐다 (Service + Controller 계층) 실제 서버를 실행하고 API을 호출하면 정상적으로 응답이 되는데 테스트코드를 돌릴때만 에러가 발생했다…. 디버깅하고 확인해보니 @Component + @MockBean 사용시 발생하는 문제였다… 원인 분석과 해결 과정을 정리 ...

Mockito 프레임워크 정리

Mockito를 사용하면 테스트를 진행할 때, 외부 의존성을 가진 객체를 Mocking하여 테스트를 진행할 수 있다. 이번 포스팅에서는 Mockito를 사용하여 테스트를 진행하는 방법을 정리해보겠다. ✅ Mocking이란? Mocking은 테스트를 진행할 때, 외부 의존성을 가진 객체를 Mocking하여 테스트를 진행하는 방법이다. 실게...

MySQL 실수로 날린 데이터 복구하기

실수로 날린 데이터를 바이너리 로그를 활용하여 복구하는 방법에 대해 알아보겠습니다. 참고로 아래 예제는 한개의 바이너리 로그 파일 안에 모든 쿼리가(insert, truncate) 다 들어있다는 가정하에 진행됩니다. Drop, Turncate, Delete, Update 등 데이터에 변화를 줄 수 있는 쿼리는 꼭!! 트랜잭션 을 걸고 실행하길 바랍니다...

동서싱 이슈 해결 방법

해당 글은 재고시스템으로 알아보는 동시성 이슈 해결 방법 강의를 정리한 글입니다. 정리 코드: 깃허브 링크 개발 환경 Java 17 Spring boot 3.2.3 redis docker mysql jpa lombok ✅ 동시성 이슈란? 동시에 여러 개의 스레드, 프로세스 또는 작업이 공유된 자원에 접근하...

Graceful Shutdown 동작 과정

Spring Boot Application에서 Controller가 요청을 처리하고 응답이 되지 않았는데 종료요청이 오면 어떻게 될까요? Client는 응답을 받지 못하고 timeout이 발생합니다. 해당 상황을 예방하기 위하여 Graceful Shutdown에 대해 알아보겠습니다. ✅ Graceful Shutdown이란? Grace...

JPA N+1 발생 원인 및 해결방법

JPA를 사용한다면 한번쯤은 마주쳤던, 또는 들어 봤던 문제입니다. 바로 N+1 문제인데요. 원인과 해결방법을 알아보겠습니다. N + 1 문제란? JPA에서 연관 관계가 설정된 엔티티 사이에서 한 엔티티를 조회하였을 때 조회된 엔티티의 개수(N개)만큼 연관된 엔티티를 조회하기 위해추가적인 쿼리가 발생하는 (+1) 문제를 의미합니다. 지연...

Transaction 롤백 동작 및 시나리오 정리

Unchecked Exception 발생 시에는 롤백 되지만, Checked Exception 발생 시에는 롤백되지 않는건 유명한 정보이다. 하지만 예외를 catch 했을때 어떤식으로 처리가 되는지는 햇갈려서 케이스별로 정리해 보려고 한다. 스프링에서 지원해주는 전파속성은 위와 같이 많이 존재하지만 실제로 자주 사용하는 REQUIRED, RE...

Java HashMap 동작 방식

Java HashMap은 어떻게 동작하는가? 이번 글에서는 Java 7, Java 8에서 HashMap이 어떻게 구현되어 있는지 알아보겠습니다. Java에서는 HashTable을 구현할 때 어떻게 충돌 가능성을 줄이고 성능을 향상시키려 했는지에 대해 중점을 두어 정리해보겠습니다. HashMap과 HashTable public class ...

Jenkins + Nginx 무중단 배포

✅ 왜 무중단 배포를 해야할까? 무중단 배포란 소프트웨어 또는 웹 애플리케이션을 업데이트하거나 새로운 버전을 배포할 때, 중단 없이 서비스를 계속 제공하는 배포 방식을 말하며 기존의 서비스가 동작하면서 새로운 업데이트가 이루어지기 때문에 사용자들은 전환 과정에서 서비스 중단을 경험하지 않게 된다. 배포할때마다 서버가 멈추게 된다면 많은 문제들이 ...

POI 라이브러리 OOM 해결과정

팀장님 으로부터 요청이 들어왔다. (회원 통계 엑셀 생성 프로그램 제작) SQL로 쿼리 결과를 하나 하나 엑셀에 대입 해주고 있는데 시간이 너무 오래 걸려서 요청하심 (3시간 이상 소요) 제작 후 Local, Dev 에서 테스트 후 운영에서 실행 하자마자 엑셀이 생성이 안된다는 응답이 왔다..! 원인 분석과 해결 과정을 정리 해보자. ...

프로그래머스 - 미로 탈출

미로 탈출 문제 바로가기 풀이 위 문제는 최단거리 알고리즘을 이용하며 풀면된다. 먼저 레버까지의 최단거리를 찾고, 출구까지의 최단거리를 찾아주면 된다. import java.util.LinkedList; import java.util.PriorityQueue; import java.util.Queue; class Solution { i...

MVC, MVP, MVVM 패턴 비교

MVC(Model-View-Controller) 패턴 모델(Model): 애플리케이션의 데이터와 비즈니스 로직을 담당한다. 뷰(View): 사용자에게 데이터를 보여주는 역할, 사용자 인터페이스를 표현하고 모델의 정보를 표시한다. 컨트롤러(Controller): 모델과 뷰 사이의 상호 작용을 관리, 뷰에서 데이터를 받아 모델에게 전달한다...

이터레이터 패턴(Iterator Pattern)

이터레이터 패턴이란? 컬렉션의 요소를 순차적으로 접근하거나 탐색하기 위한 디자인 패턴 중 하나이다. 컬렉션 내부 구조에 대한 세부 정보를 숨기고, 일관된 방법으로 요소에 접근할 수 있는 방법을 제공한다. 구성 요소 이터레이터(Iterator): 요소를 순차적으로 접근하거나 탐색하는 데 사용되는 인터페이스 컬렉션(Collecti...

옵저버 패턴(Observer Pattern)

옵저버 패턴이란? 객체의 상태 변화가 다른 객체들에게 자동으로 통지되는 패턴 구성요소 Subject(주체): 상태가 변경될 때 알림을 보내는 주체, 옵저버 객체들을 등록, 삭제하고 상태가 변경될 때 옵저버들에게 알림을 보냄 Observer(옵저버): 주체의 상태 변화를 관찰하고 이에 반응하는 객체, 이들은 주체에 등록되어 있으며 ...

전략 패턴(Strategy Pattern)

전략 패턴이란? 실행중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 패턴이다. 전략 패턴은 OOP의 집합체 GOF의 디자인 패턴 책에서는 전략 패턴을 다음과 같이 정의한다. 동일 계열의 알고리즘군을 정의하고 -> 전략 구현체로 정의 각각의 알고리즘을 캡슐화하여 -> 인터페이스로 추상화 ...

팩토리 메서드 패턴(Factory Method Pattern)

팩토리 메서드 패턴이란? 객체의 생성을 캡슐화 하는 패턴이다. 구체적인 객체의 생성 과정을 팩토리로 모듈화하여 구체적인 부분이 아닌 추상적인 부분에 의존할 수 있도록 한다. 팩토리 메서드 패턴과 추상 팩토리 패턴이 존재한다. 객체를 생성할 때 어떤 클래스의 인스턴스를 만들 지 서브 클래스에서 결정하게 한다. 장단점 장점 캡...

싱글톤 패턴(Singleton Pattern)

싱글톤 패턴이란? 특정 클래스가 단 하나만의 인스턴스를 생성하여 사용하기 위한 패턴 생성자를 여러 번 호출하더라고 하나의 인스턴스를 보장해준다. Socket Connection, DB JDBC Connection, Spring Bean 등 사용 장단점 장점 유일한 인스턴스: 인스턴스는 앱 전역에서 단 하나만을 보장해주기 때문에...

디자인 패턴 정리

디자인 패턴은 무수히 많다 그 중 대표적인 GoF 디자인 패턴에 대해 알아보자 싱글톤 패턴 (SingleTon Pattern) 객체를 하나만 만들어 사용하는 패턴 Socket Connection, DB JDBC Connection, Spring Bean 등 사용 public class Singleton { private Sin...

가비지 컬렉션 정리

Garbage Collection(GC) 이란? JVM(자바 가상 머신)의 Heap 영역에서 필요 없게 된 객체를 삭제해주는 프로세스 객체가 접근 불가능한 상태(Unreachable)가 되었을 때, 메모리가 누적되므로 이를 수거해줌 그럼 이런 의문이 들 수도 있다. 왜 메모리 관리를 해줘야 돼?.. 다음의 예시를 보자 for (i...

interview - operated

프로세스, 스레드 차이 프로세스 운영체제로부터 자원을 할당받는 작업의 단위 프로세스 간의 통신은 IPC(Inter-Process Communication)을 사용 프로세스는 각각 독립된 메모리 영역을 할당받는다. 프로세스 간의 전환...

interview - database

DBMS란 무엇인지, DB를 사용하는 이유 여러 사용자가 DB에 접근해 사용할 수 있도록 하는 소프트웨어를 의미 파일의 데이터 중복, 비일관성, 검색 등의 문제를 해결할 수 있다. DB 특징에 대해 설명 실시간 접근성(Real-Time Accessibilit...

interview - structure

interview - spring

Spring이란? 자바 오픈소스 프레임워크 중 하나이다. 스프링 컨테이너로 자바 객체를 관리하며 DI와 IoC를 통해 결합도를 낮출수 있다. AOP를 통해 공통 기능을 분리하여 관리할 수 있다. Spring DI/IoC 동작방식 스프링 프레임워크는 느슨한 ...

interview - network

OSI 7계층이란? 네트워크에서 통신이 일어나는 과정을 단계별로 나눈 것 물리계층 전기적, 물리적 세부 사항을 정의하는 계층 리피터, 허브 데이터링크 같은 ...

interview - java

Java 특징 객체지향 프로그래밍 언어 기본 자료형을 제외한 모든 요소가 객체로 표현 JVM에서 동작하기 때문에 운영체제에 독립적 GC를 통한 자동 메모리 관리 다중 상속이나 타입에 엄격하며, 제약이 많음 클래스,겍채,인스턴스 차이 ...

chapter7 - 병렬 데이터 처리와 성능

Java7 이전 데이터 컬렉션을 병럴로 처리하기가 어려웠음 1) 데이터를 서브파트 분할 2) 분할된 서브파트를 각각의 스레드로 할당 3) 의도치 않은 race condition이 발생하지 않도록 적절한 동기화 작업 4) 부분 결과를 합침 Java7 이후 fork/join 프레임워크 제공 더 쉽게 병렬화를 수행하며 ...

chapter5 - 스트림 활용

5.1 필터링 5.1.1 프레디케이트로 필터링 filter 메서드는 프레디케이트를 인수로 받아서 프레디케이트와 일치하는 모든 요소를 포함하는 스트림을 반환한다. List<Dish> vegetarianMenu = menu.stream() .filter(Dish::isVegetarian) .colle...

chapter4 - 스트림 소개

스트림이란 무엇인가? 스트림은 Java 8 API에 새로 추가된 기능이다. 스트림을 이용하면 선언형(데이터를 처리하는 임시 구현 코드 대신 질의로 표현하는 방법)으로 컬렉션 데이터 처리가 가능하다. 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다. 기존코드 -> 스트림 사용 예제 기존 코드 ...

chapter3 - 람다표현식

3.1 람다란 무엇인가? 메서드로 전달할 수 있는 익명 함수를 단순화 시킨 것 파라미터 + 화살표 + 바디로 이루어진다. 람다의 특징 익명 보통의 메서드와 달리 이름이 없으므로 익명 함수 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다. ...

chapter2 - 동적 파라미터화 코드 전달하기

유저가 어떤 상황에서 일을 하든 소비자 요구사항은 항상 바뀐다. 변화하는 요구사항에 맞춰 엔지니어링적인 비용을 최소화 하며, 그뿐 아니라 새로 추가한 기능은 쉽게 구현할 수 있어야 하며 장기적인 관점에서 유저보수가 쉬워야 한다. 동적 파라미터를 이용하면 이문제에 효과적으로 대응할 수 있다. 동적 파라미터란? 어떻게 실행할 것인지 결정하지 않은...

chapter1 - 자바 8,9,10,11 무슨 일이 일어나고 있는가?

1.1 역사의 흐름은 무엇인가? 자바 역사를 통틀어 가장 큰 변화가 자바 8에서 일어났다. 자바 버전이 올라감에 따라 생긴 크고 작은 변화 덕분에 프로그램을 더 쉽게 구현할 수 있게 되었다. ex) 사과 무게순 정렬 고전적 코드 Collections.sort(inventory, new Comparator<Apple>() {...

Item 30 - 이왕이면 제네릭 메서드로 만들라

제너릭 메서드 메서드의 선언부에 제너릭한 타입이 선언된 메서드 public static <E> Set<E> Union(Set<E> s1, Set<E> s2){ Set<E> result = new HashSet<>(s1); result.addAll(s2); return...

Item 29 - 이왕이면 제너릭 타입으로 만들라

기존에 구현되어 있는 Object 기반의 스택 클래스를 보자 public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack(){ ...

Item 28 - 배열보다는 리스트를 사용하라

배열과 리스트(제너릭 타입)의 차이 1. 배열 (Array) 1) 배열은 함께 변한다. 즉, 공변(convariant)이다. Sub extends Super인 경우, Sub[] extends Super[]이다. class Sub extends Super { } Super[] superman = new Sub[1]; 2) 배열은 실체화(re...

Item 27 - 비검사 경고를 제거하라

제네릭을 사용하기 시작하면 수많은 컴파일러 경고를 볼 수 있음. 컴파일러 경고 예시) 비검사 형변환 경고, 비검사 메서드 호출 경고, 비검사 매개변수화 가변인수 타입 경고, 비검사 변환 경고 등 자바 7부터 지원하는 다이아몬드 연산자(<>)를 사용하면 타입 매개변수를 추론 가능. 할 수 있는 한 비검사 경고를 제거해서 ClassC...

Item 26 - 로 타입은 사용하지 말라

1. 제너릭이란? (Generic type) 클래스 내부에서 사용할 데이터 타입을 나중에 인스턴스를 생성할 때 확정하는 것. 클래스와 인터페이스 선언에 타입 매개변수가 쓰이면 이를 제너릭 클래스 혹은 제너릭 인터페이스라 한다. ex) List 인터페이스 public interface List<E> extends Collection<E...

Item 25 - 톱레벨 클래스는 한 파일에 하나만 담으라

A top level class is a class that is not a nested class. A nested class is any class whose declaration occurs within the body of another class or interface. 출처 : Oracle docs Chapter 8.Clas...

Item 24 - 멤버 클래스는 되도록 static으로 만들라

이 아이템에서는 각각의 중첩 클래스를 언제, 왜 사용해야하는지 얘기하고 있다. 중첩클래스란? 중첩 클래스(nested class): 다른 클래스 안에 정의된 클래스 정적 멤버 클래스 (비정적) 멤버 클래스 익명 클래스 지역 클래스 정적 멤버 클래스를 제외한 나머지는 내부 클래스(inner class)이다. 1. 정적 멤버 클래스...

Item 23 - 태그 달린 클래스보다는 클래스 계층구조를 활용하라

태그 달린 클래스 태그 클래스란 두가지 이상의 의미를 표현할 때 그 중 현재 표현하는 의미를 태그값으로 알려주는 클래스 class Figure { enum Shape { RECTANGLE, CIRCLE } // 태그 필드 final Shape shape; // RECTANGLE 용 필드 ...

Item 22 - 인터페이스는 타입을 정의하는 용도로만 사용하라

인터페이스는 타입을 정의하는 용도로만 사용해야한다. 상수 공개용 수단으로 사용하지 말자. 인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 클래스가 어떤 인터페이스를 구현한다는건, 인스턴스로 무엇을 할 수 있는지를 클라이언트를 알려주는 행위 안티패턴 - 사용 금지 메서드 없이, 상수를 뜻하는 static final ...

Item 21 - 인터페이스는 구현하는 쪽을 생각해 설계하라

인터페이스에서 새로운 메소드를 추가하면 기존의 구현체들에 영향이 가게 된다. 이러한 문제를 해결하여 새로운 메소드를 추가할 수 있도록 한 것이 자바 8 부터 등장한 default 메소드이다. default 메소드 public interface JavaStudyable { // ~able 네이밍 규칙을 가진다. public abstract voi...

Item 20 - 추상 클래스보다는 인터페이스를 우선하라

자바는 단일 상속만 지원하니, 추상 클래스 방식은 새로운 타입을 정의하는 데 커다란 제약을 안고 있다. 반면 인터페이스는 여러개를 구현(implement) 할 수 있으며 어떤 클래스를 상속했든 같은 타입으로 취급된다. 따라서 추상클래스 보다는 인터페이스를 우선으로 하여 구현하는것을 권장한다. 인터페이스의 장점 기존 클래스에도 손쉽게 새로운 인터페이스...

Item 19 - 변상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라

상속을 염두에 두지 않은 외부 클래스(주: 프로그래머의 통제권 밖에 있어 변경 시점을 알 수 없는 클래스)를 상속할 경우 여러 문제가 발생할 수 있다. 상속을 고려한 설계와 문서화는 정확히 무얼 뜻할까? 1. 재정의 메서드 문서화 상속이 목적인 클래스를 설계한다면 기능 확장 및 재정의할 수 있는 메서드들이 내부적으로 어떻게 이용되는지 문서로 남겨...

Item 18 - 상속보다는 컴포지션을 사용하라

Item 18 :: 상속보다는 컴포지션을 사용하라 일반적인 구체 클래스를 패키지 경계를 넘어, 즉 다른 패키지의 구체 클래스를 상속하는 일은 위험하다. 이 책에서 말하는 상속이란 클래스가 다른 클래스를 확장하는 구현 상속을 말한다. 상속 관계의 여러 문제점 1. 메소드 호출과 달리 상속은 캡슐화를 깨뜨린다. 상위 클래스가 어떻게 구현되느냐에 따...

Item 17 - 변경 가능성을 최소화하라

필드만 정의된 것 외에는 아무 목적도 없는 클래스를 작성하는 경우가 있을 것이다 public class Point { public double x; public double y; } 클래스의 mutability(상태 변경 가능성)을 최소화하라(Minimize mutability) ex: 불변 복소수 클래스(Immutable complex nu...

Item 16 - public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라

필드만 정의된 것 외에는 아무 목적도 없는 클래스를 작성하는 경우가 있을 것이다 public class Point { public double x; public double y; } 이런 클래스는 외부에서 필드로 직접 접근 할 수 있어 캡슐화의 이점을 제공하지 못한다 또한, 클라이언트 코드 수정 없이는 표현 방식을 바꿀 수도 없고 불변...

Item 15 - 클래스와 멤버의 접근 권한을 최소화하라

내부 구현을 외부 컴포넌트로부터 잘 숨겼다면 잘 설계된 컴포넌트라고 할 수 있다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 개의치 않는 것이다 → 정보 은닉 혹은 캡슐화라는 개념으로 부른다. 정보 은닉은 다음과 같은 장점을 가진다. API를 통해서 다른 컴포넌트와 소통하기 때문에 API를 먼저 설계하고 ...

Item 14 - Comparable을 고려하라

알파벳, 숫자, 연대, 번호 등 순서가 있는 값 클래스를 작성하면 반드시 Comparable 를 구현하자. Comparable 인터페이스는 compareTo() 라는 하나의 메서드를 정의한다. 이 메서드는 Object 메서드가 아니다. 이 메서드의 성격은 Object의 equals와 유사하지만 아래와 같은 차이가 있음 ...

Item 13 - clone 재정의는 주의해서 진행하라

Cloneable 인터페이스란? 복제해도 되는 클래스임을 명시하는 믹스인 인터페이스이다. 믹스인 클래스란? public interface Singer { String sing(String s); } interface Songwriter { String compose(boolean hit); } interface SingerSon...

Item 12 - toString을 항상 재정의하라

toString의 일반 규약 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다. Object의 기본 toString : 클래스_이름@16진수_해시코드 유익하지 않은 경우가 대부분이다. 예시(전화번호) public final class PhoneNumber { // 지역코...

Item 11 - equals를 재정의하려거든 hashCode도 재정의하라.

Object 의 HashCode 규약 애플리케이션이 유지되는 동안 equals비교에 사용되는 정보(핵심필드)가 유지된다면, hashCode는 항상 같은값을 반환해야한다 equals() 로 두 객체를 같다고 판단했다면 두 객체의 hashCode는 똑같은 값을 반환해야한다 equals()가 두 객체를 다...

Item 10 - equals는 일반 규약을 지켜 재정의하라

다음 중 하나에 해당한다면 equals를 재정의하지 않는 것이 최선이다. 각 인스턴스가 본질적으로 고유하다. Ex) Thread 인스턴스의 ‘논리적 동치성(logical equality)’을 검사할 일은 없다. Ex) Pattern equals를 재정의하여 두 Pattern의 인스...

Item 9 - try-finally 보다는 try-with-resources를 사용하라

자바 라이브러리에서 close 메서드를 호출해 직접 닫아줘야 하는 자원 예시 : InputStream, OutputStream, java.sql.Connection 등 자원 닫기는 예측할 수 없는 성능 문제로 이어져 finalizer을 사용하지만 썩 믿음직스럽지 못하다. 코드 9-1. try-finally 더 이상 자원을 회수하는 최선의 방책이 아...

Item 8 - Finalizer와 Cleaner는 피하라

finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. 오동작, 낮은 성능, 이식성 문제의 원인이 되기도 한다. Finalizer를 유용하게 쓸 수 있는 경우는 극히 드물다. 딱 두가지의 경우에 적용을 고려할만하다. 자원의 소유자가 Close 메서드를 호출하지 않는 것에 대한 안전망 역할로 자원을 반납하고자 하...

Item 7 - 다 쓴 객체 참조를 해제하라

메모리 직접 관리 자바에 GC(가비지 콜렉터)가 있기 때문에 메모리 관리에 대해 신경쓰지 않아도 될거라 생각하기 쉽지만 그렇지 않다. 다음 코드를 살펴보자. // 코드 7-1 메모리 누수가 일어나는 위치는 어디인가? (36쪽) public class Stack { private Object[] elements; private int si...

Item 6 - 불필요한 객체 생성을 피하라

똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을때가 많다. 재사용은 빠르고 세련되다. 특히 불변 객체(아이템 17)는 언제든 재사용할 수 있다. 잘 못된 객체 생성 예 String s = new String("bikini"); // 개선된 버전 - 실행될 때마다 하나의 String 인스턴스를 사용 String s = "bi...

Item 5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

많은 클래스는 하나 이상의 자원에 의존한다. 이 책에서는 맞춤법 검사기인 SpellChecker와 dictionary를 예로 들고있다. 즉, SpellChecker가 dictionary를 사용하고, 이를 의존 하는 리소스 또는 의존성이라고 부른다. 이때 SpellChecker를 다음과 같이 구현하는 경우가 있다. 부적절한 구현 static 유틸 클래...

Item 4 - 인스턴스화를 막으려거든 private 생성자를 사용하라

정적 메서드와 정적 필드만을 담은 클래스를 만드는 이유 java.lang.Math, java.util.Arrays 처럼 기본 타입 값이나 배열 과련 메서드를 모아놓을 수 있다. java.util.Collections 처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드를 모아놓을 수도 있다. final클래스와 관련한 메서드들을 모...

Item 3 - private 생성자나 열거 타입으로 싱글턴임을 보증하라

싱글턴: 객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미 ex) 함수와 같은 stateless Object(무상태 객체), 설계상 유일해야 하는 시스템 컴포넌트 stateless Object(무상태 객체): 인스턴스 변수가 없는 객체 public class Car { void Car() { ...

Item 2 - 생성자에 매개변수가 많다면 빌더를 고려하라

정적 팩터리와 생성자의 공통적인 제약은 선택적 매개변수가 많을 때 적절히 대응하기 어렵다. 책에서는 NutritionFacts라는 클래스를 예로 들고 있다. 1. 점층적 생성자 패턴(telescoping constructor pattern) 매개 변수가 많을 때 프로그래머들이 주로 사용하는 패턴 telescop는 망원경이라는 뜻. 변수가 늘...

Item 1 - 생성자 대신 정적 팩터리 메서드를 고려하라

정적 팩터리 메서드의 장점 1. 이름을 가질 수 있다. 정적 팩터리 메서드는 생성자보다 읽기 편하다. 하나의 시그니처로는 생성자를 하나만 만들 수 있다. public Student(String studentID, int grade); //가 생성된 상태에서 public Student(String studentID, int GPA); //이렇...