
이 코드를 통해 얻을 수 있는 Benefit(이점), 느낀 점, 그리고 목표를 설명드리겠습니다.
스프링의 데이터베이스 관리 효율성:
외부 설정 관리:
application.properties와 같은 외부 설정 파일을 사용하여, 코드에서 하드코딩을 줄이고 설정 값을 유연하게 관리할 수 있다. 이로 인해 환경 변화나 데이터베이스 연결 정보의 변경에도 쉽게 대응할 수 있다.트랜잭션 관리의 용이성:
@EnableTransactionManagement와 PlatformTransactionManager를 통해 트랜잭션을 일관되게 관리하고, 데이터 일관성과 무결성을 유지하는 방법을 배운다. 트랜잭션 관리는 데이터베이스 작업에서 매우 중요한 부분으로, 이 설정이 자동으로 이루어진다는 점이 큰 이점이다.Hibernate와 JPA의 통합:
스프링의 유연성 및 확장성:
외부 설정의 중요성:
@PropertySource와 @Value 어노테이션을 통해 외부 설정 파일을 활용하는 방식이 애플리케이션의 유연성과 유지보수성을 크게 높여준다. 설정 값을 코드에서 하드코딩하지 않고 외부 파일로 분리하여 관리하는 것이 얼마나 중요한지 다시 한번 깨닫게 되었다.보안과 연결 관리의 중요성:
스프링 프레임워크 심화 학습:
효율적인 데이터베이스 관리 시스템 구축:
코드 가독성과 유지보수성 향상:
보안과 성능을 고려한 애플리케이션 설계:
이러한 이점과 목표를 통해 더 효율적이고 확장성 있는 애플리케이션을 개발하고, 스프링 프레임워크의 다양한 기능을 실제 프로젝트에서 적극 활용하는 개발자가 되는 것을 목표로 할 수 있습니다.
<[Config] DBConfig>
package org.project.backend.config;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
/**
* 데이터베이스 설정을 관리하는 클래스.
* JPA, 트랜잭션 관리, 데이터 소스 설정을 포함한다.
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.project.backend.repository")
@PropertySource("classpath:application.properties")
public class DBConfig {
/**
* 엔티티 매니저 팩토리를 설정하고 Hibernate 관련 속성을 추가한다.
*
* @param dataSource 데이터 소스 (HikariCP)
* @param ddlAuto hibernate.ddl-auto 설정 값 (application.properties에서 읽어옴)
* @param dialect hibernate.dialect 설정 값 (application.properties에서 읽어옴)
* @return LocalContainerEntityManagerFactoryBean 객체
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
@Value("${spring.jpa.hibernate.ddl-auto}") String ddlAuto,
@Value("${spring.jpa.properties.hibernate.dialect}") String dialect) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("org.project.backend.model"); // 엔티티가 위치한 패키지
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
// Hibernate 설정 추가
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", ddlAuto);
properties.setProperty("hibernate.dialect", dialect);
em.setJpaProperties(properties);
return em;
}
/**
* HikariCP를 이용한 데이터 소스를 설정한다.
* MySQL 데이터베이스에 연결되며, 연결 풀의 최대 크기는 10으로 설정된다.
* HikariCP를 쓰는 이유 : https://github.com/brettwooldridge/HikariCP-benchmark
*
* @return DataSource 객체 (HikariDataSource)
*/
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://localhost:3306/baenang");
config.setUsername("root");
config.setPassword("1234");
config.setMaximumPoolSize(10); // 최대 커넥션 풀 크기
return new HikariDataSource(config);
}
/**
* 트랜잭션 매니저를 설정한다.
* EntityManagerFactory를 통해 JPA 트랜잭션을 관리한다.
*
* @param entityManagerFactory 엔티티 매니저 팩토리
* @return PlatformTransactionManager 객체
*/
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
이 코드는 스프링 프레임워크에서 데이터베이스 설정, JPA(Entity 매니저) 및 트랜잭션 관리를 담당하는 구성 파일입니다. 각 줄의 자바 및 스프링 개념을 설명하겠습니다.
package org.project.backend.config;
org.project.backend.config 패키지에 포함되어 있음을 나타낸다.import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
HikariCP, JPA, 트랜잭션 관리 및 데이터베이스 설정에 필요한 클래스들을 임포트한다.@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.project.backend.repository")
@PropertySource("classpath:application.properties")
public class DBConfig {
@Configuration으로 해당 클래스가 스프링 컨텍스트에 빈(bean)으로 등록되고, @EnableTransactionManagement로 트랜잭션 관리가 활성화된다.application.properties 파일에서 설정 값을 가져오고, org.project.backend.repository 패키지의 JPA 리포지토리와 상호작용한다.LocalContainerEntityManagerFactoryBean 빈 선언@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
@Value("${spring.jpa.hibernate.ddl-auto}") String ddlAuto,
@Value("${spring.jpa.properties.hibernate.dialect}") String dialect) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("org.project.backend.model"); // 엔티티가 위치한 패키지
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", ddlAuto);
properties.setProperty("hibernate.dialect", dialect);
em.setJpaProperties(properties);
return em;
}
EntityManagerFactory를 설정하고, 데이터 소스와 Hibernate 관련 속성을 설정한다.@Value를 통해 application.properties에서 Hibernate 설정을 가져온다.HikariDataSource 및 application.properties 파일의 설정 값과 상호작용하며, org.project.backend.model 패키지에 있는 엔티티 클래스를 스캔한다.DataSource 빈 선언@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://localhost:3306/baenang");
config.setUsername("root");
config.setPassword("1234");
config.setMaximumPoolSize(10); // 최대 커넥션 풀 크기
return new HikariDataSource(config);
}
PlatformTransactionManager 빈 선언@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
EntityManagerFactory를 통해 JPA 트랜잭션을 관리한다.EntityManagerFactory와 상호작용하며, 데이터베이스 작업이 원자성을 유지하도록 트랜잭션을 관리한다.@Value 어노테이션:@Value는 외부 설정 파일에서 값을 읽어와 해당 변수에 주입하는 역할을 한다. 이 예제에서는 spring.jpa.hibernate.ddl-auto와 spring.jpa.properties.hibernate.dialect 값을 가져와 Hibernate의 속성을 설정한다.LocalContainerEntityManagerFactoryBean:EntityManagerFactory를 생성하는 데 사용된다. 데이터 소스와 Hibernate 설정을 통해 데이터베이스와 엔티티 객체 간의 매핑을 설정합니다.PlatformTransactionManager는 JPA 트랜잭션을 관리하기 위해 사용됩니다.이 코드는 데이터베이스 설정, JPA 엔티티 매니저 팩토리 및 트랜잭션 관리에 필요한 구성을 모두 포함하고 있습니다. 이러한 설정은 스프링 프레임워크를 사용하는 애플리케이션에서 데이터베이스와의 상호작용을 관리하며, 특히 트랜잭션의 원자성을 보장하여 데이터 일관성을 유지하는 중요한 역할을 합니다.
이 코드 구조를 이해하면 스프링 애플리케이션에서 데이터베이스 설정과 트랜잭션 관리를 어떻게 구성하고 효율적으로 처리할 수 있는지 배우게 됩니다.
Hibernate는 자바에서 널리 사용되는 ORM(Object-Relational Mapping) 프레임워크로, 자바 객체와 관계형 데이터베이스 간의 매핑을 자동으로 처리해 주는 도구입니다. ORM은 객체 지향 프로그래밍 언어의 객체와 관계형 데이터베이스의 테이블 간의 불일치를 해결해 주는 역할을 합니다. Hibernate는 JPA(Java Persistence API) 표준을 구현한 가장 대표적인 프레임워크 중 하나입니다. 주요 기능은 다음과 같습니다.
UPDATE SQL을 작성하지 않아도, 객체 상태 변화만으로 데이터베이스에 변경 사항이 자동 반영됩니다.Hibernate는 자바 애플리케이션에서 데이터베이스와의 상호작용을 단순화하고, 개발 생산성을 높이며, 유지보수를 쉽게 해주는 강력한 도구입니다.
트랜잭션 관리는 데이터베이스 작업을 안전하게 처리하기 위한 중요한 개념으로, 여러 작업이 하나의 논리적인 단위로 묶여 수행되는 것을 보장하는 프로세스를 말합니다. 트랜잭션 관리의 핵심 목적은 데이터의 일관성, 무결성, 신뢰성을 유지하는 것입니다. 트랜잭션 관리의 기본 개념과 동작 방식, 스프링에서의 구현 방식에 대해 설명하겠습니다.
트랜잭션은 하나의 일련의 데이터베이스 작업을 묶어서 하나의 작업처럼 처리하는 것을 말합니다. 트랜잭션 내에서 수행되는 모든 작업은 성공적으로 완료되거나(Commit), 실패 시 전부 취소(Rollback)되는 특성을 가집니다. 즉, 여러 데이터베이스 작업이 트랜잭션으로 묶여 있으면, 그 중 하나라도 실패하면 전체 작업이 취소됩니다.
트랜잭션이 안전하게 처리되기 위해서는 ACID 속성을 만족해야 합니다:
트랜잭션 관리는 이 ACID 속성을 보장하면서 데이터베이스 작업을 관리합니다. 주요 역할은 다음과 같습니다:
스프링 프레임워크는 선언적 트랜잭션 관리와 프로그래밍 방식 트랜잭션 관리를 모두 지원합니다. 스프링에서는 주로 선언적 트랜잭션 관리가 사용됩니다.
스프링에서 선언적 트랜잭션 관리는 트랜잭션을 직접 제어할 필요 없이, 어노테이션을 통해 트랜잭션을 관리합니다. 트랜잭션 처리를 해야 하는 메소드에 @Transactional 어노테이션을 사용하여 트랜잭션 경계를 설정합니다.
@Transactional
public void updateAccountBalance(Long accountId, Double amount) {
Account account = accountRepository.findById(accountId);
account.setBalance(account.getBalance() + amount);
accountRepository.save(account);
} 위의 코드에서는 updateAccountBalance 메소드가 트랜잭션으로 감싸져 있으며, 이 메소드 내에서 오류가 발생하면 롤백이 됩니다.프로그래밍 방식 트랜잭션 관리는 개발자가 트랜잭션을 명시적으로 시작하고, 커밋이나 롤백을 직접 처리하는 방식입니다. 보통 PlatformTransactionManager 인터페이스를 사용하여 트랜잭션을 관리합니다.
Example:
@Autowired
private PlatformTransactionManager transactionManager;
public void performTransaction() {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// 비즈니스 로직 수행
transactionManager.commit(status); // 성공 시 커밋
} catch (Exception e) {
transactionManager.rollback(status); // 실패 시 롤백
}
}
이 방식은 직접 트랜잭션 경계를 지정하고 제어할 수 있지만, 코드가 복잡해질 수 있습니다.
트랜잭션 격리 수준은 여러 트랜잭션이 동시에 처리될 때 서로 간의 영향을 최소화하기 위해 설정됩니다. 격리 수준이 높을수록 트랜잭션 간의 간섭은 줄어들지만, 성능이 떨어질 수 있습니다. 스프링에서는 @Transactional 어노테이션에서 격리 수준을 설정할 수 있습니다.
스프링에서는 트랜잭션이 호출되는 메소드 간에 어떻게 전파될지 결정하는 전파(Propagation) 속성을 설정할 수 있습니다. 예를 들어, 트랜잭션을 호출하는 메소드와 호출된 메소드가 각각 독립적인 트랜잭션을 가질 것인지, 아니면 하나의 트랜잭션으로 묶일 것인지를 결정합니다.
트랜잭션 관리는 애플리케이션에서 매우 중요합니다. 특히 다음과 같은 상황에서 필수적입니다:
트랜잭션 관리는 데이터베이스 작업을 안전하고 일관성 있게 처리하기 위한 핵심적인 메커니즘입니다. 트랜잭션을 통해 오류 발생 시 롤백하여 데이터 무결성을 유지하고, 여러 작업이 하나의 단위로 실행되도록 보장할 수 있습니다. 스프링에서는 @Transactional 어노테이션을 사용하여 선언적으로 쉽게 트랜잭션 관리를 할 수 있어, 코드의 복잡성을 줄이면서 안정성을 높일 수 있습니다.
HikariCP는 자바 애플리케이션에서 사용하는 JDBC 커넥션 풀링(Connection Pooling) 라이브러리입니다. 커넥션 풀링은 데이터베이스와 애플리케이션 간의 연결을 효율적으로 관리하기 위한 기법으로, HikariCP는 특히 빠르고 경량이라는 장점 때문에 많이 사용됩니다. HikariCP는 성능과 자원 효율성 면에서 뛰어나서 많은 자바 기반 웹 애플리케이션에서 선택되는 커넥션 풀링 솔루션입니다.
커넥션 풀링은 데이터베이스에 연결을 요청할 때마다 새로운 연결을 생성하는 대신, 미리 일정 수의 연결을 생성해 놓고, 필요할 때마다 이를 재사용하는 기법입니다. 이를 통해 데이터베이스와의 연결을 효율적으로 관리하고, 성능을 크게 향상시킬 수 있습니다.
HikariCP는 설정을 통해 커넥션 풀의 동작을 조정할 수 있습니다. 주요 설정 항목은 다음과 같습니다.
jdbc:mysql://localhost:3306/mydb와 같이 설정할 수 있습니다.Spring Boot에서 HikariCP를 사용하는 방법을 간단히 설명하면 다음과 같습니다. Spring Boot에서는 기본적으로 HikariCP를 사용하도록 설정되어 있습니다.
application.properties 예시:spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/mydb
spring.datasource.hikari.username=root
spring.datasource.hikari.password=1234
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.pool-name=MyHikariCP
Java 코드에서 직접 설정:import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class DataSourceConfig {
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("1234");
config.setMaximumPoolSize(10); // 최대 커넥션 풀 크기
config.setMinimumIdle(5); // 최소 유휴 커넥션 수
config.setConnectionTimeout(30000); // 커넥션 요청 시 대기 시간
return new HikariDataSource(config);
}
}
HikariCP는 빠르고 가벼운 커넥션 풀링 라이브러리로, 성능이 중요한 자바 애플리케이션에서 사용하기 적합합니다. 높은 성능과 안정성, 간단한 설정으로 인해 많은 개발자들이 선택하고 있으며, 특히 트랜잭션 처리나 고부하 시스템에서 매우 유용합니다.
