GitHub 저장소
STEP 2 목표
변경 사항
개선할 점
배운 점
궁금한 점
나가며
📆 기간 : 2023.04.27 ~ 2023.05.08
들어가며
2단계를 진행하기 전 나는 장바구니 미션을 진행하면서 구조에 대해 헷갈리는 부분이 많아서 고려하면서 짜야겠다고 결심을 하였다.
크루들도 말이 다 달라서 나만의 기준을 찾고자 했다. 하지만 그 기준을 찾는 것이 어려웠다. 계속 헷갈렸고 팔랑귀처럼 누가 "이게 좋다더라" 하면 그런 것 같았고 다른 누가 "이게 좋대!" 라고 하면 또 그게 맞는 것 같았다. 이 과정에서 나만의 기준을 찾고자 노력하였다....
2단계를 진행하면서 중간중간 아무 생각없이 코드를 작성했던 적이 있었던 것 같다. 그때는 js쪽을 잘 볼 줄 몰라 생겼던 일이라 좀 아쉽다. 지금도 잘 못보긴 하지만 대충 어떻게 기능하는지는 알 것 같다.
GitHub 저장소
[2단계 - 장바구니 기능] 오션(김동해) 미션 제출합니다. by donghae-kim · Pull Request #285 · woowacourse/jwp
안녕하세요 디디 ! 오션 🌊 입니다 ! 1단계 보다 쉽지는 않았지만 열심히 구현해보았습니다! 궁금한점 현재 Cart Table이 사용자, 상품 외래키를 가지고 있습니다. 이렇다 보니 CartService에서 dao에
github.com
STEP 2 목표
- 인증 기능
- 장바구니 기능 구현
- argument resolver 및 interceptor
- MVC
인증, 장바구니 기능 이라는 우테코 목표 외에도 그 외의 것들도 학습을 해보고 싶었다. 근본이 되는 것들인 만큼 지금 알아두면 좋은 지식이 될 것 같았다.
변경사항
인증 기능
이번 미션에서는 Basic인증을 통해 사용자를 인식하였다.
const selectMember = (member) => {
const {email, password} = member;
const string = `${email}:${password}`;
localStorage.setItem('credentials', btoa(string));
alert(`${email} 사용자로 설정 했습니다.`);
}
member객체를 전송하면 그에 따라 js에서 인코딩을 하여 전송해 주는 코드가 있었다. 그래서 우리는 이 값을 디코딩하여 알아차릴 수 있도록 하는 기능만 구현하면 되었다.
처음에는 인증 디코딩을 하기 위해 Controller에서 코드를 작성해 보았다. 그러다 보니 중복코드가 너무 많이 발생했고 처음 파라메터로 들어올 때 부터 값이 디코딩되어 들어왔으면 좋겠다는 생각에 argument Resolver를 사용하였다.
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CustomMember.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
String header = webRequest.getHeader("Authorization");
if (header == null) {
throw new UnAuthorizationException();
}
if ((header.toLowerCase().startsWith(BASIC_TYPE.toLowerCase()))) {
String authHeaderValue = header.substring(BASIC_TYPE.length()).trim();
byte[] decodedBytes = Base64.decodeBase64(authHeaderValue);
String decodedString = new String(decodedBytes);
String[] credentials = decodedString.split(DELIMITER);
String email = credentials[0];
String password = credentials[1];
return new MemberRequestDto(email, password);
}
throw new UnAuthorizationException();
}
아예 CustomMember라는 어노테이션을 만들어서 이에 해당할 경우 아래 resolveArgument가 작동하도록 하였다.
@GetMapping("/carts")
public ResponseEntity<List<ProductResponseDto>> getCarts(@CustomMember MemberRequestDto member) {
}
이런식으로 처음 부터 member로 받을 수 있도록 하여 많은 코드들에서 중복되던 디코딩 코드를 줄일 수 있었다.
장바구니 기능
장바구니 기능을 구현함에 있어서 js코드 html코드 작동하는 것을 조금은 알았어야 했다. 나는 알지 못해서 좀 어려웠다..
장바구니 기능은 인증된 사용자에 따라 사용자의 카트 CRD를 진행하였다.
axios.request({
url: `/carts/${productId}`,
method: 'post',
headers: {
'Authorization': `Basic ${credentials}`
}
}).then((response) => {
alert('장바구니에 담았습니다.');
}).catch((error) => {
console.error(error);
});
이런 것들이 제일 어려웠다. 😱
개선할 점
미션을 진행하면서 중간중간 문제가 발생할 때 내 코드만 의심했다. 문제는 타임리프로부터 나왔다.. 타임리프도 어느정도 볼 줄 안다면 훨씬 미션을 빠르게 진행할 수 있었을 것 같다.
2단계를 진행하면서 중간에 뇌를 빼놓고 코딩한 적이 있는 것 같다. 왠지 모르게 체력이 떨어짐에 따라 하기 싫어짐이 커지는 것 같은데 잘 자고 힘을 내야할 것 같다.
미션 별로 학습하면 좋을 것을 지난주 까지 열심히 학습했다. 이번주에는 계획했던 테스트 코드 관련해서 진행하지 못한 것이 아쉽다.
배운 점
- Servlet
- Dispatcher Servlet
- Argument Resolver
- Interceptor
- 통합 테스트
- Restful Api (봐도 봐도 잘 모르겠다)
- session
- cookie
- MVC CONFIG
궁금한 점
DTO 와 도메인 모두에서의 검증이 필요할까 ?
난 DTO의 @valid, domain에서 모두 검증을 처리한다면 검증이 여러번 반복되어 중복될 수 있을 것 같다고 생각하였다. 하지만 DTO 스펙이 변경되어 어노테이션이 누락된다면 불안정해질 수 있을 것 같다. 또한 도메인 객체는 항상 완전해야함으로 중복은 불가피하고 도메인에서의 검증을 최후 저지선이라고 생각하게 되었다.
도메인과 엔티티의 정의
이건 아직도 어렵다. 불과 레벨1까지만 해도 엔티티라는 개념은 없었다. 갑작스레 db를 사용하게 됨으로써 스멀스멀 나오게 된 개념인데 도메인과 엔티티를 아직도 잘 모르는 것 같다.
물론 도메인과 엔티티를 분리하는 것은 좋다. 앱이 복잡해지고, 도메인 규칙이 많아지며 테이블 변경이 잦아질 때는 엔티티와 도메인을 분리할 수 있다고 생각한다. 하지만 지금구조에서는 필요는 없다고 본다. 그래도 사용해보고 싶었다.
나는 비즈니스 로직이 있을 경우 도메인, 영속성 계층간 DTO로써 엔티티 를 생각하고 있다.
이 과정에서 도메인에 비즈니스로직, 특정 조건이 없다면 엔티티를 도메인이자 DTO로써 사용할 수 있다고 생각하고 있다.
그래서 현재 단계에서는 Product,Member를 도메인으로써사용하고, CartEntity를 도메인이자,DTO로써 엔티티를 사용하였다.
도메인과 엔티티를 분리하는 이유는 DB의 변경이 잦고 그런 변경으로부터 도메인을 지키고자 위함이다. 도메인, 엔티티가 분리되더라도 자동차 경주 처럼 도메인 만으로 원하는 비즈니스 요구사항을 만족할 수 있다면 좋을 것 같다.
DB와 객체관 괴리감 때문에 생기는 일인 것 같다.....
레포지토리
Service에서는 repository인터페이스를 가지고, repository인터페이스를 구현한 repositoryImpl 에서 dao에 접근하도록 하는 방법인데 어떻게 생각하시는지 궁금합니다! 라고 물었는데
Repository와 같은 계층을 만드는것은 저도 괜찮다는 의견이지만, 그런 Repository가 여러 도메인(Dao)를 담당하는 객체가 되는것은 반대합니다. Repository나 Dao나 우리가 원하는 도메인에 대한 데이터영역으로부터 저장하고, 불러오는 역할을 하는건데, 여러 도메인을 종합하는 역할을 하게되면 도메인의 각각의 경계가 허물어질 수 있을거라고 생각해요. 라고 듣게 되었다.
나가며
남은 레벨2 화이팅~
'우아한테크코스' 카테고리의 다른 글
[우아한테크코스 5기] 지하철 2단계 학습로그 (2) | 2023.05.28 |
---|---|
[우아한테크코스 5기] 지하철 1단계 학습로그 (1) | 2023.05.21 |
[우아한테크코스 5기] 장바구니 1단계 학습 (2) | 2023.04.30 |
[우아한테크코스 5기] 웹 자동차 경주 2단계 학습 로그 (1) | 2023.04.23 |
[우아한테크코스 5기] 웹 자동차 경주 1단계 학습 로그 (1) | 2023.04.23 |