728x90
1. 데이터 접근 기술
- SQLMapper
- JdbcTemplate
- MyBatis
- ORM 관련 기술
- JPA, Hibernate
- 스프링 데이터 JPA
- Querydsl
2. 프로젝트 구조 설명
2.1. 패키지 구조
2.2. Domain
- ItemSearchCond & ItemUpdateDto
- 두개 파일 모두 DTO를 의미
- 팀 내, 규칙으로 파일명 설정
- Cond같은 경우 목적이 검색조건 data를 넘겨 주는 것이기 때문에 dto이긴 하지만 Cond로 합의
- 나머지 data 이동 Domain은 끝에 Dto 붙이는 규칙 설정
- 완전 핵심 dto의 경우 딱 이름만 씀
- Dto(data transform object)
- 데이터 전송 객체
- 기능은 없고 data를 전달만 하는 용도록 사용되는 객체
- Dto 위치
- 최종적으로 사용하는 단계에 위치 시킴.
ex) 회원 조회시, 처음으로 data를 dto에 저장하는 위치는 repository. 따라서 repository에 dto를 위치시킴 - 애매한 경우, Domain 폴더를 따로 두어서 보관
- 최종적으로 사용하는 단계에 위치 시킴.
3. bootApplication 설정
- configFile : 수동 bean 등록 file
- testDataInit : 초기 test file
- @EventListener(ApplicationReadyEvent.class)
- @PostConstruct
- bootApplication
- @Import
- @SpringBootApplication(scanBasePackages = "")
- app 내부 @Bean, @Profile("")
- application.properties
- main : local
- test : test
- 해당 파일 code
package hello.itemservice.config;
@Configuration
public class MemoryConfig {
@Bean
public ItemService itemService() { return new ItemServiceV1(itemRepository()); } // bean 등록 + 의존관계 주입
@Bean
public ItemRepository itemRepository() { return new MemoryItemRepository(); } // bean 등록
}
/* * 수동 bean 설정
* 현재 sample code에서 수동 bean 등록과 자동빈 등록 annotation이 같이 존재해서 헷갈렸는데
* 실제적으로 실험을 해본 결과,
* 각 service, repository 구현체에서 @Service, @Repository 제거해도 문제가 발생하지 않음
* 그냥 중복으로 되어있다고 참고만 할 것, 원래는 2개 중 1개만 수행함
* 수동 bean 등록 복습
* 1. bean 등록 : bean 명은 method 명 | bean 객체는 new로 새로 생성한 객체
* 2. 의존 관계 주입 : 해당 class가 생성자 주입을 받는 경우 빈으로 등록될 객체를 매개변수로 넘겨주는 과정
* 결론
* - 수동 bean 등록 시, 해당 class에서 빈 생성 및 등록과 의존관계 주입이 일괄적으로 수행
* */
package hello.itemservice;
@Slf4j
@RequiredArgsConstructor
public class TestDataInit {
private final ItemRepository itemRepository;
/**
* 확인용 초기 데이터 추가
*/
@EventListener(ApplicationReadyEvent.class)
public void initData() {
log.info("test data init");
itemRepository.save(new Item("itemA", 10000, 10));
itemRepository.save(new Item("itemB", 20000, 20));
}
}
package hello.itemservice;
// 현재 componentScan의 영역이 web 이하이므로 @Import로 수동 bean 등록 내용을 받아야 springContainer가 받아와야하는 bean을 받아올 수 있다.
@Import(MemoryConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ItemServiceApplication.class, args); //web 내부 @Component만 bean으로 등록한다는 의미
}
@Bean // 수동 bean 등록 방법 중 직접 등록 방법
@Profile("local") // application.properties의 설정 중 local 환경일 경우 @Bean으로 등록
public TestDataInit testDataInit(ItemRepository itemRepository) { // 의존관계 주입도 들어감 - ItemRepository
return new TestDataInit(itemRepository);
}
}
# main/resources/application.properties
# 해당 설정이 없을 경우, profiles는 default로 지정된다.
spring.profiles.active=local
# test/resources/application.properties
# test package에 지정한 profiles로 boot test 실행시, 해당 profiles가 우선시 된다.
#설정이 없으면 main profiles를 따른다.
spring.profiles.active=test
3.1. ConfigFile
package hello.itemservice.config;
@Configuration
public class MemoryConfig {
@Bean
public ItemService itemService() { return new ItemServiceV1(itemRepository()); } // bean 등록 + 의존관계 주입
@Bean
public ItemRepository itemRepository() { return new MemoryItemRepository(); } // bean 등록
}
- sample File에서 해당 service, repository 구현체에 @Component 및 @Autowired가 다 등록이 되어있는데, 수동 bean 등록하는 config file이 존재해서 혼란이 왔음
- 확인 해본 결과, 각 service, repository 구현체에서 @Service, @Repository 제거해도 문제가 발생하지 않았다.
- @springBootApplication의 componentScan 범위가 Controller pacakge로 한정이 되어있어서 수동 config파일을 통해서 @Import @Bean 등록을 수행
- service와 repository의 DI 어노테이션은 관습적으로 들어가있다고만 참고 할 것
3.2. TestDataInit
package hello.itemservice;
@Slf4j
@RequiredArgsConstructor
public class TestDataInit {
private final ItemRepository itemRepository;
@EventListener(ApplicationReadyEvent.class)
public void initData() {
log.info("test data init");
itemRepository.save(new Item("itemA", 10000, 10));
itemRepository.save(new Item("itemB", 20000, 20));
}
}
- @EventListener(ApplicationReadyEvent.class)
- AOP를 포함한 spring container가 완전히 초기화를 다 끝내고, 실행 준비가 됬을 경우 해당 어노테이션이 붙은 메서드가 호출
- AOP설정 초기화는 @Transactional 읽고 proxy 객체 만드는 과정을 의미
- @PostConstruct
- @EventListener(ApplicationReadyEvent.class)와 유사한 기능이지만, AOP 같은 부분이 아직 다 처리되지 않은 시점에 호출될 수 있기 때문에, 간혹 문제가 발생
3.3. SpringBootApplication
package hello.itemservice;
// 현재 componentScan의 영역이 web 이하이므로 @Import로 수동 bean 등록 내용을 받아야 springContainer가 받아와야하는 bean을 받아올 수 있다.
@Import(MemoryConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ItemServiceApplication.class, args); //web 내부 @Component만 bean으로 등록한다는 의미
}
@Bean // 수동 bean 등록 방법 중 직접 등록 방법
@Profile("local") // application.properties의 설정 중 local 환경일 경우 @Bean으로 등록
public TestDataInit testDataInit(ItemRepository itemRepository) { // 의존관계 주입도 들어감 - ItemRepository
return new TestDataInit(itemRepository);
}
}
- @SpringBootApplication(scanBasePackages = "hello.itemservice.web")
- scanBasePackages : 해당 pacakge부터 componentScan을 해서 bean을 등록하겠다는 의미
- scanBasePackages : 해당 pacakge부터 componentScan을 해서 bean을 등록하겠다는 의미
- @Import("CLASS")
- 해당 class를 설정파일로 사용한다는 뜻
- @Configuration, @Bean으로 수동 주입하는 방법과 동일한 역할
- @Import하면 해당 class를 빈으로 등록해주어서 수동 주입 할 필요없이 깔끔하게 처리된다.
- @Bean
- Application 에 직접적으로 @bean 등록하는 직접 수동 방법
- @Configuration 없이 (@SpringBootApplication 내부에 있으므로) 자동으로 springContainer에 bean 등록 됨
- bean 등록 방법 3가지
- 자동 등록 - @ComponentScan - @Controller, @Service, @Repository - @Autowired
- 수동 등록 (Config file 이용) - @Configuration @Bean
- 수동 등록 (boot file에 직접 등록) - @Bean
- @Profile
- spring은 로딩 시점에 application.properties의 spring.profiles.active 을 읽어서 프로필로 사용
- @Profile("local")이 설정된 method나 설정, class는 application.properties가 local인 경우 작동
3.4. Profile
# main/resources/application.properties
# 해당 설정이 없을 경우, profiles는 default로 지정된다.
spring.profiles.active=local
# test/resources/application.properties
# test package에 지정한 profiles로 boot test 실행시, 해당 profiles가 우선시 된다.
#설정이 없으면 main profiles를 따른다.
spring.profiles.active=test
- Profile
- application.properties의 spring.profiles.active = "" 로 profile 지정이 가능
- 따로 지정을 하지 않을 시, profile은 (default)로 설정
- 관습적 분류 : dev, local, prod, test(test패키지에서 사용)
- profile별 사용 방식
- @profile
- application-{profile}.properties || application-{profile}.yml
- 동작 방식
- 공통설정은 application.properties 에서 수행
- 이후 profilte 지정 시,
1) 해당 application-{profile}.yml 설정 내용 수행
2) @Profile("{profile}")에 부합한 method 수행 - 단, 중복 코드 발생시, 우선권은 application.properties에서 지정한 profile 파일의 설정이 우선권을 가진다.
= profile설정으로 code를 덮어씌운다.
- 공통설정은 application.properties 에서 수행
- test package의 경우
- test package 내부에 resources/application.properties를 생성 가능
- test package에 application.properties 파일 자체가 없는 경우에는 main/resources/application.properties를 따름
- test package에 applcation.properties가 생기는 순간 부터, test file은 application.properties에 profiles의 존재 유무에 관계없이 해당 application.properties를 따른다.
- main/resources/application.properties와 test/resources/application.properties에 profile 설정을 안해서 둘다 default를 가지더라도 각각 다른 default임을 헷갈리지 말자
- test package 내부에 resources/application.properties를 생성 가능
- 참고 doc
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles