You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
기본 생성자, memberId, name을 포함하는 생성자 이렇게 2개의 생성자를 만들었다.
DbConfig
@Slf4j@ConfigurationpublicclassDbConfig {
@BeanpublicDataSourcedataSource() {
log.info("dataSource 빈 등록");
HikariDataSourcedataSource = newHikariDataSource();
dataSource.setDriverClassName("org.h2.Driver");
//dataSource.setJdbcUrl("jdbc:h2:tcp://localhost/~/db");//DB를 서버모드가 아닌 JVM 안에서 DB 를 메모리 모드로 띄움dataSource.setJdbcUrl("jdbc:h2:mem:test");
dataSource.setUsername("sa");
dataSource.setPassword("");
returndataSource;
}
@BeanpublicTransactionManagertransactionManager() {
log.info("transactionManager 빈 등록");
returnnewDataSourceTransactionManager(dataSource());
}
@BeanpublicJdbcTemplatejdbcTemplate() {
log.info("jdbcTemplate 빈 등록");
returnnewJdbcTemplate(dataSource());
}
}
JdbcTemplate을 사용해서 회원 데이터를 DB에 보관하고 관리하는 기능이다.
DataSource, TransactionManager, JdbcTemplate을 스프링 빈으로 직접 등록한다.
빈 등록이 실제 호출되는지 확인하기 위해 로그를 남겨두었다.
DB는 별도의 외부 DB가 아니라 JVM 내부에서 동작하는 메모리 DB를 사용한다.
메모리 모드로 동작 옵선: jdbc:h2:mem:test
JdbcTransactionManager는 DataSourceTransactionManager와 같은 것으로 생각하면 된다. 여기에 예외 변환 기능이 보강되었다.
MemberRepository
@RepositorypublicclassMemberRepository {
publicfinalJdbcTemplatetemplate;
//DbConfig에서 JdbcTemplate을 빈으로 등록했기 때문에 바로 주입받아서 사용할 수 있다.publicMemberRepository(JdbcTemplatejdbcTemplate) {
template = jdbcTemplate;
}
publicvoidinitTable() {
template.execute("CREATE TABLE member(member_id VARCHAR PRIMARY KEY, name VARCHAR)");
}
publicvoidsave(Membermember) {
template.update("INSERT INTO member(member_id, name) VALUES(?,?)",
member.getMemberId(),
member.getName());
}
publicMemberfind(StringmemberId) {
returntemplate.queryForObject("SELECT member_id, name FROM member WHERE member_id=?",
BeanPropertyRowMapper.newInstance(Member.class),
memberId);
}
publicList<Member> findAll() {
returntemplate.query("select member_id, name from member",
BeanPropertyRowMapper.newInstance(Member.class));
}
}
JdbcTemplate을 사용해서 회원을 관리하는 리포지토리이다.
initTable: 보통 리포지토리에 테이블을 생성하는 스크립트를 두지는 않는다. 여기서는 예제를 단순화
하기 위해 이곳에 사용했다.
BeanPropertyRowMapper.newInstance(Member.class): Spring JDBC에서 제공하며, SQL 쿼리 결과를 Member 자바 객체로 자동 매핑
참고로 @Transactional을 사용하려면 TransactionManager가 스프링 빈으로 등록되어 있어야 한다. ⇒ 우리는 앞서 TransactionManager를 빈으로 등록했었다.
테이블을 생성하고, 회원 데이터를 저장한 다음 다시 조회해서, 기존 데이터와 같은지 간단히 검증한다.
테스트가 성공 한다면 정상 동작한 것이다.
정리
회원 데이터를 DB에 보관하고 관리하기 위해 앞서 빈으로 등록한 JdbcTemplate, DataSource, TransactionManager가 모두 사용되었다. 그런데 생각해보면 DB에 데이터를 보관하고 관리하기 위해 이런 객체들을 항상 스프링 빈으로 등록해야 하는 번거로움이 있다. 만약 DB를 사용하는 다른 프로젝트를 진행한다면 이러한 객체들을 또 스프링 빈으로 등록해야 할 것이다.
0x02. 자동 구성 확인
${\textsf{\color{orange}2.1. 빈 등록 확인}}$
JdbcTemplate, DataSource, TransactionManager가 스프링 컨테이너에 잘 등록되었는지 간단히 확인해보자.
해당 빈들을 DbConfig 설정을 통해 스프링 컨테이너에 등록했기 때문에, null이면 안된다.
사실 @Autowired는 의존관계 주입에 실패하면 오류가 발생하도록 기본 설정되어 있다. 이해를 돕기 위해 이렇게 코드를 작성했다.
테스트는 정상이고 모두 의존관계 주입이 정상 처리된 것을 확인할 수 있다.
출력 결과를 보면 빈이 정상 등록된 것을 확인할 수 있다.
${\textsf{\color{orange}2.2. 빈 등록 제거 ⇒ 자동 구성 확인}}$
JdbcTemplate, DataSource, TransactionManager 빈은 모두 DbConfig를 통해서 스프링 컨테이너에 빈으로 등록되었다.
이번에는 DbConfig에서 해당 빈들을 등록하지 않고 제거해보자.
DbConfig에서 빈 등록을 제거하는 방법은 2가지 이다.
@Configuration을 주석처리: 이렇게 하면 해당 설정 파일 자체를 스프링이 읽어들이지 않는다. (컴포넌
트 스캔의 대상이 아니다.)
@Bean 주석처리: @Bean이 없으면 스프링 빈으로 등록하지 않는다.
여기서는 간단히 @Configuration을 주석처리 해보자.
DbConfig - 수정
@Slf4j//@Configuration 주석 처리publicclassDbConfig {
@BeanpublicDataSourcedataSource() {
log.info("dataSource 빈 등록");
HikariDataSourcedataSource = newHikariDataSource();
dataSource.setDriverClassName("org.h2.Driver");
//DB를 서버모드가 아닌 JMV 안에서 DB 를 메모리 모드로 띄움dataSource.setJdbcUrl("jdbc:h2:mem:test");
dataSource.setUsername("sa");
dataSource.setPassword("");
returndataSource;
}
@BeanpublicTransactionManagertransactionManager() {
log.info("transactionManager 빈 등록");
returnnewDataSourceTransactionManager(dataSource());
}
@BeanpublicJdbcTemplatejdbcTemplate() {
log.info("jdbcTemplate 빈 등록");
returnnewJdbcTemplate(dataSource());
}
}
@Configuration을 주석처리 했다.
DbConfigTest.checkBean() 테스트를 다시 실행해보자.
출력결과
이번에 실행한 출력 결과를 보면 기존에 있던 빈 등록 로그가 없는 것을 확인할 수 있다.
기존 빈 등록 로그
우리가 등록한 JdbcTemplate, DataSource, TransactionManager가 분명히 스프링 빈으로 등록되지 않았다는 것이다.
그런데 테스트는 정상 통과하고 심지어 출력결과에 JdbcTemplate, DataSource, TransactionManager 빈들이 존재하는 것을 확인할 수 있다. 어떻게 된 것 일까?
사실 이 빈들은 모두 스프링 부트가 자동으로 등록해 주는 기본 빈들이다. 뒤에서 이를 살펴보자.
0x03. 스프링 부트의 자동 구성
스프링 부트는 자동 구성(Auto Configuration)이라는 기능을 제공하는데, 일반적으로 자주 사용하는 수 많은 빈들을 자동으로 등록해주는 기능이다.
앞서 우리가 살펴보았던 JdbcTemplate, DataSource, TransactionManager 모두 스프링 부트가 자동 구성을 제공해서 자동으로 스프링 빈으로 등록된다.
이러한 자동 구성 덕분에 개발자는 반복적이고 복잡한 빈 등록과 설정을 최소화 하고 애플리케이션 개발을 빠르게 시작할 수 있다.
${\textsf{\color{orange}3.1. 자동 구성 살짝 알아보기}}$
스프링 부트는 spring-boot-autoconfigure라는 프로젝트 안에서 수 많은 자동 구성을 제공한다.
spring-boot-starter 는 기본적으로 spring-boot-autoconfigure을 사용한다.
주의! 여기서 모든 것을 깊이있게 이해하지 않아도 된다. 대략 어떻게 동작하는지 감을 잡을 수 있는 정도면 충분하다. 진행하면서 자동 구성과 관련된 부분들을 단계적으로 풀어나간다.
@AutoConfiguration: 자동 구성을 사용하려면 이 애노테이션을 등록해야 한다.
자동 구성도 내부에 @Configuration이 있어서 빈을 등록하는 자바 설정 파일로 사용할 수 있다. after = DataSourceAutoConfiguration.class
자동 구성이 실행되는 순서를 지정할 수 있다. JdbcTemplate은 DataSource가 필요하기 때문에 DataSource를 자동으로 등록해주는 DataSourceAutoConfiguration 다음에 실행
하도록 설정되어 있다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
0x01. 프로젝트 설정 및 예제 만들기
프로젝트 설정 순서
autoconfig-start의 폴더 이름을autoconfig로 변경하자.File⇒Open⇒ 해당 프로젝트의build.gradle을 선택 ⇒ 선택창에서Open as Project선택build.gradle 확인
build.gradleplugins { id 'org.springframework.boot' version '3.0.2' id 'io.spring.dependency-management' version '1.1.0' id 'java' } group = 'hello' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() }스프링 부트에서 다음 라이브러리를 선택했다.
테스트 코드에서 lombok을 사용할 수 있도록 설정을 추가했다
동작 확인
스프링 부트가 제공하는 자동 구성(Auto Configuration)을 이해하기 위해 간단한 예제를 만들어보자.
JdbcTemplate을 사용해서 회원 데이터를 DB에 저장하고 조회하는 간단한 기능이다.MembermemberId,name필드가 있는 간단한 회원 객체이다.DbConfigJdbcTemplate을 사용해서 회원 데이터를 DB에 보관하고 관리하는 기능이다.DataSource,TransactionManager,JdbcTemplate을 스프링 빈으로 직접 등록한다.jdbc:h2:mem:testJdbcTransactionManager는DataSourceTransactionManager와 같은 것으로 생각하면 된다. 여기에 예외 변환 기능이 보강되었다.MemberRepositoryJdbcTemplate을 사용해서 회원을 관리하는 리포지토리이다.initTable: 보통 리포지토리에 테이블을 생성하는 스크립트를 두지는 않는다. 여기서는 예제를 단순화하기 위해 이곳에 사용했다.
BeanPropertyRowMapper.newInstance(Member.class): Spring JDBC에서 제공하며, SQL 쿼리 결과를Member자바 객체로 자동 매핑MemberRepositoryTest@Transactional을 사용해서 트랜잭션 기능을 적용했다.@Transactional을 사용하려면TransactionManager가 스프링 빈으로 등록되어 있어야 한다. ⇒ 우리는 앞서 TransactionManager를 빈으로 등록했었다.테스트가 성공 한다면 정상 동작한 것이다.
정리
회원 데이터를 DB에 보관하고 관리하기 위해 앞서 빈으로 등록한
JdbcTemplate,DataSource,TransactionManager가 모두 사용되었다. 그런데 생각해보면 DB에 데이터를 보관하고 관리하기 위해 이런 객체들을 항상 스프링 빈으로 등록해야 하는 번거로움이 있다. 만약 DB를 사용하는 다른 프로젝트를 진행한다면 이러한 객체들을 또 스프링 빈으로 등록해야 할 것이다.0x02. 자동 구성 확인
JdbcTemplate,DataSource,TransactionManager가 스프링 컨테이너에 잘 등록되었는지 간단히 확인해보자.DbConfigTest해당 빈들을
DbConfig설정을 통해 스프링 컨테이너에 등록했기 때문에,null이면 안된다.@Autowired는 의존관계 주입에 실패하면 오류가 발생하도록 기본 설정되어 있다. 이해를 돕기 위해 이렇게 코드를 작성했다.테스트는 정상이고 모두 의존관계 주입이 정상 처리된 것을 확인할 수 있다.
출력 결과를 보면 빈이 정상 등록된 것을 확인할 수 있다.
JdbcTemplate,DataSource,TransactionManager빈은 모두DbConfig를 통해서 스프링 컨테이너에 빈으로 등록되었다.이번에는
DbConfig에서 해당 빈들을 등록하지 않고 제거해보자.DbConfig에서 빈 등록을 제거하는 방법은 2가지 이다.@Configuration을 주석처리: 이렇게 하면 해당 설정 파일 자체를 스프링이 읽어들이지 않는다. (컴포넌트 스캔의 대상이 아니다.)
@Bean주석처리:@Bean이 없으면 스프링 빈으로 등록하지 않는다.여기서는 간단히
@Configuration을 주석처리 해보자.DbConfig - 수정
@Configuration을 주석처리 했다.DbConfigTest.checkBean()테스트를 다시 실행해보자.출력결과
이번에 실행한 출력 결과를 보면 기존에 있던 빈 등록 로그가 없는 것을 확인할 수 있다.
기존 빈 등록 로그
우리가 등록한
JdbcTemplate,DataSource,TransactionManager가 분명히 스프링 빈으로 등록되지 않았다는 것이다.그런데 테스트는 정상 통과하고 심지어 출력결과에
JdbcTemplate,DataSource,TransactionManager빈들이 존재하는 것을 확인할 수 있다. 어떻게 된 것 일까?사실 이 빈들은 모두 스프링 부트가 자동으로 등록해 주는 기본 빈들이다. 뒤에서 이를 살펴보자.
0x03. 스프링 부트의 자동 구성
스프링 부트는 자동 구성(Auto Configuration)이라는 기능을 제공하는데, 일반적으로 자주 사용하는 수 많은 빈들을 자동으로 등록해주는 기능이다.
앞서 우리가 살펴보았던
JdbcTemplate,DataSource,TransactionManager모두 스프링 부트가 자동 구성을 제공해서 자동으로 스프링 빈으로 등록된다.이러한 자동 구성 덕분에 개발자는 반복적이고 복잡한 빈 등록과 설정을 최소화 하고 애플리케이션 개발을 빠르게 시작할 수 있다.
스프링 부트는
spring-boot-autoconfigure라는 프로젝트 안에서 수 많은 자동 구성을 제공한다.spring-boot-starter는 기본적으로spring-boot-autoconfigure을 사용한다.JdbcTemplate을 설정하고 빈으로 등록해주는 자동 구성을 확인해보자.JdbcTemplateAutoConfiguration@AutoConfiguration: 자동 구성을 사용하려면 이 애노테이션을 등록해야 한다.자동 구성도 내부에
@Configuration이 있어서 빈을 등록하는 자바 설정 파일로 사용할 수 있다.after = DataSourceAutoConfiguration.classJdbcTemplate은DataSource가 필요하기 때문에DataSource를 자동으로 등록해주는DataSourceAutoConfiguration다음에 실행하도록 설정되어 있다.
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })는 설정들이 모두 무효화 되고, 빈도 등록되지 않는다.
@ConditionalXxx시리즈가 있다. 자동 구성의 핵심이므로 뒤에서 자세히 알아본다.JdbcTemplate은DataSource,JdbcTemplate라는 클래스가 있어야 동작할 수 있다” 는 의미이다.@Import: 스프링에서 자바 설정을 추가할 때 사용한다.@Import의 대상이 되는JdbcTemplateConfiguration를 추가로 확인해보자.JdbcTemplateConfiguration@Configuration: 자바 설정 파일로 사용된다.@ConditionalOnMissingBean(JdbcOperations.class)JdbcOperations빈이 없을 때 동작한다.JdbcTemplate의 부모 인터페이스가 바로JdbcOperations이다.JdbcTemplate이 빈으로 등록되어 있지 않은 경우에만 동작한다.JdbcTemplate과 자동 구성이 등록하는JdbcTemplate이 중복 등록되는 문제가 발생할 수 있다.
JdbcTemplate이 몇가지 설정을 거쳐서 빈으로 등록되는 것을 확인할 수 있다.자동 등록 설정
다음과 같은 자동 구성 기능들이 다음 빈들을 등록해준다.
JdbcTemplateAutoConfiguration:JdbcTemplateDataSourceAutoConfiguration:DataSourceDataSourceTransactionManagerAutoConfiguration:TransactionManager그래서 개발자가 직접 빈을 등록하지 않아도
JdbcTemplate,DataSource,TransactionManager가 스프링 빈으로 등록된 것이다.Auto Configuration은 주로 다음 두 용어로 번역되어 사용된다.
(1) 자동 설정
Configuration이라는 단어가 컴퓨터 용어에서는 환경 설정, 설정이라는 뜻으로 자주 사용된다. AutoConfiguration은 크게 보면 빈들을 자동으로 등록해서 스프링이 동작하는 환경을 자동으로 설정해주기 때문에 자동설정이라는 용어도 맞다.(2) 자동 구성
Configuration이라는 단어는 구성, 배치라는 뜻도 있다.예를 들어서 컴퓨터라고 하면 CPU, 메모리등을 배치해야 컴퓨터가 동작한다. 이렇게 배치하는 것을 구성이라 한다. 스프링도 스프링 실행에 필요한 빈들을 적절하게 배치해야 한다. 자동 구성은 스프링 실행에 필요한 빈들을 자동으로 배치해주는 것이다.
자동 설정, 자동 구성 두 용어 모두 맞는 말이다. 자동 설정은 넓게 사용되는 의미이고, 자동 구성은 실행에 필요한 컴포넌트 조각을 자동으로 배치한다는 더 좁은 의미에 가깝다.
정리
스프링 부트가 제공하는 자동 구성 기능을 이해하려면 다음 두 가지 개념을 이해해야 한다.
@Conditional: 특정 조건에 맞을 때 설정이 동작하도록 한다.@AutoConfiguration: 자동 구성이 어떻게 동작하는지 내부 원리 이해0x04. 자동 구성 직접 만들기 - 기반 예제
자동 구성에 대해서 자세히 알아보기 위해 간단한 예제를 만들어보자.
실시간으로 자바 메모리 사용량을 웹으로 확인하는 예제이다.
Memoryused: 사용중인 메모리max: 최대 메모리used가max를 넘게 되면 메모리 부족 오류가 발생한다.MemoryFindermax는 JVM이 사용할 수 있는 최대 메모리, 이 수치를 넘어가면 OOM이 발생한다.total은 JVM이 확보한 전체 메모리(JVM은 처음부터max까지 다 확보하지 않고 필요할 때 마다 조금씩 확보한다.)free는total중에 사용하지 않은 메모리(JVM이 확보한 전체 메모리 중에 사용하지 않은 것)used는 JVM 이 사용중인 메모리이다. (used = total - free)MemoryControllermemoryFinder를 주입받아 사용한다.MemoryConfigmemoryController,memoryFinder를 빈으로 등록하자.hello.config에 위치한다.실행
결과
간단하게 메모리 사용량을 실시간으로 확인할 수 있다.
패키지 위치
패키지를 이렇게 나눈 이유는,
memory라는 완전히 별도의 모듈이 있고,hello에서memory의 기능을 불러다 사용한다고 이해하면 된다.Beta Was this translation helpful? Give feedback.
All reactions