-
[개발노트] 영화 커뮤니티 웹사이트Programming/Note 2021. 3. 3. 12:10
My Note
1. 오라클 + 스프링 부트 + JPA 연동 해결 : ar-tec.tistory.com/55
2. 스프링 시큐리티+ JWT + REACT(SPA) 인증(로그인) 기능 진행 상황 : ar-tec.tistory.com/68
References
1. 자바 ORM 표준 JPA 프로그래밍 : ultrakain.gitbooks.io/jpa/content/
2. 리액트 + Spring : www.youtube.com/watch?v=hdsALpVJwgU&list=PL93mKxaRDidEfLM0I_FFb-98vfAQgXT82
3. 스프링 시큐리티 : www.youtube.com/watch?v=GEv_hw0VOxE&list=PL93mKxaRDidERCyMaobSLkvSPzYtIk0Ah
4. 인스타 클론코딩 (Spring + JPA) : https://github.com/codingspecialist/Springboot-Jpa-Instagram-v2
SCHEDULE
[각 스프린트 당 6일] 개발, 테스트, 정리
[스터디 방식] 프로젝트 시작 때 '어제 개발한 부분 + 앞으로 할 부분 공유' (+문서화)[배포방식 논의] Docker, AWS
더보기SPRINT 1 (3/2~3/12 목) : 개발환경 세팅, 로그인/회원가입 기능, 메인 페이지 라우팅 설정프로젝트 환경 설정- SpringBoot, Spring Security, Hibernate
- Oracle
- React
- Front
로그인회원가입로그인 인증 토큰 처리
- Back
회원 생성, 조회, 수정, 삭제시큐리티 로그인설정
- 보완할 점
- 테스트
- Front
- 회원가입시 기입할 정보 수정
프로필 사진 추가불필요한 정보 삭제 : 생년월일, 핸드폰 번호, 주소추가 정보 : 웹사이트, 자기소개
회원가입 시 아이디, 비밀번호, 이메일 검증- 로그인 인증 토큰 저장 장소 변경
- 회원가입시 기입할 정보 수정
- Back
- 소셜 로그인 기능
- 권한 인가 설정하기 (시큐리티 필터에 url 권한 등록)
SPRINT 2 (3/13~3/17 수) : 게시물 작성API 규칙 세팅- 'api/review'
- Front
게시물 작성 모달창영화 정보 실시간 검색창별점 라디오 버튼이미지 업로더서버에 데이터 전송 및 기타 설정
- Back
REVIEW, IMAGE 엔티티 연관 관계 설정- 리뷰 생성
이미지 파일 메모리에 저장REVIEW, IMAGE 테이블에 저장
- 보완할 점
- 테스트
- Back
- 영화 고유 ID 설정
- Front
- 이미지 업로드 안했을 경우 선택한 영화 포스터 자동으로 등록
SPRINT 3 (3/18~3/23 화) : 게시물 표시API 규칙 세팅- 리뷰 수정, 삭제
- 댓글 생성, 수정, 삭제
- 좋아요 생성, 삭제
- Front
리뷰 출력- 리뷰 화면
- 수정 버튼
좋아요 버튼댓글 창, 버튼
- Back
REVIEW, COMMENT, LIKE, MEMBER 엔티티 연관관계 설정리뷰 수정, 삭제댓글 생성, 수정, 삭제좋아요 생성, 삭제
- 보완할 점
- 게시물 이미지 사이즈 조정
SPRINT 4 (3/24~4/4 일) : 검색, 박스 오피스, 마이 페이지
API 규칙 세팅- 리뷰 조회(전체, 회원명으로, 영화명으로)
- 박스오피스 조회
- Front
- 리뷰
- 검색창
전체 리뷰 게시물 스크롤 처리- 리뷰 게시물 생성, 수정, 삭제 후 렌더링
- 박스오피스
순위, 영화명, 전일 대비 순위 변동 정보 출력
- 마이 페이지
내 리뷰 게시물 모아보기리뷰의 첫번째 이미지, 좋아요 개수, 댓글 개수 출력
회원 수정이름, 이메일, 웹사이트, 자기소개 변경
회원 탈퇴비밀번호 재입력하여 검증
- 리뷰
- Back
리뷰 조회페이징 처리전체, 회원명, 영화명에 따라
마이 페이지LIKE, COMMENT 리포지토리에 count 필드 생성
박스오피스박스오피스 순위 자동 업데이트
- 보완할 점
- 테스트
- 프론트 코드 정리
- 검색창
- 스크롤
- UI 디자인
- 리뷰 출력
- 생성, 삭제 후 렌더링
SPRINT 5 : 상영중인 영화
- [API 규칙 세팅]
- [view]
- [vo, repository, service, controller]
- [test]
- [문서정리] 스토리 보드 구체화, 개발할 때 이슈 정리
5주차(3/29~4/4)
4/4 (일)
Today's task
1. 소셜 로그인(진행중)
2. 회원가입 수정(완료)
- UI 수정
- 아이디, 비밀번호, 이메일 정규식 검증
Today I Learn
- 소셜로그인
- Build.gradle oauth 라이브러리 추가(완료)
- Application.yml 구글만 (완료)
- Member 엔티티 수정(완료)
- String Provider
- String ProviderId
- PrivncipalDetail 수정(완료)
- 다중 상속 : OAuth2User
- 필드에 추가
- Oauth 로그인시 사용할 생성자 추가
- PrincipalService는 동일(완료)
- Provider 디렉토리 생성
- OAuth2UserInfo 인터페이스(완료)
- GoogleUserInfo 생성. 인터페이스 상속받아서(완료)
- PrincipalOauth2UserService 생성 (완료)
- DefaultOAuth2UserService 상속
- Securityconfig 설정
결과 ===> REDIRECT FILTER에 처리필요한 둣
4/2 (금)
Today's task
1. 마이 페이지
- 로그인 후 profile 페이지에 필요한 정보 스토리지에 저장? or didupdate때 불러오게?
2. Member 엔티티 수정
- 프로필 이미지
- 아이디
- 이메일
- 이름
- 자기 소개
- 웹 사이트
4/1 (목)
Today's task
1. 마이 페이지
- Back
- 내 게시물 모아보기
- 회원 수정
- 회원 탈퇴
3/30 (화)
Today's task
1. 서버 코드 리팩토링
- ROLE_TYPE ENUM으로 변경
- 엔티티 int, long=> Integer, Long 타입으로 변환
- sequence allocation size 50이나 100으로 변경
- 엔티티 순환참조 문제
- @jsonIgnoreProperties
2. develop과 merge
3. 피드백 받은거 고치기
- 상수 사용
- Like 메서드 분리
4주차(3/22~3/28)
3/28 (일)
Today's task
1. 서버 코드 리팩토링
2. 테스트
Today I Learn
1. 멤버 엔티티 수정
- Model : Pk인 id값 Long타입으로 변환
- Repository : Repository도 Long타입으로 변경
- 이유 : 1) 양수 범위 늘어남, null 처리
2. 정보 수정 시나리오
- Front : 입력한 password 가지고 있음
- Back : 입력한 password 암호화한 결과가 db와 일치하는지 확인
- Front : password, name, email, address, phone 기존 값 + 변경된 값 전체 보내기
- Back : set으로 다시 세팅
- 기존 password로 다시 한번 인증
- 인증 확인되면 정보 변경
- 시큐리티 기능 적용 (완료)
3. 리뷰 기능
- Controller에 시큐리티 적용 (완료)
- Dto 생성 (완료)
- 리뷰 생성, 리뷰 수정 DTO
- Default는 @ResponseBody가 아니라 @ModelAttribute
- Service 레이어 분리(완료)
- 테스트
- 생성
- 이미지 없이 생성
- 생성
- 이미지 포함 생성
- Update
- 없는 리뷰 게시물 수정
- 있는 리뷰 게시물 수정
- 없는 리뷰 id로 리뷰 수정 요청
- 없는 이미지 id로 이미지 삭제 요청
- 권한 없는 review id(내 게시물이 아닌 이미지들)로 이미지 삭제 요청
- 있는 이미지 id로 이미지 삭제 요청
- 새로운 이미지 추가 요청
- 존재 안하는 게시물 수정
- 권한 없는 리뷰에 대한 수정 요청
- Delete
- 없는 리뷰 게시물 삭제
- 권한 없는 리뷰 게시물 삭제
- 권한 있는 사람이 게시물 삭제
4. 좋아요 기능(완료)
- Likes, Review 연관관계 설정(완료)
- Review id와 member id로 Likes 찾아옴
- SERVICE, CONTROLLER(완료)
- 클릭하면 추가하고 LIKE 반환
- 다시 클릭하면 삭제하고 UNLIKE 반환
5. 댓글 기능
- Review, Comment, Member 연관관계 설정
- Comment라는 테이블 생성 불가. Comments라고 해야됨
- 댓글 추가 (model로 받으려면 post body의 form-data로 보내야 한다. )
- 댓글 수정(dto 클래스에 세터 없으면 null값 반환)
- 댓글 삭제
6. 리뷰 삭제시 디렉토리에 저장된 이미지 파일도 삭제 (완료)
7. saveImage 뭔가 개선할 수 있을 거같다.
- 아이디어 : DTO 자체를 OPTIONAL로 만든다음에 saveFiles에서 직접 catch로 잡아주고 ifPresent안에서 처리하기
8. 리뷰 조회
- Like, comment, review 전체 다 뿌려주기
- 순환 참조 문제 해결하기
9. @ModelAttribute null 문제
- Content type을 application/json으로 보내면 안됨
- RESTFUL의 정의가 뭘까?
- 왜 DTO를 써야 RESTFUL한 프로그램이라 하는 거지?
3/27 (토)
Today's task
1. 서버 코드 리팩토링
- 리뷰 생성, 수정, 조회, 삭제
- JSONObject로 결과 반환하기
Today I Learn
1. JPARepository에서 detele 메서드 호출할 때 엔티티 없어도 오류 발생시키지 않는다
2. 조회 + 페이징 처리 : https://www.baeldung.com/spring-data-jpa-pagination-sorting
3/26 (금)
Today's task
1. 서버 코드 리팩토링
- 리뷰 생성, 수정 컨트롤러 메서드 리팩토링(파람말고 바디로 주고받게 변경)
Today I Learn
1. 파일을 포함한 데이터 받기
- 방법 1 : @RequestParam(required=false)
- 방법 2 : @RequestBody (ReviewDTO) => 안됨.
1) 리뷰 수정 : 삭제할 이미지의 IDX와 새로 추가할 이미지 파일 포함
- 오류1 : Null로 받아오는 문제
- https://override1592.tistory.com/21
- Spring requestparam get과 post만 사용가능 => put쓰면 null로 표시된다.
- 오류2 : 파싱 에러
- 참고 : https://repacat.tistory.com/31
- 여전히 같은 에러가 뜬다 => 파싱 에러
- @RequestBody로 받아와서 DTO를 사용하면 POSTMAN 사용할 때 계속 에러난다;;
- 해결 : @ModelAttribute로 받아오면 ㄱㅊ다. 왜 그런지 찾아봐야될듯
2. 자식 엔티티에게 영속성 전이 설정
- 연관관계 부모에서 cascade 설정하기
- 연관관계 끊어진 자식 엔티티 자동삭제 기능
- https://parkhyeokjin.github.io/jpa/2019/11/06/JPA-chap8.html
- 설정 안했을 경우, 이미지 엔티티 있으면 삭제 불가능하다. 고아객체를 설정해서 자동으로 삭제할 수 있게 가능
3/25 (목)
Today's task
1. 서버 코드 리팩토링
- Service 인터페이스 제거
3/24 (수)
Today's task
1. 서버 코드 리팩토링
- MEMBER, REVIEW, IMAGE, LIKE, COMMENT 연관관계 재설정
3/23 (화)
Today's task
1. 스프린트 회고 준비
2. back
- refresh token
3. front
- edit, delete 기능
- 별점 1점 ~10점으로 수정
4. 기타
- 디렉토리, 컴포넌트 네이밍 수정
Today I Learn
1. Edit 기능
- 리뷰 모달창의 버튼 분리하기
- 자식에게 데이터 전송
- 부모로 부터 받아온 isOpen과 close 찍어보기
- Edit 버튼 누르면 현재 있는 게시물의 위치까지 reviewbox 실행됨..
- 원인 : ReviewList > ReviewBox > ReviewBody(edit button) 의 의존관계를 가짐. 이 때 스크롤 내릴 시 매번 새로운 review box가 생성되고 해당 박스에 대한 body가 생성되어 무한 루프에 빠짐.
- 해결 : 리뷰 박스에 유니크한 키값을 주어, 한 번 생성되면 다시 생성되지 않게 변경하면 해당 구조로 사용해도 가능
TODO
1. JPA 공부하고 코드 리팩토링
3/22 (월)
Today's task
1. BACK
- 토큰 처리하는 로직 다시 원래대로 => refresh token 사용해보기
2. Front
- 구조 파악
- Header : writername, createdate
- Body : title, content, rating, images
- Footer : 댓글
- 수정에 필요한 value는 사실상 body에 존재. Header와 body 구분하면 데이터 주고 받는 로직 더러워 질거같음
- Controller에서 Rating 타입 오류 문제 해결 => parseInt
- 이미지 전송 문제 => Pictures 배열 초기화
- 현명 오빠 코드 merge후 실행 안됨(해결) => 왜 안됬었는지 알수가 없네 ㅇㅂㅇ
- EDIT 기능
- 수정 버튼을 누르면 모달창이 띄워져야하는데, 현재 REVIEW WRITE 컴포넌트 내부에 버튼 장착되어 있음. 밖으로 빼야함
- 참고 : https://velog.io/@7p3m1k/React-modal-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%B0%BD-%EB%A7%8C%EB%93%A4%EA%B8%B
- DELETE 기능
- 제안 => 디렉토리 네이밍 변경. 헷갈려 ㅇㅂㅇ
Today I Learn
1. 이미지 있는 게시물 업로드 후 다시 모달창 열어서 이미지 없는 게시물 업로드 시도 => 오류
- 분명 이미지 없는 거로 업로드 요청했는데 url이 api/review/img로 세팅된다.
- Pictures 배열에 요소가 존재한다는 의미
- 원인은 reviewWriteBox 컴포넌트의 생성주기.
- 모달창을 새로 open할 때마다 컴포넌트가 생성되는 것이 아니기 때문에, handleClose()호출 전에 pictures 배열을 clear한뒤에 모달창을 닫아야 한다.
2. Rating(평점)이 string value로 전송되는데, controller에서 int값으로 받기 때문에 발생하는 오류
- 평점이 소숫점이 되면 string value로 세팅된다 => 처리해줘야 할듯
- 서버에서 발생하는 오류 메세지 :org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "4.5"]
- 시도 1 : StarBoxComponent에서 parseInt로 value값을 세팅한 뒤 부모로 전달했다.
- 그래도 안됨… 전달된 값이 또 string으로 세팅된다.
2. Git
- Staged 파일 확인하기
- 원격 저장소에 update된 내용이 있고, 나도 add하여 push할 내용이 있는 경우.
- 우선 push 명령어를 사용하면 pull하라는 이야기를 한다. 이미 원격 브랜치에 업데이트 된 내용이 있기 때문ㅇ
- 이 때 바로 git pull을 시도하면 다음과 같은 에러가 뜬다. 내가 intellij 로 수정(사실 난 커밋을 했는데?)한 부분을 stash로 임시저장소로 옮긴 뒤에 하라는 것. 오버라이팅 될 수 있기 때문에!
- 그래서 우선 나의 작업 내용을 stash로 임시 저장소에 저장했다.
- 그런 뒤에 pull
- 임시 저장해 놓은 commit을 다시 빼냈다.
- 그런 다음 push => 정상 작동띠
3. 궁금한거 =>picture배열 초기화가 필요할까?
- 모달창 생성자 언제 호출되는지 확인해보자.
- 모달창 여러 번 껏다켰는데 호출 1번만 됨. 결국 picture 초기화 필요할듯? 일단 더 실험
- 맞네 pictures 배열 초기화 안해주면. 계속 더 파일 추가됨(그 전에 파일 2개 추가했고, 이번에는 1개만 추가했는데 배열 크기 3으로 뜬다.)
- 해결띠
TODO
1. 스프린트 회고 준비
2. back
- refresh token
3. front
- edit, delete 기능
- 별점 1점 ~10점으로 수정
4. 기타
- 디렉토리, 컴포넌트 네이밍 수정
3주차(3/15~3/21)
3/21 (일)
Today's task
1. 리뷰 작성 창
- 프론트
모달창 별점 o빈 칸 확인 o다수의 이미지 전송
- 방법 : https://developer.mozilla.org/ko/docs/Web/API/FormData/append
- 배열 자체를 넣는 것이 아니라 for문을 돌면서 동일한 key값으로 추가해야 한다.
- 백
Controller에서 파일 없어도 저장되게 처리 o파일 여러 개 전송 가능하게 하기Review에 별점 저장할 필드 만들기 o
Today I Learn
1. 이미지 업로드 라이브러리
- 처음 본 블로그 글 : http://noartist.com/react%EC%9A%A9-image-upload-component/
- 깃헙 리포지토리 : https://github.com/JakeHartnell/react-images-upload/tree/master/src/component
TODO
1. BACK
- 토큰 처리하는 로직 다시 원래대로 => refresh token 사용해보기
2. Front
- 구조 파악
- EDIT 기능
- DELETE 기능
- 제안 => 디렉토리 네이밍 변경. 헷갈려 ㅇㅂㅇ
3/20 (토)
Today's task
1. 게시물 작성 : 네이버 API와 연동
- 별점 모달창
- Placeholder
- 이미지 다수로
Today I Learn
1. 모달창과 검색창 기능 합치기
- 참고 : https://ichi.pro/ko/reactlo-silsigan-jadong-wanseong-saengseong-jeonche-gaideu-63375445320588
- 모달창과 검색창 기능 합쳐서 구현할 방법
- 컴포넌트화의 문제점. 부모에서 데이터를 바로 확인할 수가 없음
- 부모에서 자식으로 자식에서 부모로 데이터를 공유할 수 있는 방법 없을까?
- https://ghwlchlaks.github.io/react-data-transfer
- https://medium.com/@ghur2002/react%EC%97%90%EC%84%9C-children-component%EC%97%90-props-%EB%84%98%EA%B2%A8%EC%A3%BC%EA%B8%B0-911bf74f83b9
- This.selected에 분명히 들어가서 영화이름 세팅되는데, 부모로 보내질 못햇다.
- 1차 시도 : js로 뺀 메서드를 jsx로 가져와서 세팅한 후 this.state.selected 확인
- 결과 : 그래도 handle change호출을 안한다?
- 분명 onchange로 등록되어 있는데..
- 잘 모르겠지만 div에 넣고 그 중간에 텍스트를 넣는거는 그 태그 자체의 value가 변경되는게 아니다(input은 value자체가 변하기 때문에 그랬던 것)
- 모달창에 title 세팅하는방법
- Title에 값 세팅!
- 명시적으로 안불러주면 전송 안된다.
- 알아낸 거 <input onchange={handler}>은 input태그의 value가 변경될 때마다 handler가 호출되는 것이고 <div onchange={handler}> or <p>{value} </p> </div> 이런식으로는 써도 태그 내부의 value가 변하는 것이 아니라 그냥 태그가 감쌀 뿐이므로 handler 작동 안한다.;;;;
- 그러니까 이런 경우에는 콜백 함수말고 직접적으로 호출해서 써야 한다. (js에 넣을 수 없었던 핵심이유…;;)
- 하 진짜.. 겨우했다^^ 개어렵다 진심
- This.props.변수명으로 바로 접근하면 undefined 뜬다
- 대신 this.props.부모에 등록한 콜백메서드 명시적으로 호출해주면 됨.
- 이렇게 부모의 함수를 호출할 수 있는 이유는 부모 컴포넌트에서 다음과 같은 설정을 했기 때문
- 자식 컴포넌트에서 안하면 사용불가
- (설정 안한 경우)
- 주의할 점!!
- 자식에서 부모를 부를 때 사용하는 callbackfromparent는 자식 컴포넌트를 배치시킬 때 고정한 이름 때문에 바꿀 수 없다. (내가 지정한 이름인줄 알고..)
- Onclick 인자 보내기 : https://webisfree.com/2020-09-02/react-onclick-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B0%92-%EC%A0%84%EB%8B%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95
2. 토큰 자동 갱신 작업
- 오래있다가 다시 보내니까 TokenExpiredException 발생
- 일단 다시 로그인해서 토큰 받아와보았음
- 이건 된다.
- 나중에 토큰 처리할 방법도 생각해야 할 듯
3. 일단 여태까지 로직으로 db저장되는지 보자
- 파일 저장 루트 설정
- 저장완료
3. 문제상황 케이스
- 사진 없으면 터지는 문제
- 서버에서 터짐 => 컨트롤러에 해당 파라미터로 매칭되는 메서드 없기 때문
- 오류 메세지 : 2021-03-20 22:40:45,586 WARN org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
- 영화이름 세팅 안해도 들어감(다른 영화 이름으로 들감)
-
- 기입 안한 경우 안잡아주기 때문에 모달창 껏다켜도 그 전에 선택했던 영화 리뷰로 들어감
TODO
1. 리뷰 작성 창
- 프론트
- 모달창 별점
- 빈 칸 확인
- 백
- Review에 별점 저장할 필드 만들기
- Controller에서 파일 없어도 저장되게 처리
3/19 (금)
Today's task
1. 게시물 작성 : 네이버 API와 연동
네이버 API에서 정보 받아와서 파싱실시간 렌더링 검색창 구현- 별점 모달창
- Placeholder
- 이미지 다수로
Today I Learn
1. 값이 null이거나 undefined인지 검증하기 위해 if(변수명)을 사용할 수 있다.
2. Status 코드로 오류의 종류를 구분하기
- 400번대 에러
- 500번대 에러
3. 깃
성공.. 휴
[참고] http://minsone.github.io/git/how-do-i-clone-all-remote-branch
4. 인텔리제이 에러
갑자기 can not resolve ~ 에러가 뜨면서 스프링 인식이 안되었다.
File > Invalidate Caches/restart 로 해결
참고 : https://hyesun03.github.io/2019/08/27/intellij-cannot-resolve-symbol-error/
5. Naver api 연동
- 클라이언트 프로그램에서 API 호출 불가능하다
- 백에서 처리하기
- 참고(네이버 개발 문서) https://developers.naver.com/docs/search/blog/
- Postman에 응답 보내기
- 참고: https://blog.voidmainvoid.net/155
- response.setContentType("text/plain;charset=UTF-8");으로 설정 안됨. 디코딩 제대로 안되서 ??로 뜸
- @GetMapping(produces="text/plain;charset=UTF-8")로 해결
- 리뷰 컨트롤러에 naver api 요청 메서드 추가
TODO
1. 게시물 작성 : 네이버 API와 연동
- 별점 모달창
- Placeholder
- 이미지 다수로
3/18 (목)
Today's task
1. 프론트
로그인 유무로 네비게이션 바 나누기- 오류 : merge 한 이후 모듈을 못찾는 문제로 리액트 빌드 실패
- Choid…version…
- Can not find Jsonfile/util module
- 해결 : 하나씩 다시 옮겼다..><
- Naver API로 값 가져오기
- 모달창 디자인 하기
- 리액트 아이콘(material UI) : https://velog.io/@sunkim01/React-Material-UI-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0
2. 백
- 당장 해야하는 작업
회원아닌 사람이 로그인 요청 O비밀번호 틀릴 때 O
- 기타
로그아웃- (시간 날 때 하기) 멤버 정보 수정 삭제
- JPA 기본 강의 꾸준히 듣자
- JPA 읽을거리: https://ict-nroo.tistory.com/122
3. 기타
- 문서 합치기
- 스토리 보드
- Api 문서
Today I Learn
1. Git
- 협업 방식 FIX
- Fork 해서 개발 후에 pr 하는 방식은 오픈소스 컨트리뷰트할 때 사용
- 기본적인 협업에는 하나의 리포지토리 안에서 브런치를 나눠서 개발 => 이걸로 FIX!
- 원격 브랜치 가져와서 반영시키기
- https://lucidmaj7.tistory.com/161
- Git checkout -t origin/feature/review
2. JPA
- 엔티티 DB 반영 안될 경우 => 연관관계 설정을 살펴봐라
- 출처: https://ict-nroo.tistory.com/122 [개발자의 기록습관]
- 주인 : @JoinColumn
- 종속 : @mappedBy
3. 토큰 문제 해결방법
- 원인
- Back : 노출 헤더를 지정해 주지 않았기 때문에, response를 받은 쪽에서 지정된 헤더들만 열람할 수 있는 문제가 있었다.
- Front : response header에 token을 담아서 전송했는데, response body를 열람하여 token을 가져오려 했기 때문에 제대로 token을 저장할 수 없었다.
- 해결
- Back : CorsConfig.java 에 노출 헤더를 설정해주어. 지정된 헤더를 응답 받은 쪽에서 볼 수 있게 설정하였다.
- Front : response header에서 authorization으로 token을 get하여 local storage에 저장하였다.
4. 로그인 유무에 따른 메뉴 navbar 분리
- 메뉴 뷰를 위한 js 만들기 (완료)
- 로그인된 유저용 MenuForAuthorized.js
- 로그인 안된 유저용 MenuForUnauthorized.js
- App.js에 라우팅 (완료)
- Undefined가 아닌 null이다. [코드를 제대로 확인하자!]
- (access === null) ? <로그인 x/> : <로그인 o/>
- (참고) undefined와 null의 차이: 두 타입 모두 js에서 값이 비어있음을 나타낸다.
- undefind : 값이 할당되지 않은 변수
- 변수 선언만 하더라도 undefined가 할당됨
- 타입: undefined
- 값 : undefined
- null : 값이 비어있음을 나타냄
- 변수로 선언한 후에 null로 값을 바꿈
- 타입 : null
- 값 : null
- undefind : 값이 할당되지 않은 변수
- 문제 : 새로고침해야 렌더링 된다.
- 해결방법(https://geonlee.tistory.com/191)
- Push : 사용자가 앞뒤로 페이지 이동할 수 있다.
- Replace : 다시 뒤로 이동할 수 없다.
- 이전: Prop.history.push('/')
- 이후: window.location.replace('/')
- History.push와 location.replace의 차이(https://stackoverflow.com/questions/40210673/whats-the-different-between-browserhistory-push-and-location-replace/40210737)
5. 없는 아이디로 로그인 할 경우 처리
- 기존 로직
- InternalAuthenticationServiceException 발생
- 우선 loadUserByUsername에서 멤버 네임 db쿼리
- 없을 경우 InternalAu~던지게 처리
- unsuccessfulAuthentication() 메서드 발견
- Catch문으로 잡아주면 동작안하고, catch문 없을 때는 unsuccessful 동작 => 그냥 안쓰는게 나을듯
- This.setState 함수 안에서 사용하는 변수는 const에 선언할 필요없다.
- 로컬 스토리지
- localStorage에 저장해 놓은 토큰(로그인 정보) 없애려면?
- (참고) https://www.zerocho.com/category/HTML&DOM/post/5918515b1ed39f00182d3048
- 브라우저 저장소 종류
- 지속적으로 필요한 데이터(자동 로그인) 등을 담는다.
- 잠깐 동안 필요한 정보(일회성 로그인..)을 담는다. 비밀번호 같은 중요한 정보는 저장하기 말아라! 클라이언트에 저장하는 것이기 때문에 언제든 털릴 수 있다.
- 로컬 스토리지 : 사용자가 지울 때까지 브라우저에 남아있음
- 세션 스토리지 : 윈도우나 브라우저 탭을 닫을 경우 제거
- Front/back 서버를 내렸다 다시 올리는 것은 상관이 없다.
- localStorage는 브라우저에 내장된 저장소의 일종이다.
- 따라서 캐시를 삭제해야 한다.
TODO
1. 게시물 작성 : 네이버 API와 연동
- 네이버 API에서 정보 받아와서 파싱
- 실시간 렌더링 검색창 구현
- 별점 모달창
- Placeholder
- 이미지 다수로
3/17 (수)
Today's task
1. 로그인 토큰으로 인증해서 파일 전송 후 저장
파일 전송Db 저장(Images, Review)
Today I Learn
[TASK1 디버깅 과정]
1. Db 저장 기능
- 실행 결과 : detached entity passed to persist: com.codeworrisors.Movie_Community_Web.model.Member
- 토큰으로 인증하는 코드에서 한 번 더 db에 해당 멤버 정보를 넣으려하는 것 같다.
- 1차 시도
- : (검색) CASECADETYPE.ALL 로 설정해 준 것 때문에 문제 생겼다는 얘기..
- JPA 개념을 제대로 모르기 때문에 생긴 문제인듯 => 우선 김영한 모델링 먼저 보자
- https://conservative-vector.tistory.com/entry/%EC%97%90%EB%9F%ACdetached-entity-passed-to-persist-orgrefrigeratorspringbootdomainrecipeFood-nested-exception-is-orghibernatePersistentObjectException
2. 테이블 모델링
- Order와 Item사이에 OrderItem을 놓았듯이,Review와 Image사이에 ReviewImages 를 놓아서 사용해야 할 듯.
- 리뷰는 Image가 아니라 ImageList를 가지고 있게끔
- => 로그 보니 JPA가 자동으로 테이블 만들어서 Insert해
3. VIEW에서 토큰 가져올 수 없는 문제
- 원인
- back : (cors 관련 이슈) response 받는 측에서 header값을 읽을 수 없도록 default 설정되어 있음
- front : response header에서 authorization이라는 key값으로 value가져와서 저장해야하는데, body에서 찾고 있었음
- 해결
- back : cors허용추가(현명님 코드 참고)
- front : response.headers['authorization']으로 가져와서 세팅하기
TODO
1. [서버-클라이언트 통신문제] Cors 문제에 대해 확실히 알고 넘어가야 할 것같다.
2. [JPA 설정 문제] CASCADE에 대해 확실히 알고 넘어가야 할 것 같다.
- mappedBy?
- cascade 설정과 어떨 때 해야하는지
3/16 (화)
Today's task
1. [View] 로그인/회원가입 기능 완성
2. [BACK] 리뷰 업로드 기능 완성
TASK1 : 리뷰 엔티티 변경 O- 프론트로부터 받은 이미지를 담기 위해서 FILE 엔티티 하나 더 필요(1-리뷰 : 다-FILE)
TASK2 : 파일 업로드 기능 O- application/json이 아닌 form-data형식으로 받아와야함
- Json은 이미지를 전송할 수 없음.
- 가져온 파일은 resources 폴더에 저장
- 저장 처리
TASK3 : 세션 처리O- 권한 있는 사람만 url 요청할 수 있게 해야하고
- 파일과 함께 받은 토큰으로 membername 세팅해야한다.
Today I Learn
1. VIEW
- 문제 1 : 리액트에서 문제 있으면 프로젝트 빌드 불가
- 해결 : npm start로 View단 문제 해결한 뒤에 다시 올려야 함
- 문제 2 : 로그인한 상태에서 또 다시 회원가입 신청하면 오류남
- 이유 : 모르겠음====> 해결필요!!!!!!!!!!!!!!!!!!
- 추가하고 싶은 기능
- 회원가입에서 중복체크 완료되면 버튼 못누르게 처리하기
- localStorage에 안전성 이슈가 있다. 캐시에 저장하는 방법 찾기
2. GIT
- 문제 1
- 원인 : 내 저장소에 있는거 조직에 PULL REQUEST 하려했음. 그런데 file conflict 발생함. 어차피 조직 저장소에 있는 파일은 사용할 코드가 없었기 때문에 조직 저장소 파일 중 conflict 나는 파일을 다 삭제함.
- 결과: 다 꼬였다…. ==========> 해결필요
- 배운거
- 알게 된 것들
- 인텔리제이에 브랜치 체크아웃한거 반영 안되면 reload from the disk
- Pull request에서 merge conflict나면 커맨드 라인 추천 참고해라
- Reset과 revert의 차이(되돌리기)
- 다른 리포지토리의 특정 브랜치만 가져오기 : git pull 저장소명 브런치명
- (예시) Git pull http://github.com/codingwarriorss/movie_community feature/review
3. BACK
[TASK1 디버깅 과정 (완료)]
1. Member - review - image 테스트 : pk 모두 id로 놓으면??
- 다 컬럼명 id로 나옴 => 그래도 구분 가능할둣?
2. Review에서 member로의 @JoinColumn 설정
- 시도1 : Member 테이블에서 id라고 설정해줬기 때문에 @Joincolumn(id)로 설정했다.
- 결과 : id (should be mapped with insert="false" update="false")
- 시도 2 : 유튜브를 참고하니 Member 테이블에서 설정한 변수명과 상관없이 @JoinColumn(memerId)로 설정하는 것을 보았다. 따라해보았다.
- 결과 : 성공!
- 이유 : 해당 테이블에서의 pk 컬럼명을 적는 것이 아니라, 현재 테이블에서 fk를 어떤 컬럼명으로 설정할지를 적는 것이다.
3. Review와 Image 연관관계 설정하기
- 하나의 게시물이 가진 이미지를 조회하는 기능이 필요(R --> I)
- 하나의 이미지가 어떤 게시물의 이미지인지 조회? 필요없(I -X-> R)
- 하나의 게시물이 여러개의 이미지를 가진 1대다 연관관계이다.
- 단방향 연관관계이다.
- 즉, '다'인 이미지가 fk를 가지게끔 Image 클래스에 Review를 추가한다.
- 결과 : 성공!!
4. 커밋하는데 갑자기 프론트쪽안된다.
오류 메시지 :npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path C:\Users\anyej\Downloads\movie_community/package.json
npm ERR! errno -4058
npm ERR! enoent ENOENT: no such file or directory, open 'C:\Users\anyej\Downloads\movie_communnpm ERR! enoent ENOENT: no such file or directory, open 'C:\Users\anyej\Downloads\movie_commun
ity\package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! Enoent
Enoent: 말 그대로 파일 또는 디렉토리가 없을 경우 나오는 에러이다
- Package.json을 지우고 다시깔라는 글을 봤다…. 이게 뭐지?
- package.json은 프로젝트 정보와 의존성(dependencies)을 관리하는 문서입니다.
- 이미 작성된 package.json 문서는 어느 곳에서도 동일한 개발 환경을 구축할 수 있게 해줍니다.
- JSON 포맷으로 작성해야 하며, 다음과 같은 옵션들이 추가될 수 있습니다.
- 그럼 설정 다시 해줘야 되는 부분..? 는 바보였따……
- 해결 : frontend 밑에서 npm start해줘야되는데… 다른 디렉토리에서 실행해서 나온문제 ㅠㅠㅠ 말 그대로 경로 잘못되서 그런거였음.. 바보멍청아!!!
[TASK2 디버깅 과정 (완료)]
1. 파일 업로드 방법? [참고 : https://caileb.tistory.com/152]
- 스프링 프레임워크 환경의 서버라면, 스프링에 제공하는 MultipartFile 클래스와 MultipartHttpServletRequest 클래스를 사용해서 File 업로드 기능을 구현할 수 있다. (Content-Type : multipart/form-data)
- 3가지 방법
- @RequestParam MultipartFile 타입 사용
- SevletRequest 혹은 MultipartHttpServletRequest 타입 사용
- 사용자 정의 class 타입 사용
- 1번째 방법의 특징 => 레퍼런스가 있으므로 이걸 써보겠따.
- 1번째 방법 : 요청파라미터 타입을 @RequestParam 어노테이션과 함께 사용하는 경우
- (장점) 서버는 클라이언트의 HTTP 요청 메세지에 포함된 파라미터들을 모두 분리해서 컨트롤할 수 있기 때문에, 요청 파라미터 타입 중 MultipartFile타입에 해당하는 한가지를 직접 골라서 file데이터를 다룰 수 있다.
- (단점) file데이터 외에 다른 파라미터들 (String, Integer, MultipartFile) 을 몇가지 추가해서 함께 받는 다면 코드가 조금 지저분해질 수도 있다.
- 3번째 방법의 특징 => 이것도 가눙한가?
- 해당 클래스를 정의할 때 File을 받을 수 있는 MultipartFile 타입 변수를 클래스내에 함께 작성해두면 된다.
- 3번째 방법: 요청파라미터 타입을 사용자가 정의한 클래스 타입(커맨드 객체)으로 사용하는 경우.
- 서버는 클라이언트의 HTTP 요청 메세지에 포함된 파라미터들이 모두 자동으로 사용자가 정의한 클래스의 구조에 맞게 파싱되기 때문에, 개발자는 하나의 Command Object로 컨트롤할 수 있다.
- (장점) 요청 파라미터를 여러 개 받는 것다 코드가 훨씬 깔끔해질 수 있다. 선호하는 사람 많음
2. Getinthere 따라하기 [https://blog.naver.com/getinthere/221735956499]
- Application.yml에 path 옵션 추가
- ReviewController
- Uuid : 식별자
- @value : application 속성 파일에 있는 프로퍼티를 읽을 때 쓰는 어노테이션
- 1차시도 (postman으로 시도)
- Postman사용법 : https://velog.io/@k904808/Postman%EC%9C%BC%EB%A1%9C-%ED%8C%8C%EC%9D%BC%EC%A0%84%EC%86%A1-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%98%EA%B8%B0
- 오류 : the request was rejected because no multipart boundary was found
- 해결 : Content-Type을 제거했다. [https://stackoverflow.com/questions/36005436/the-request-was-rejected-because-no-multipart-boundary-was-found-in-springboot]
- 문제2 : 파일 전송하면 500error 뜨면서 서버 터짐
- @RestController는 뭐고 @Controller는 뭐지? View를 반환할 것인지 데이터를 반환할 것인지 차이(무관함)
- 해결: @RequestUrl 에 넣고 걍 @Post만
- 문제3 : 파일 전송 완료 후에db 저장 문제
- TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.codeworrisors.Movie_Community_Web.model.Review.member -> com.codeworrisors.Movie_Community_Web.model.Member
- 참고자료 : https://m.blog.naver.com/PostView.nhn?blogId=rorean&logNo=221479709787&proxyReferer=https:%2F%2Fwww.google.com%2F
- @OneToMany 또는 @ManyToOne 을 사용할 때 Parent에 추가하는 Child 개체가 아직 데이터베이스에 저장되지 않아서 생긴 문제입니다.
- cascade = CascadeType.ALL 을 포함해야 에러 메시지가 출력되지 않습니다.
- 참고할 자료 !!! Cascade에 대해서 : https://velog.io/@max9106/JPA%EC%97%94%ED%8B%B0%ED%8B%B0-%EC%83%81%ED%83%9C-Cascade
- 저장 성공
- 그런데 생각해보니까 image 엔티티만 만들어놓고 이 엔티티를 다룰 repository를 안만들어 놈
4. 이미지와 리뷰? 양방향이다.
- 리뷰에서도 이미지 가지고 있어야 함.
5. Arrays.asList 쓰니까 이상한 값 들어간다.
- 그냥 new로 생성해줘서 해결
[TASK3 디버깅 과정]
1. 토큰 인증으로 로그인해서 리뷰 저장하기
- 실행 결과 : detached entity passed to persist: com.codeworrisors.Movie_Community_Web.model.Member
토큰으로 인증하는 코드에서 한 번 더 db에 해당 멤버 정보를 넣으려하는 것 같다.- 연관관계 설정 문제임
TODO
1. 토큰 인증 로그인 완료하기
- 테이블 재설계(각 객체 연관관계 설정)
- CASCADE?
3/15 (월)
Today's task
1. 로그인, 회원가입 UI2. 스토리지 저장기능 연동3. 로그아웃 기능
4. 로그인, 회원가입 로직 수정하기
- CASE
중복체크 이후에 다른 아이디 입력하고 가입하는 경우- 정보 수정 : id로 찾아서 set만 호출하면 됨
- 비밀번호 문자, 숫자, 특수문자 포함 확인
- UI 수정
중복 체크 버튼 크기- 필수 사항에 빨간 체크
비밀번호 확인 이후 초록색으로 변경
Today I Learn
1. 에자일개발론, 스크럼개발론, MVP개발방식
- MVP 개발이란 [https://sjlim2.medium.com/mvp%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%9D%EA%B0%81-9ec642cff699]
- Minimum viable product 우리 서비스를 사용하기 위해 최소한의 서비스만을 우선적으로 개발하고, 그것을 고도화시켜가는 방식으로 개발
- 에자일 방식
- 짧은 단위의 작업 계획 구축 : (~4/3일 까지)
- 한 가지 기능에 대한 시제품을 만들어 나가는 사이클을 반복 : 각 기능별로 스프린트 나눠서 개발
- 스크럼 개발방법론(애자일 개발과정의 하나) https://medium.com/dtevangelist/scrum-dfc6523a3604
- 제품 백로그 : 개발할 제품의 전체 요구사항
- 스프린트 : 계획, 개발, 리뷰 작업 단계를 포함하는 하나의 사이클(보통 1주~4주)
- 일일 스크럼 회의 : 매일 어제 한일, 오늘 할일, 해결해야 할 장애/문제 요소를 공유하는 회의(매일 15분 정도 수행)
- 스프린트 리뷰 : 스프린트 마지막날 개발자가 개발한 내용을 시연하고 검토(매 스프린트마다 1번 4시간)
- 스프린트 회고 : 스프린트 마지막날 좋았던 점, 개선할 점을 도출하고 더 나은 방향으로 개선
2. 로그인, 회원가입 UI [코드 참고 : https://www.remotestack.io/react-bootstrap-login-register-ui-templates/]
1) 부트스트랩 사용하기
- npm install bootstrap --save
- Src/App.js 에 import 하기
2) LoginComponent.jsx에 로그인 페이지 구현
- loginApp 안써도 될듯.
- LoginComponent는 App.js에 연결됨
3) SignupComponent.jsx [서비스 따로 두지 않기->로그인처럼 인증관련 서비스 많지 않기 때문]
- 회원가입 뷰
- Input tag는 onchange={changeHandler}에서 Name을 기준으로 현재의 value값을 넣어준다.
- onChange 이벤트가 발생하면, e.target.value 값을 통하여 이벤트 객체에 담겨있는 현재의 텍스트 값을 읽어올 수 있습니다.
TODO
1. [View] 로그인/회원가입 기능 마무리
2주차 (3/8~3/14)
3/14 (일)
Today's task
1. 게시물 작성 백엔드 기능
- Review 엔티티 만들기
- DB 저장
- 테스트 코드
Today I Learn
1. GIT
1) 브랜치 지우기
- 로컬 브랜치 지우기 : git branch -d feature/createboard
- 원격 브랜치 지우기 : git push origin --delete feature/createboard
2. 백단
1) 회원가입 로직 수정 필요성
- 다른 아이디로 중복확인하고, 새로운 아이디로 회원가입 가능함(db에 이미 있는 id면 가입 제대로 안될 것)- 주소 API 사용하기
- 빨간색으로 필수로 넣어야할 영역 표시하기
- 아이디 중복확인 버튼 오른쪽으로 밀기- 생년월일/휴대폰번호에 문자 들어가면 안되게 하기- 잘못된 이메일 형식 막기- 새로고침? X (form으로 되어있기 때문)2) 리뷰게시물 CRUD 로직 (멤버와 1:N)
- Review 엔티티 생성하기 => 시퀀스 생성오류
- 내용 : @GeneratedValue(GenerationType.IDENTITY) 라인에서org.hibernate.dialect.identity.IdentityColumnSupportImpl does not support identity key generation 오류 발생
- 해결방법
- 첫번째 {https://stackoverflow.com/questions/24009042/org-hibernate-dialect-oracledialect-does-not-support-identity-key-generation}
- @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "review_Sequence")
- @SequenceGenerator(name = "review_Sequence", sequenceName = "REVIEW_SEQ")
- 두번째
- @GeneratedValue(strategy = GenerationType.AUTO)
- 첫번째 {https://stackoverflow.com/questions/24009042/org-hibernate-dialect-oracledialect-does-not-support-identity-key-generation}
- 문제원인
- 첫번째 해결방법 설명 : 사용중인 Oracle10g 버전에서는 해당 어노테이션 지원불가
- 현명님 설명 : IDENTITY는 MY SQL등 AUTO INCREMENT가 가능한 시스템에서 사용하는 방식이다. 오라클은 사용할 수없?
3) 생성자 어노테이션 사용법
- allArgumentConstructor => 전체 생성자
- NoArgumentConstructor => 디폴트 생성자
- Required =>생성자에서 필요한 의존성 주입
4) JUnit 테스트
- 코드 참고 : https://stackoverflow.com/questions/41315386/spring-boot-1-4-datajpatest-error-creating-bean-with-name-datasource
- 설명 참고 : https://4whomtbts.tistory.com/128
- 1) 테스트 러너 설정 : @RunWith(JUnit 기본 러너 대신 사용할 러너를 지정)
- 러너 : 테스트 실행 프로세스를 계획하고 실행시키는 주체
- SpringRunner : SpringJUnit4ClassRunner의 단축어
- 특징 : 유닛 테스트 전에 Spring container를 시작하는 작업을 포함하기 때문에 오버헤드가 크다.
- 써야하는 상황
- 컴포넌트 주입이 필요할 때
- 설정 데이터 주입이 필요할 때
- 따라서 스프링과 관계없는 기능을 테스트할 때는 사용을 지양하자.
- 2) @RunWith와 @SpringBootTest의 차이
- 전자가 더 가볍다. 일부 스프링 기능만을 사용
- 후자는 ApplicationContext를 모두 적재하기 때문에 시간이 오래걸린다.
- 3) @DataJpaTest
- JUnit4를 사용하면 @DataJpaTest를 사용할 때 반드시 @RunWith(SpringRunner.class)를 해줘야 한다.
- 4) @AutoConfigureTestDatabase 속성
- Replace.None : 프로퍼티스 파일에 설정해놓은 DB
- Replace.ANY : 내장 DB
- 5) @DataJpaTest : 각 테스트 메서드마다 테스트 따로 실행가능하다.
- 6) 생성자 주입한 경우 테스트 사용방법 구현해보았다.
5) Review CRUD기능
- 1) 서버
- @RequestBody를 메서드 인자에 넣어줘야 클라이언트로부터 값을 받을 수 있다.
- JPARepository CRUD 메서드
- CREATE : 모든 컬럼값이 있어야 정상적으로 삽입가능
- UPDATE : PK값만 있으면 업데이트 가능
- 프론트에서 이전의 상태까지 모두 가지고 있다가, 수정된 부분만 수정해서 전체 내용 보내줘야 제대로 수정가능할 듯? 아니면 save() 호출하면서 다른 부분 다 NULL될 거 같다.
- DELETE : PK값만 있으면 삭제가능.
- 존재하지 않는 PK값으로 호출해도 exception 안던진다.
- 2) 클라이언트
- 삽입 Request 보낼 때 모든 컬럼값을 key로 설정해줘야 (따로 세팅을 하지 않는다면) null로 삽입되지 않는다.
- {
- "content" : "time need?",
- "movieTitle" : "zxcv",
- "imageUrl" : "zxcv",
- "createDate" : "" // 어차피 timeStamp로 찍지만 써줘야 된다.
- }
- 삽입 Request 보낼 때 모든 컬럼값을 key로 설정해줘야 (따로 세팅을 하지 않는다면) null로 삽입되지 않는다.
6) DATA JPA CRUD TEST 참고 자료
TODO
1. 시큐리티 마무리
- UI 변경
- 로그인
- 회원가입
- 스토리지에 토큰 저장
2. 애자일 방식 적용해보기
3/13 (토) => 코테
Today's task
Today I Learn
TODO
3/12 (금)
Today's task
1. 프로젝트에 적용하기
- 백단 : 시큐리티로 로그인 처리, 인가 처리
Today I Learn
1. 시큐리티 노트에 써놓음
TODO
1. [시큐리티]UI 변경
2. [게시물 작성] 스프린트 시작
- API 설정
- 역할 나누기 전에 먼저 현명님이랑 조금씩 진행
- 뷰/백
3/11 (목)
Today's task
1. 시큐리티 플젝 따라하면서 공부 (데어프로그래밍) (완료)
- JWT 플젝 실습 (완료)
2. 프로젝트에 적용하기
- 백단 : 시큐리티로 로그인 처리, 인가 처리 (미완)
Today I Learn
1) 회원가입 완료되어 있는 아이디로 로그인 요청시 401 unAuthorized error 발생
- '/join'을 처리하는 메서드가 Controller에 없었기 때문에 `asdf`, `asdf`로 직접 암호화를 하여 DB에 INSERT를 했다.
- DB에 직접 저장한 비밀번호와 클라이언트로부터 받아와서 BCyrpt~얘로 암호화한 값이 달라서 생기는 문제였다.
- DB를 클리어하고, '/join' 메서드를 만들어 서버에서 회원가입이 되도록한 뒤에 요청하니 해결되었다.
1-1) 에러
1-2) 해결 : 서버에서 회원가입 후 로그인 시도
2) @RequiredArgsConstructor 어노테이션 쓰임
- 클래스에 선언해 놓은 인스턴스 변수에 대한 생성자가 필요할 때 코드를 작성할 필요없이, 필요한 파라미터 값을 모두 가진 생성자를 자동생성해주는 어노테이션
3) jwt + 시큐리티 프로젝트 실습
TODO
1. 프로젝트에 적용하기
- 백단 : 시큐리티로 로그인 처리, 인가 처리
3/10 (수)
Today's task
1. 전체 프로젝트 진행방향 회의 (완료)
- 시큐리티 (~3/11 목)
- 다음 스프린트 6일씩 잡고, 매 스프린트마다 `api 설정`, `뷰`, `백`, `테스트`, `문서 정리` 로 진행
2. 시큐리티 플젝 따라하면서 공부 (데어프로그래밍)
- OAuth 2.0 플젝 실습 (완료)
- JWT 실습 전 기본 지식 (완료)
- JWT 플젝 실습 (미완)
Today I Learn
1) [JPA] JPA의 등장 배경 : sgc109.github.io/2020/07/26/jpa-basic/
- SQL 작성 안하게
- 코드가 DB에 의존하지 않게 => 따라서 upload와 같은 테이블 엔티티도 필요한 것
2) [GIT] 새로 생성한 로컬 저장소 원격 저장소와 연결하기
TODO
1. 시큐리티 플젝 따라하면서 공부 (데어프로그래밍)
- JWT 플젝 실습
2. 프로젝트에 적용하기
- 백단 : 시큐리티로 로그인 처리, 인가 처리
3/9 (화)
Today's task
1. 사용자 도메인 수정 -> (현재) api/members/join에서 아이디 중복체크 -> (변경 후) api/members/checkid로 중복체크 후 join으로 바로 가입 (완료)
2. [Front]
- fetch -> axios로 변경 (미완)
- feature/logjoin develop에 머지하기 (완료)
- feature/Client에 백단 로직 반영하기 (완료)
3. 전체 프로젝트 계획 세우기(~4/3)
4. 스프링 시큐리티 공부 방향 잡기
- 기본 흐름 잡기 (테코톡) (완료)
- 시큐리티 플젝 따라하면서 공부 (데어프로그래밍) (미완)
Today I Learn
1. [GIT] branch merge 방법 (빨리감기)
- logjoin브랜치 일단 devleop pull 해서 똑같이 만든 후에 develop에 merge
- fast forward 식 merge
- backlog.com/git-tutorial/kr/stepup/stepup2_4.html
2. [Back]
1) 클라이언트에서 JSON값 받아올 때 모든 요청은 (@RequestBody Member member)로 받아오는 것이 낫다.
- (String id)로 받아오게 되면, parsing 따로 해줘야하기 때문에 귀찮아진다.
2) 생성자 주입 쓰는 경우에 testcode?
3. [Front]
1) memberPassword2 undefined 에러.
- 비밀번호 확인 기능 넣으면서 생성자의 this.state= {}에 해당 변수를 초기화하지 않았다.
2) App.js 에 오탈자 제거
3) 자바스크립트에서 json 타입의 변수는 일반변수와 선언방식이 다르다!!
- const {data} = {}가 아니라 const data = {}
4) memberIdIsPossible 변수 value 변화 안됨.
- fetch()는 비동기로 처리되기 때문에 setState()는 값이 담기기전에 처리되서 response로 받아온 값으로 초기화가 안되었다.
5) fetch 안에서 바로 setstate() 못하는 문제
- 다음과 같이 that이라는 지역변수를 사용해서 해결했다.
stackoverflow.com/questions/49684217/how-to-use-fetch-api-in-react-to-setstate
TODO
1. 전체 플젝 방향 회의
2. 스프링 시큐리티 공부 방향 잡기
- 기본 흐름 잡기 (테코톡) (완료)
- 시큐리티 플젝 따라하면서 공부 (데어프로그래밍)
3/8 (월)
Today's task
1. [피드백] @Data 어노테이션 대체하기
2. [피드백] @Autowired 생성자 DI 주입
3. [Back] 사용자 도메인 - 수정, 삭제 기능 추가
4. [Front] 아이디 중복확인, 비밀번호 일치여부 확인, 공백 체크 기능 추가
Today I Learn
1. [Back]
A) lombok : JPA와 같은 ORM을 사용할 때, @Data 어노테이션을 사용하면 안되는 이유
- @Data 어노테이션은 @toString을 포함한다.
- 객체가 서로를 참조하고 있을 때 toString이 호출되면, 무한 루프에 빠지게 된다.
public class Member { private String id; private String pw; private Address addr; @Override public String toString() { return "Member [id=" + id + ", pw=" + pw + ", addr=" + addr + "];"// Address의 인스턴스를 참조 } } public class Address { private String zipcode; private Member member; @Override public String toString() { return "Address [zipcode=" + zipcode + ", member=" + member + "]"; // Member의 인스턴스를 참조 } }
B) Spring Framework : 의존성 주입시 필드/세터 주입보다 생성자 주입을 권장하는 이유
- 참고 : madplay.github.io/post/why-constructor-injection-is-better-than-field-injection
- 순환 참조 방지 : 프로젝트가 커지면 여러 컴포넌트 간에 의존성이 생긴다. 비즈니스 로직으로 인하여 서로의 메서드를 순환 참조하는 형태의 코드가 짜질 수 있다(객체 지향적인 관점에서 아주 안 좋음). 필드/세터 주입에서는 오류 없이 동작하지만 stackoverflow 런타임에러가 발생한다. 생성자 주입에서는 BeanCurrentlyInCreationException 예외가 발생하여 어플리케이션 자체가 구동되지 않는다. 따라서 발생할 수 있는 오류를 사전에 체크할 수 있다.
- 테스트에 용이 : 매우 간단하게 테스트코드를 작성할 수 있다.
SomeObject someObject = new SomeObject(); MadComponent madComponent = new MadComponent(someObject); madComponent.someMadPlay();
- 불변성 : 필드 주입과 세터 주입은 해당 필드를 final로 선언할 수 없기 때문에, 초기화 이후에도 Bean 객체가 변경될 여지가 있다. 하지만 생성자 주입은 필드를 final로 선언할 수 있기 때문에, 런타임 환경에서 객체가 변경될 때(일어나기 힘든 경우지만) 발생할 수 있는 오류를 사전에 방지할 수 있다.
@Service public class MadPlayService { private final MadPlayRepository madPlayRepository; public MadPlayService(MadPlayRepository madPlayRepository) { this.madPlayRepository = madPlayRepository; } }
2. [Front] React
- input 태그의 value get : const {name} = this.state;
- this.state 인식 못함 => bind 문제 (constructor에서 bind)
- 비밀번호 일치 체크 : onkeyup 이벤트 사용
-아이디 중복체크 : JSON 반환값 처리
- submit 전 공백 체크
- e.preventDefault()란? 기본적으로 정의된 이벤트를 작동하지 못하게 한다.
form에서 onSubmit()을 통해 submit을 하면 이벤트 완료 후 refresh가 된다.
하지만 리액트로 만드는 SPA 앱에서 원하는 이벤트가 아니다.
따라서 e.preventDefault()를 활용하여 추가로 이벤트를 전파하지 않고 취소하게끔 설계하는 것이다.
**checkID로 아이디 중복체크하는 함수에서도 써줘야 함
- 코드 수정이 브라우저에서 반영안될 경우 => 캐시 삭제해보기
3. [GIT] 잘못된 브랜치에서 작업하고 있었을 때 checkout 시도 => overwritten 경고 오류 해결
- 참고 : blog.hodory.dev/2020/02/18/error-Your-local-changes-would-be-overwritten-by-merge/
- git stash : 현재 staging 영역에 있는 파일의 변경사항을 스택에 넣어둔다.
- git checkout origin feature/logjoin : 이동
- git stash pop : stash 명령어로 스택에 넣어둔 변경 사항 auto 적용시킨다
- intellij 의 resolve conflict로 사용할 코드 선택
- git commit
- git push origin feature/logjoin
*아이텀 : git bash 명령어 자동완성
**logjoin에 frontend 디렉토리 ...
Todo
1. 사용자 도메인 수정 -> (현재) api/members/join에서 아이디 중복체크 -> (변경 후) api/members/checkid로 중복체크 후 join으로 바로 가입
2. [Front]
- fetch -> axios로 변경
- feature/logjoin develop에 머지하기
- feature/Client에 백단 로직 반영하기
3. [GIT] intellij git authorization 문제 해결
4. 전체 프로젝트 계획 세우기(~4/3)
1주차
3/5 (금)
Today's task
1. 회원가입, 로그인 로직 (사용자 기능 로직 짜기) *spring data jpa로
- 패키지 구조, 클래스명 다르니까 merge시 conflict 발생했다.
2. git branch : master > dev > feature/members... 로 파서 진행 => 제대로 정리하기
3. 프로젝트용 오라클 접속 계정 만들기
Today I Learn
1) [GIT] 자주쓰는 명령어
- 원격저장소에 새로 등록된 브랜치 로컬저장소로 가져오기 : git remote update
- 현재 branch에 새로 update된 내용 가져오기 : git pull
- dev에서 분기해서 feature/xx 작업하기 : git checkout -b feature/login dev
- feature/xx 작업 완료 이후 dev에 반영하기
- merge conflict 날 때 해결방법 : intellij에서 unstashchanges 체크하고 다시 merge
2. [Oracle] 접속 계정 생성(develop , 1234)
3. postman 사용법
Todo
- 회원 수정, 삭제 기능 추가
- 게시글 생성 기능
3/4 (목)
Today's task
1. [완료] oracle - spring 연동 문제 해결
1. [미완] spring data jpa로 변경
2. [완료] join/login/front 머지하기
Today I Learn
1) git dev 아래 feature/join 넣는 법 => checkout 옵션=> 정리*************
Todo
- 구조도 다시 짜기 (머지하니까 다 겹쳐...conflict 대박임)
- 현명님이랑 나눠서 구조 다시?
- spring data jpa로 변경
3/3 (수)
Today's task
1.[완료] 회원가입 기능 버그 고치기
- 문제원인 : <createUserFrom.html> input 태그에 'name'값을 VO의 변수명과 동일하게 설정해야 한다. 'id'값이 아님
2.[완료] oracle 11g - spring - jpa 연동
3.[완료] git branch 따로 파서 작업하기 [master -> dev -> feature/join]
Today I Learn
1) [해결] 회원가입 기능 디버깅
- createUserForm.html에서 submit한 이후부터 정상적으로 작동하지 않았다. (500 error - whitelabel...)
- join()과 관련 메서드는 이미 단위 테스트를 했기 때문에 백단의 문제는 아니었다.
- 콘솔에 찍어보니 html파일에서 값을 제대로 받아오지 못했다.
- 문제는 input 태그에 name 속성을 주지 않았기 때문이었다. id를 name과 혼동했다.
- Spring은 input의 'name'을 기준으로 VO의 변수명과 대조해보고 객체를 만들어 반환하기 때문에 반드시 name 속성을 줘야 한다.
2) [해결] 깃 작업 브랜치 분기
- 내가 작업할 브랜치를 생성하고 체크아웃하면 생성한 브랜치(내 작업 브랜치)로 이동한다.
- 작업한 결과를 커밋, 푸시하면 원격 저장소에 있는 해당 작업 브랜치에만 작업 결과가 반영된다. (아직 merge, pull request.. 할 필요없음)
3) oracle 11g + spring 연동
- sql developer나 intellij의 datasource에서 접근하는 건 문제 없었다.
- 근데 spring 프로젝트가 db에 접근을 못한다. 왤까....
- 현명님이 docker 환경에서 실행하신건 괜찮았눈데, 고쳐봐야겠답.
4) [해결] oracle ID, PWD 헷갈려 ㅇㅂㅇ
- id: system, pwd: 1220
5) [해결] Oracle 예약어 컬럼명으로 설정할 경우 에러
- USER 테이블의 PK를 'UID'라는 컬럼명으로 설정하기로 했다. 그런데 'UID' 오라클 예약어이기 때문에 오류가 있었다. 예약어 잘 알아보고 컬럼 설정해야할 듯
- UID(시퀀스) 컬럼을 굳이 둘 필요없이 USER_ID(VARCHAR2)를 PK로 두면 될 것같다. (참고. www.gurubee.net/article/66137)
6) 프로세스 id 찾기
- netstat -ano | findstr 8080
Todo
- 회원가입 기능 oracle+spring data jpa로 변경
- login/join/front 머지해보기
3/2 (화)
Today's task
1. 회원가입 기능 구현 *인프런 김영한 스프링 기본 참고 (완료)
- 요구사항 : 스프링 부트, MVC 패턴
Today I Learn
1) [해결] Intellij가 종종 Spring 라이브러리를 제대로 인식하지 못하는 문제가 있었다.
- 해당 프로젝트 내의 .idea 디렉토리를 설치한 뒤에 인텔리제이를 시작해서 라이브러리를 다시 설치하게 해서 문제를 해결했다.
2) [해결] thymeleaf 템플릿엔진으로 html을 랜더링 한 뒤에, 사용자로부터 정보를 받아와서 map형태로 저장하는 기능을 구현했다. 하지만 memory 저장이 안되는 문제가 있었다.
- input 태그에 'name'값을 VO이름과 동일하게 설정해야 한다. 'id'값이 아님
Todo
- 회원가입 기능 버그 고치기 (html로부터 읽어들인 내용 map에 저장 안되는 문제)
- 오라클 설치하고 spring에 설정파일 입력
- git branch -> dev -> function/join 에서 작업하기
'Programming > Note' 카테고리의 다른 글
[개발노트] Spring Security + JWT + React(SPA) 진행 상황 (0) 2021.03.13 [개발 노트] Spring Security + JWT + React(SPA) 디버깅 과정 (0) 2021.03.13 [개발노트] Spring + JPA + Oracle 연동 문제해결 (0) 2021.03.05 댓글