Replies: 2 comments
|
고생하셨습니다! DB 2편도 뿌셔버려요! |
0 replies
|
고생하셨습니다! DB 2편 출발 ! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
1️⃣ 데이터 접근 기술 진행 방식 소개
적용 데이터 접근 기술
여기에는 크게 2가지 분류가 있다.
SQLMapper
ORM 관련 기술
SQLMapper 주요기능
ORM 주요 기능
2️⃣ 프로젝트 설정과 메모리 저장소
프로젝트 설정 순서
itemservice-db-start의 폴더 이름을itemservice-db로 변경3️⃣ 프로젝트 구조 설명1 - 기본
프로젝트 설정
build.gradle
spring-boot-starter-thymeleaf: 타임리프 사용spring-boot-starter-web: 스프링 웹, MVC 기능 사용spring-boot-starter-test: 스프링이 제공하는 테스트 기능lombok: lombok을 추가로 테스트에서도 사용하는 설정 주의도메인 분석
item
Item은 상품 자체를 나타내는 객체이며, 이름, 가격, 수량을 속성으로 가지고 있다.리포지토리 분석
ItemRepository 인터페이스
ItemSearchCond
ItemUpdateDto
📍 DTO(data transfer object)
ItemSearchCond도 DTO의 역할을 하지만 이 프로젝트에서는Cond는 검색 조건으로 사용한다는 규칙을 정했기 때문에 DTO를 붙이기 않아도 된다.MemoryItemRepository
ItemRepository인터페이스를 구현한 메모리 저장소이다. 메모리이기에 다시 실행하면 기존에 저장된 데이터가 모두 사라진다.findById는Optional을 반환해야 하기 때문에Optional.ofNullable을 사용했다.findAll은ItemSearchCond이라는 검색 조건을 받아서 내부에서 데이터를 검색하는 기능을 한다.where구문을 사용해서 필요한 데이터를 필터링 하는 과정을 거치는 것이다.itemName이나,maxPrice가null이거나 비었으면 해당 조건을 무시한다.itemName이나maxPrice에 값이 있을 때만 해당 조건으로 필터링 기능을 수행한다.clearStore()메모리에 저장된Item을 모두 삭제해서 초기화한다. 테스트 용도로만 사용된다.서비스 분석
ItemService 인터페이스
ItemServiceV1
ItemServiceV1서비스 구현체는 대부분의 기능을 단순히 리포지토리에 위임한다.컨트롤러 분석
HomeController
items로 이동하는 컨트롤러ItemController
4️⃣ 프로젝트 구조 설명2 - 설정
스프링 부트 설정 분석
MemoryConfig
ItemServiceV1,MemoryItemRepository를 스프링 빈으로 등록하고 생성자를 통해 의존관계를 주입한다.TestDataInit
@EvenListener(ApplicationReadyEvent.class);: 스프링 컨테이너가 완전히 초기화를 다 끝내고, 실행 준비가 되었을 때 발생하는 이벤트이다. 스프링은 이 시점에 해당 애노테이션이 붙은initData()메소드를 호출해준다.@PostConstruct를 사용할 경우 AOP 같은 부분이 아직 다 처리되지 않은 시점에 호출될 수 있기에 문제가 발생할 수 있다. 예를 들어@Transactional과 관련된 AOP가 적용되지 않은 상태로 호출될 수 있다.ItemServiceApplication
@Import(MemoryConfig.class): 앞서 설정한MemoryConfig를 설정 파일로 사용한다.scanBasePackages = "hello.itemservice.web": 여기서는 컨트롤러만 컴포넌트 스캔을 사용하고, 나머지는 직접 수동 등록한다. 그래서 컴포넌트 스캔 경로를hello.itemservice.web하위로 지정했다.@Profile("local"): 특정 프로필의 경우에만 해당 스프링 빈을 등록한다.local이라는 이름의 프로필이 사용되는 경우에만testDataInit이라는 스프링 빈을 등록한다.프로필
스프링은 로딩 시점에
application.properties의spring.profiles.active속성을 읽어서 프로필로 사용한다.예를 들어 로컬PC에서는 로컬PC에 설치된 데이터베이스에 접근해야 하고, 운영 환경에서는 운영 데이터베이스에 접근해야 한다면 서로 설정 정보가 달라야 한다. 환경에 따라서는 다른 스프링 빈을 등록해야 할 수도 있다.
프로필을 사용하면 이런 문제를 깔끔하게 해결할 수 있다.
main 프로필
/src/main/resources하위의application.propertiesapplication.properties는/src/main하위의 자바 객체를 실행할 때 동작하는 스프링 설정이다. 스프링은local이라는 프로필로 동작한다.@Profile("local")이 동작하고,testDataInit이 스프링 빈으로 등록된다.default) 프로필이 실행된다.test 프로필
/src/test/resources하위의application.propertiesapplication.properties는/src/test하위의 자바 객체를 실행할 때 동작하는 스프링 설정이다.주로 테스트 케이스를 실행할 때 동작한다.
이 경우에는 직전에 설명한
@Profile("local")는 프로필 정보가 맞지 않아서 동작하지 않는다.testDataInit스프링 빈도 등록되지 않고, 초기 데이터도 추가하지 않는다.프로필 기능을 사용해서 스프링으로 웹 애플리케이션을 로컬에서 직접 실행할 때는
testDataInit이 스프링 빈으로 등록된다. 따라서 등록한 초기화 데이터를 편리하게 확인할 수 있다.초기화 데이터 덕에 편리한 점도 있지만 테스트 케이스를 실행할 때는 문제가 될 수 있다. 데이터를 하나 저장하고 전체 카운트를 확인하는데 1이 아니라
testDataInit때문에 데이터가 2건 추가되어 3건이 되는 일이 발생한다.프로필 기능 덕분에 테스트 케이스에서는
test프로필이 실행된다. 따라서TestDataInit는 스프링 빈으로 추가되지 않고, 초기 데이터로 추가되지 않는다.5️⃣ 프로젝트 구조 설명3 - 테스트
ItemRepositoryTest
afterEach(): 테스트는 서로 영향을 주면 안되기 때문에 각각 테스트가 끝나고 저장한 데이터를 제거해야 한다.@AfterEach는 각각의 테스트의 실행이 끝나는 시점에 호출된다. 메모리 저장소를 완전히 삭제해서 다음 테스트에 영향을 주지 않도록 초기화 한다.clearStore()가 없기 때문에MemoryItemRepository인 경우에만 다운 캐스팅을 해서 데이터를 초기화한다.save(): 상품 하나를 저장하고 잘 저장되었는지 검증한다.updateItem(): 상품을 하나 수정하고 잘 수정되었는지 검증한다.findItems(): 상품을 찾는 테스트이다.null조건도 있지만, 빈 문자("") 의 경우에도 잘 동작하는 지 검증한다.6️⃣ 데이터베이스 테이블 생성
item테이블 생성generated by default as identityidentity전략이라고 하는데, 기본 키 생성을 데이터베이스에 위임하는 방법이다. MySQL의 AutoIncrement 와 같은 방법이다.id는 개발자가 직접 지정하는 것이 아니라 비워두고 저장하면 된다. 데이터베이스가 순서대로 증가하는 값을 사용해서 넣어준다.테이블 생성과 동작하는 지 확인
📍 참고 - 권장하는 식별자 선택 전략
데이터베이스의 기본 키는 다음 3가지 조건을 모두 만족해야 한다.
null값은 허용하지 않는다.테이블의 기본 키를 선택하는 전략을 크게 2가지가 있다.
자연 키 보다는 대리 키를 권장한다 .
비즈니스 환경은 언젠가 변한다.
🔗 출처
김영한 - 스프링 DB 2편 - 데이터 접근 활용 기술
All reactions