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
참고로 DTO에 기능이 있으면 안되는가? 그것은 아니다. 객체의 주 목적이 데이터를 전송하는 것이라면
DTO라 할 수 있다.
객체 이름에 DTO를 꼭 붙여야 하는 것은 아니다. 대신 붙여두면 용도를 알 수 있다는 장점은 있다.
이전에 설명한 ItemSearchCond 도 DTO 역할을 하지만, 이 프로젝트에서 Cond 는 검색 조건으로 사용한다는 규칙을 정했다. 따라서 DTO를 붙이지 않아도 된다. ItemSearchCondDto 이렇게 하면 너무 복잡해진다. 그리고 Cond 라는것만봐도용도를알수있다.
참고로 이런 규칙은 정해진 것이 없기 때문에 해당 프로젝트 안에서 일관성 있게 규칙을 정하면 된다.
@Import(MemoryConfig.class) : 앞서 설정한 MemoryConfig 를 설정 파일로 사용한다.
scanBasePackages = "hello.itemservice.web" : 여기서는 컨트롤러만 컴포넌트 스캔을 사용하고, 나머지는 직접 수동 등록한다. 그래서 컴포넌트 스캔 경로를 hello.itemservice.web 하위로 지정했다.
@Profile("local") : 특정 프로필의 경우에만 해당 스프링 빈을 등록한다. 여기서는 local 이라는 이름의 프로필이 사용되는 경우에만 testDataInit 이라는 스프링 빈을 등록한다. 이 빈은 앞서 본 것인데, 편의상 초 기 데이터를 만들어서 저장하는 빈이다.
✅ 프로필
스프링은 로딩 시점에 application.properties의 spring.profiles.active 속성을 읽어서 프로필 사용한다.
main 프로필
/src/main/resource 하위의 application.properties
spring.profiles.active=local
이 위치의 application.properties 는 /src/main 하위의 자바 객체를 실행할 때 (주로 main() ) 동작 하는 스프링 설정이다. spring.profiles.active=local 이라고 하면 스프링은 local 이라는 프로필로 동작한다. 따라서 직전에 설명한 @Profile("local") 가 동작하고, testDataInit 가 스프링 빈으로 등록 된다.
실행하면 로그가 다음과같이 생긴다.
The following 1 profile is active: "local"
참고로 프로필을 지정하지 않으면 디폴트( default ) 프로필이 실행된다.
No active profile set, falling back to 1 default profile: "default"
test 프로필
/src/test/resource 하위의 application.properties
spring.profiles.active=test
이 위치의 application.properties 는 /src/test 하위의 자바 객체를 실행할 때 동작하는 스프링 설정
이다.
주로 테스트 케이스를 실행할 때 동작한다.
spring.profiles.active=test 로 설정하면 스프링은 test 라는 프로필로 동작한다. 이 경우 직전에 설
명한 @Profile("local") 는 프로필 정보가 맞지 않아서 동작하지 않는다. 따라서 testDataInit 이라는
스프링 빈도 등록되지 않고, 초기 데이터도 추가하지 않는다.
afterEach() : 테스트는 서로 영향을 주면 안된다. 따라서 각각의 테스트가 끝나고 나면 저장한 데이터를 제거해야 한다. @AfterEach 는 각각의 테스트의 실행이 끝나는 시점에 호출된다. 여기서는 메모리 저장소를 완전히 삭제해서 다음 테스트에 영향을 주지 않도록 초기화 한다.
인터페이스에는 clearStore()가 없기 때문에 MemoryItemRepository 인 경우에만 다운 케스팅을 해서
데이터를 초기화한다. 뒤에서 학습하겠지만, 실제 DB를 사용하는 경우에는 테스트가 끝난 후에 트랜잭션을 롤백해서 데이터를 초기화 할 수 있다.
save()
상품을 하나 저장하고 잘 저장되었는지 검증한다.
updateItem()
상품을 하나 수정하고 잘 수정되었는지 검증한다.
findItems()
상품을 찾는 테스트이다.
상품명과 상품 가격 조건을 다양하게 비교하는 것을 확인할 수 있다.
문자의 경우 null 조건도 있지만, 빈 문자( "" )의 경우에도 잘 동작하는지 검증한다.
6️⃣ 데이터 베이스 테이블 생성
H2 데이터베이스 Item 테이블 생성
droptable if exists item CASCADE;
createtableitem
(
id bigint generated by default as identity,
item_name varchar(10),
price integer,
quantity integer,
primary key (id)
);
generated by default as identity
identity 전략이라고 하는데, 기본 키 생성을 데이터베이스에 위임하는 방법이다. MySQL의 Auto
Increment와 같은 방법이다.
여기서 PK로 사용되는 id 는 개발자가 직접 지정하는 것이 아니라 비워두고 저장하면 된다. 그러면 데이터베이스가 순서대로 증가하는 값을 사용해서 넣어준다.
등록 쿼리
insert into item(item_name, price, quantity) values ('ItemTest', 10000, 10)
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.
데이터 접근 기술 - 시작
1️⃣ 데이터 접근 기술 진행 방식 소개
✅ 분류
✅ SQL Mapper 주요기능
✅ ORM 주요 기능
2️⃣ 프로젝트 설정과 메모리 저장소
✅ 프로젝트 설정 순서
3️⃣ 프로젝트 구조 설명 1 - 기본
✅ 프로젝트 설정
메모리 구현체에서 향후 다양한 데이터 접근 기술 구현체로 손쉽게 변경하기 위해 리포지토리에 인터페이스를 도입
각각의 기능은 메서드 이름으로 충분히 이해가 될 것이다.
ItemSearchCond
검색 조건으로 사용된다. 상품명, 최대 가격이 있다. 참고로 상품명의 일부만 포함되어도 검색이 가능해야 한다. (like 검색)
cond → condition 을 줄여서 사용
ItemUpdateDto
✅ DTO(data transfer object)
데이터 전송 객체
DTO는 기능은 없고 데이터를 전달만 하는 용도로 사용되는 객체를 뜻한다.
DTO라 할 수 있다.
객체 이름에 DTO를 꼭 붙여야 하는 것은 아니다. 대신 붙여두면 용도를 알 수 있다는 장점은 있다.
이전에 설명한 ItemSearchCond 도 DTO 역할을 하지만, 이 프로젝트에서 Cond 는 검색 조건으로 사용한다는 규칙을 정했다. 따라서 DTO를 붙이지 않아도 된다. ItemSearchCondDto 이렇게 하면 너무 복잡해진다. 그리고 Cond 라는것만봐도용도를알수있다.
참고로 이런 규칙은 정해진 것이 없기 때문에 해당 프로젝트 안에서 일관성 있게 규칙을 정하면 된다.
MemoryItemRepository
ItemRepository 인터페이스를 구현한 메모리 저장소이다.
메모리이기 때문에 자바를 다시 실행하면 기존에 저장된 데이터는 사라진다.
save, update, findById는 쉽게 이해할 수 있을 것이다.
findAll은 ItemSearchCond이라는 검색 조건을 받아서 내부에서 데이터를 검색하는 기능을 한다.
clearStore() 메모리에 저장된 Item을 모두 삭제해서 초기화한다. 테스트 용도로만 사용한다.
ItemService 인터페이스
서비스의 구현체를 쉽게 변경하기 위해 인터페이스를 사용
참고로 서비스는 구현체를 변경할 일이 많지는 않기 때문에 사실 서비스에 인터페이스를 잘 도입하지 않는다.
ItemServiceV1
✅ 컨트롤러 분석
단순히 홈으로 요청이 왔을 때 items로 이동하는 컨트롤러이다.
itemContoller
4️⃣ 프로젝틑 구조 설명 2 - 설정
✅ 스프링 부트 설정 분석
ItemServiceV1, MemoryItemRepository를 스프링 빈으로 등록하고 생성자를 통해 의존관계를 주입한다.
참고 - 서비스와 리포지토리는 구현체를 편리하게 변경하기 위해, 이렇게 수동으로 빈을 등록했다.
컨트롤러는 컴포넌트 스캔을 사용한다.
TestDataInit
애플리케이션을 실행할 때 초기 데이터를 저장한다.
리스트에서 데이터가 잘 나오는지 편리하게 확인할 용도로 사용
@EventListener(ApplicationReadyEvent.class): 스프링 컨테이너가 완전히 초기화를 다 끝내고, 실행 준비가 되었을 때 발생하는 이벤트이다. 스프링이 이 시점에 해당 애노테이션이 붙은 initData()` 메서드 를 호출해준다.ItemServiceApplication
@Import(MemoryConfig.class): 앞서 설정한MemoryConfig를 설정 파일로 사용한다.scanBasePackages = "hello.itemservice.web": 여기서는 컨트롤러만 컴포넌트 스캔을 사용하고, 나머지는 직접 수동 등록한다. 그래서 컴포넌트 스캔 경로를hello.itemservice.web하위로 지정했다.@Profile("local"): 특정 프로필의 경우에만 해당 스프링 빈을 등록한다. 여기서는local이라는 이름의 프로필이 사용되는 경우에만testDataInit이라는 스프링 빈을 등록한다. 이 빈은 앞서 본 것인데, 편의상 초 기 데이터를 만들어서 저장하는 빈이다.✅ 프로필
스프링은 로딩 시점에 application.properties의 spring.profiles.active 속성을 읽어서 프로필 사용한다.
main 프로필
spring.profiles.active=local이 위치의
application.properties는/src/main하위의 자바 객체를 실행할 때 (주로main()) 동작 하는 스프링 설정이다.spring.profiles.active=local이라고 하면 스프링은local이라는 프로필로 동작한다. 따라서 직전에 설명한@Profile("local")가 동작하고,testDataInit가 스프링 빈으로 등록 된다.실행하면 로그가 다음과같이 생긴다.
default) 프로필이 실행된다.spring.profiles.active=test이 위치의
application.properties는/src/test하위의 자바 객체를 실행할 때 동작하는 스프링 설정이다.
주로 테스트 케이스를 실행할 때 동작한다.
spring.profiles.active=test 로 설정하면 스프링은 test 라는 프로필로 동작한다. 이 경우 직전에 설
명한 @Profile("local") 는 프로필 정보가 맞지 않아서 동작하지 않는다. 따라서 testDataInit 이라는
스프링 빈도 등록되지 않고, 초기 데이터도 추가하지 않는다.
실행하면 로그가 다음과 같이 생긴다.
5️⃣ 프로젝트 구조 설명 3 - 테스트
데이터를 초기화한다. 뒤에서 학습하겠지만, 실제 DB를 사용하는 경우에는 테스트가 끝난 후에 트랜잭션을 롤백해서 데이터를 초기화 할 수 있다.
"")의 경우에도 잘 동작하는지 검증한다.6️⃣ 데이터 베이스 테이블 생성
generated by default as identity
Increment와 같은 방법이다.
등록 쿼리
✅참고 - 권장하는 식별자 선택 전략
All reactions