- 아샬님의 패캠 강의 기준 예시로 작성
- 손꾸락 연습을 위해 안보고 따라해보는 것이 주목적
- 매 push 마다 테스트 케이스 반드시 같이 업데이트 할 것
- Restaurant 객체 생성 테스트
- name 속성 테스트
- address 속성 테스트
- 속성 결합 테스트
- ID 속성 테스트
- Spring MVC Test 설정
- Interfaces 패키지 작성
- Restaurant Domain Controller 작성
- Restaurant list 함수 테스트
- 접속 테스트 (status 200)
- list 함수 내 restaurant id 속성 테스트
- list 함수 내 restaurant name 속성 테스트
- list 함수 내 restaurant address 속성 테스트
- 게으름 + 육아..
- endpoint 접속 확인
- 각 속성(ID, address, name) 확인
- endpoint URI 내 ID 변수화(요청값에 따라 내용 바뀌도록)
- Restaurant 객체 2개 이상으로 테스트
- 여러 객체 중 하나만 가져올 수 있는 방법 모색 (=> Java Stream으로 해결)
- !! Java Stream API 사용법 숙지할 것 !! (https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html)
- Restaurant Controller의 list(), detail() 중복 코드 제거
- 분리 된 중복 코드의 interface
- DI 적용
- test code 상의 context load 문제 해결(<= SpyBean 사용)
- Nandos restaurant test에 periperi 메뉴 추가 테스트
- MenuItem domain 새로 만들기
- MenuItem 한개 추가하기
- MenuItem 여러개 추가하기
- 각 레스토랑별로 다른 메뉴 추가해서 확인하기
- list()에서도 작동하도록 기능 구현
- test case에서 나오면 안될 값을 확인하는 방법????
- getter가 없으면 spring bean이 속성값을 불러올 수 없다
- long / Long, int / Int 같은 건 구현 방식이 아예 다르다 (data type vs. Class)
- detail()에서 application을 통해 restaurant 정보 받아오기
- application layer 구현
- application layer test 구현
- DI test를 위한 생성자 추가
- 위의 application에 추가로 menuitem 정보까지 받아오기
- restaurant controller detail() test 통과
- list()에서도 같은 방식 적용하기
- RestaurantControllerTests mock 적용
- RestaurantServiceTests mock 적용
- Mock 객체를 통해 테스트 간 의존성 감소
- 근데 테스트용 데이터가 도대체 관리가 안되고 여기저기서 똑같은 게 선언됨
- 이걸 리팩토링을 해야될까..?
- RestaurantServiceTest에 Spring runner를 이용한 테스트 적용 => DI 사용
- MenuItem List에 MenuItem 객체 넣는 기능 추가
- 접속 테스트 (status 201)
- 헤더 정보 확인 (location)
- 내용 정보 확인 (빈 dict)
- 실제로 객체 추가할 수 있도록 수정
- 인자를 받아서 처리할 수 있도록 수정
- POST 관련 도구 다시 한번 확인할 것(<- 여전히 미숙)
- 항상 돌아다니는 data type에 대해 고민할 것..
- addRestaurant을 통해 추가 후 restaurant 반환
- 실제 Repository에 추가되도록 구현
- 실제로 ID 늘어나도록 구현 시도
- 내일 싹 다 지우고 다시 재구현 시도(애 울어서 제대로 못함..)
- 접속 테스트 (status 204)
- id 인자 받을 수 있도록 구현
- service layer 구현
- 실제 repository layer 구현
- 의존성 추가
- 알아서 디버깅해보자!
- Repository 구현체들은 거의 사라질 것
- 되긴 하는데 리스트 저장이 안됨..
- 개판으로 꼬임
- JPA 모르고 그냥 맘대로 했더니 Crud 쪽에서 충돌이 너무 많이 남
- 실제 프로젝트 때는 어떻게 할까??
- JPA 적용하는 부분에 미숙한 점이 굉장히 많음
- 특히 CRUD 확장할 때...
- 새로 혼자 처음부터 만들어 볼 것
- 최신 강의 내용 따라해볼 것
- 프론트엔드는 일단 여기선 webpack으로 대충 하고 넘어간다
- PATCH /restaurants/{id} endpoint status ok
- PATCH /restaurants/{id} endpoint 속성값 잘 받는지 확인
- PATCH /restaurants/{id} endpoint restaurantService 로 책임 이관
- restaurantService 에서 적용 대상 잘 찾아오는지 확인
- restaurantService 에서 찾아온 대상의 정보가 알맞게 바뀌는지 확인
- update 에서는 명시적인 save() 처리가 아닌 @Transactional 활용
- setter 를 여러개 부르기 보다는 한번에 처리할 수 있는 메서드를 추가로 생성 (이유 확인해볼 것)
- Restaurant domain getter / setter 적용 <- setter는 필요 없어서 삭제
- Restaurant domain constructor 적용
- Restaurant domain builder 패턴 적용
- ItemMenu domain builder 패턴 적용
- Restaurant Domain 의 itemMenus column setter 변경
- Array(또는 객체 타입)의 setter 를 사용할 때는 참조 타입에 꼭 유의
- 안 지키고 하면 함수 실행 뒤의 결과값이 뒤죽박죽이 될 수 있음
- 결론 => 오브젝트 타입의 setter 는 복사본을 사용하자!
- Lombok 사용 시 불필요한 getter/setter 나 기타 코드가 생성되지 않도록 주의
- given() + will() + lambda 를 통해 실제 데이터 test 가능
- Restaurant Controller create() test case에 사례 추가
- Restaurant Controller Create Test case 작성
- Valid, Invalid 두가지 케이스로 작성
- Restaurant Controller Update Test case 작성
- @Valid annotation 은 적용 대상 resource 앞에 붙여야 한다.
- Restaurant Controller Detail case 나누기 (성공/실패)
- Restaurant Controller Detail Notfound test case 작성
- not found class 생성
- error advice controller advice 생성
- 빈 json을 돌려주는 test case 작성
- 실제 service layer 에서 동작하도록 수정
- restaurant service test 수정
- 키워드 별로 못따라간 부분이 너무 많음
- 지우고 다시 혼자 재구현할 것 (20190827 1차 재구현 완료)
- bulk update 용 json 파일 생성
- ItemMenu Controller 구현
- bulkUpdate test case 작성
- ItemMenu Service 구현
- ItemMenu Service test case 작성
- @JsonInclude Annotation 새로 사용
- JsonInclude.Include.Not_Null 인자로 없는 놈 안 보이게 할 수 있음
- @Transient 와 함께 사용법 제대로 숙지해둘 것
- ItemMenu 수정 기능 구현 (기존 기능 활용)
- ItemMenu 삭제 기능 구현
- ItemMenu 없는 대상 삭제 예외 처리 구현
- 현재 API 구조에서 ItemMenu 에 id를 주면 수정도 가능하다 (PATCH 를 쓰니까)
- 편하긴 한데 언제 POST 없이 PATCH 로만 구현해도 될 지 고민해보자
- ItemMenu 없는 대상 구현 중 이상한 현상 발견(Error Handler 쪽 주석 참고)
- Review Controller create test case 작성
- Review Controller create 구현
- Review Service 뼈대 구현
- Review Domain 뼈대 구현 + Entity 설정
- Review Service addReview 테스트 및 구현
- Review Repository 테스트 및 구현
- Review Controller Validation 테스트 및 구현
- Controller 테스트 수정
- Service 테스트 수정
- Review Service 에서 restaurantId 설정하도록 수정
- ItemMenu Service 에외처리 이상함 수정할 것
- Customer, Admin, Common 프로젝트 분리 작업 진행
- Admin RestaurantController detail() review, itemMenu 조회 기능 제거
- Admin RestaurantService detail() review, itemMenu 조회 기능 제거
- Admin ItemMenuController list() 구현 (restaurant 에 종속)
- Admin ReviewController 전체 기능 제거 후 list() 구현 (restaurant 에 비종속)
- Customer API 불필요한 기능 제거
- Common 모듈 jar 설정 추가
- Gradle을 통해 서버 실행, 테스트 변경
- Gradle을 활용하면 멀티프로젝트 관리가 용이함
- application.yml 파일 추가
- 테스트를 위한 환경변수 profile 생성
- Admin Region Domain 구현
- Admin Region Controller GET, POST 구현
- Admin Region Service list(), add() 구현
- Common Region Repository Interface 구현
- Customer Region Controller GET 구현
- Customer Region Service list() 구현
- Admin Category Domain 구현
- Admin Category Controller GET, POST 구현
- Admin Category Service list(), add() 구현
- Common Category Repository Interface 구현
- Customer Category Controller GET 구현
- Customer Category Service list() 구현
- Customer Restaurant Controller URL에 regions 추가
- Customer Restaurant Controller 변경
- Customer Restaurant Service 변경
- Restaurant Domain CategoryId 추가
- Customer Restaurant Controller URL에 category 추가
- Customer Restaurant Controller 변경
- Customer Restaurant Service 변경
- Restaurant 도메인에 categoryId 처음 추가 시 @NotNull 넣고 돌리면 에러 발생
- auto-ddl 설정 하면서 null을 기본으로 넣는데 설정에 위배되서 그런 것 같음
- User Domain 구현 (email, name, level)
- User Repository Interface 구현
- Admin User Controller, Service API GET 구현
- Admin User Controller, Service API POST 구현
- Admin User Controller, Service API PATCH 구현
- Admin User Controller, Service API DELETE 구현
- Admin User Service 예외 처리
- Restaurant Domain 필터링이 category, region에 유연하게 작동하도록 변경
- JPQL 외에는 답이 없는지 고민 필요
- Spring Security 의존성 추가 및 설정 (필요 없는 보안 설정 제거)
- Security 기본 페이지 삭제
- User Domain 수정 (password 추가)
- Customer User Controller, Service API POST 구현
- 유저 삭제 기능은 실제 삭제가 아닌 레벨 조정을 통해 구현
- Transactional 사용에 유의할 것
- 덜렁 거리지 말고 꼼꼼하게 확인하면서 개발 할 것
- Repository를 MockBean 처리해서 디버깅 한참 걸림 ㅡㅡ (null pointer 발생)
- 패스워드 암호화 (Bcrypt)
- email 중복 막기 (중복 시 exception 발생)
- /session POST API 구현
- POST return content에 accessToken 부여
- SessionDto 구현 (lombok data 활용, Application 계층에 생)
- UserService에서 인증 처리하도록 구현
- RestaurantSpecification 구현
- RestaurantSpecificationBuilder 구현
- SearchCriteria 구현
- 기존 Restaurant Controller, Service 적용
- Session Request, Respons Dto 분리 (다시 interfaces 패키지로 이동)
- Session Controller 예외 처리 (패스워드 틀린 경우, 계정 없는 경우)
- User Service authenticate 구현
- User Service test 작성 (올바른 케이스, 없는 이메일, 패스워드 틀림)
- Password Encoder 의존성 주입 형태로 변경
- 기존 테스트 코드 변경
- PasswordEncoder bean 생성
- User password 기반으로 AccessToken 생성하도록 변경
- JwtUtil Component 구현 및 의존성 주입
- JwtUtil createToken 구현
- User의 불필요한 메서드 제거
- JJWT 의존성 가져오기
- resource를 통해 jwt 시크릿 키 가져옴
- JwtAuthentication 필터 추가 (Spring Security 설정에 추가)
- Stateless Session 설정
- Spring 내부 authentication 구현
- 나중에 authentication filter 테스트 작성해보기
- Customer Review Controller 테스트 및 구현 변경 (Authentication 받도록)
- addReview 함수 시그니처 변경
- JwtAuthenticationFilter에서 Security Context가 뭔지 알아볼 것
- Entity 통채로 레이어 넘어다니는 이상한 짓은 지양하자
- DTO가 컨트롤러를 벗어나는 이상한 짓도 자제하자
- 새로운 모듈 생성
- 새로운 모듈로 기존의 login 기능 모두 이관
- JWT에 레스토랑 주인 여부 판단할 수 있는 정보 추가
- User 도메인 수정 (restaurantId 추가)
- createToken에 정보 추가
- 파라미터를 전달하기 전 정합성 확인(isRestaurantOwner)을 통해 쓸모없는 데이터를 걸러낼 수 있음
- Customer API Reservation Controller POST 구현
- Customer API Reservation Service add 기능 구현
- Reservation Domain 구현(id, userId, restaurantId, partySize, Date, Time)
- Reservation Request Dto 구현
- 인증 토큰 수신 기능 구현
- Reservation Repository 구현
- Reservation Service 기존처럼 구현
- Restaurant API Reservation Controller GET collection 구현
- Reservation Service 기존처럼 구현
- Restaurant API 인가 기능 추가
- docker-compose 파일 작성