728x90
반응형
싱글톤 패턴의 예제를 살펴보자.
데이터베이스 연결, 설정, 로깅 시스템에 대해서 예제를 들어보겠다.
데이터베이스, 설정, 로깅 은 스프링을 사용하면 Bean으로 관리되어 싱글톤을 쉽게 유지할 수 있지만 싱글톤 구조를 보기 위해 예제를 살펴보자!
1. 데이터베이스 연결 (이중 체크 락킹 방식)
데이터베이스 연결은 하나의 인스턴스만 유지해야 하므로, 이중 체크 락킹(Double-Checked Locking) 방식이 적절합니다. 이 방식은 멀티스레드 환경에서도 안전하게 인스턴스를 생성할 수 있으며, 필요할 때만 객체를 생성하여 성능을 최적화할 수 있습니다.
예제 코드
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static volatile DatabaseConnection instance;
private Connection connection;
private DatabaseConnection() {
try {
String url = "jdbc:mysql://localhost:3306/mydb";
String user = "root";
String password = "password";
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException("Database 연결 실패", e);
}
}
public static DatabaseConnection getInstance() {
if (instance == null) { // 첫 번째 체크
synchronized (DatabaseConnection.class) {
if (instance == null) { // 두 번째 체크
instance = new DatabaseConnection();
}
}
}
return instance;
}
public Connection getConnection() {
return connection;
}
}
설명
- private static volatile DatabaseConnection instance;
- volatile 키워드를 사용하여 JVM의 명령어 재정렬을 방지합니다.
- 이로 인해 여러 스레드가 동시에 접근하더라도 잘못된 객체가 반환되지 않습니다.
- 이중 체크 락킹(Double-Checked Locking) 적용
- if (instance == null)를 먼저 체크하여 불필요한 synchronized 비용을 줄입니다.
- 동기화 블록(synchronized) 내부에서도 다시 한 번 instance == null을 확인하여 객체 생성의 중복을 방지합니다.
- private DatabaseConnection()
- 생성자를 private으로 설정하여 외부에서 직접 객체를 생성하지 못하도록 합니다.
- DriverManager.getConnection()을 이용하여 DB 연결을 설정합니다.
- public Connection getConnection()
- 생성된 Connection 객체를 반환하여 데이터베이스 연결을 사용할 수 있도록 합니다.
2. 설정 클래스 (enum 방식)
설정 클래스는 애플리케이션 전역에서 동일한 설정 값을 유지해야 하며, 한 번 설정되면 변경되지 않는 경우가 많습니다.
이러한 경우 enum을 사용하면 싱글톤을 안전하게 구현할 수 있습니다.
예제 코드
public enum AppConfig {
INSTANCE;
private String appName;
private int maxConnections;
AppConfig() {
// 기본 설정
this.appName = "MyApp";
this.maxConnections = 100;
}
public String getAppName() {
return appName;
}
public int getMaxConnections() {
return maxConnections;
}
public void setAppName(String appName) {
this.appName = appName;
}
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
}
public class Main {
public static void main(String[] args) {
AppConfig config = AppConfig.INSTANCE;
System.out.println(config.getAppName()); // MyApp
config.setAppName("NewApp");
System.out.println(config.getAppName()); // NewApp
}
}
설명
- enum을 사용하여 싱글톤을 구현하면 객체가 단 한 번만 생성됩니다.
- 자바에서는 enum을 통해 싱글톤을 구현할 경우 리플렉션(Reflection) 및 직렬화(Serialization) 공격을 방지할 수 있습니다.
- INSTANCE라는 단일 인스턴스만 존재합니다.
- 설정 값 관리
- 기본 설정 값을 생성자에서 초기화합니다.
- setAppName() 및 setMaxConnections()를 사용하여 값을 변경할 수 있습니다.
3. 로깅 시스템 (이중 체크 락킹 방식)
로깅 시스템도 하나의 인스턴스를 유지하는 것이 좋으며, 멀티스레드 환경에서도 안전해야 합니다. 따라서 이중 체크 락킹 방식을 사용합니다.
예제 코드
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
public class Logger {
private static volatile Logger instance;
private PrintWriter writer;
private Logger() {
try {
writer = new PrintWriter(new FileWriter("app.log", true));
} catch (IOException e) {
throw new RuntimeException("로그 파일 생성 실패", e);
}
}
public static Logger getInstance() {
if (instance == null) { // 첫 번째 체크
synchronized (Logger.class) {
if (instance == null) { // 두 번째 체크
instance = new Logger();
}
}
}
return instance;
}
public void log(String message) {
writer.println(LocalDateTime.now() + " - " + message);
writer.flush();
}
}
설명
- private static volatile Logger instance;
- volatile 키워드를 사용하여 멀티스레드 환경에서도 안전하게 객체를 생성합니다.
- 이중 체크 락킹 적용
- synchronized 블록을 사용하여 동기화 비용을 최소화하면서도 객체 생성의 중복을 방지합니다.
- 파일 기반 로깅
- FileWriter와 PrintWriter를 사용하여 로그를 app.log 파일에 저장합니다.
- flush()를 호출하여 즉시 파일에 반영되도록 합니다.
- 사용 방법
public class Main {
public static void main(String[] args) {
Logger logger = Logger.getInstance();
logger.log("애플리케이션 시작");
logger.log("로그 시스템 정상 동작");
}
}
정리
싱글톤 적용 대상구현 방식선택 이유
데이터베이스 연결 | 이중 체크 락킹 방식 | 멀티스레드 환경에서 안전한 객체 생성을 보장하면서, 필요할 때만 객체를 생성하여 성능 최적화 |
설정 클래스 | enum 방식 | enum을 사용하면 리플렉션 및 직렬화 공격 방지, JVM이 단 한 번만 생성하도록 보장 |
로깅 시스템 | 이중 체크 락킹 방식 | 멀티스레드 환경에서도 안전한 로깅을 보장 |
이렇게 하면 안전하고 효율적인 싱글톤 패턴을 활용하여 애플리케이션을 개발할 수 있습니다.
#Java #자바 #싱글톤패턴 #SingletonPattern #JavaDesignPatterns
#이중체크락킹 #Enum싱글톤 #DB연결 #로깅시스템 #설정클래스
#멀티스레드 #Java개발 #객체지향프로그래밍 #OOP #JavaBestPractices
#SpringBoot #백엔드개발 #Java프로젝트 #자바디자인패턴
728x90
반응형
'프로그래밍 > JAVA' 카테고리의 다른 글
Java tryLock() 사용 방법 (Java ReentrantLock) (0) | 2025.03.03 |
---|---|
Java 멀티스레드 완벽 정리! 싱글 스레드와의 차이점부터 구현 방법까지 (0) | 2025.03.02 |
Java 싱글톤 패턴 완벽 정리! 개념부터 구현까지 총정리 (Singleton Pattern) (0) | 2025.03.01 |
Java 디자인 패턴 완벽 정리 | 개념, 종류, 사용 이유 (0) | 2025.03.01 |
Java SOLID 원칙 완벽 정리: SRP, OCP, LSP, ISP, DIP 개념과 예제 (0) | 2025.03.01 |
댓글