이번에 시도하는 것들 :
ERD
JWT를 활용하기
JPA 연관관계 설정
1. ERD (Entity Relation Diagram)
2. API 명세서
2-1 숙련 Lv1
1) 새로 구현하는 기능
기능 | 메서드, URL | 요청 | 응답 |
회원가입 | POST, /api/posts/signup | { "username" : String, "password" : String, "email" : String, } |
success |
로그인 | POST, /api/posts/login | { "username" : String, "password" : String } |
success |
2) 수정하는 기능
기능 | 메서드, URL | 요청 | 응답 |
게시물 작성 | POST, /api/posts |
{
"title":"제목",
"username":"글쓴이",
"contents":"내용을 작성했습니다",
}
|
{
"createdAt": "2022-12-16T21:01:52.84332", "modifiedAt": "2022-12-16T21:01:52.84332",
"id": 1,
"userId": 1,
"title": "제목",
"username": "abcedd",
"contents": "내용을 작성했습니다"
} |
선택 게시물 조회 | GET, /api/posts/{id} |
{
"createdAt": "2022-12-16T21:01:52.84332", "modifiedAt": "2022-12-16T21:01:52.84332",
"id": 1,
"userId": 1,
"title": "제목",
"username": "abcedd",
"contents": "내용을 작성했습니다"
} |
|
게시물 수정 | PUT, /api/posts/{id} | { "title": "제목", "username": "abcedd", "contents": "내용을 수정했습니다" } |
void 반환(추후 PostResponseDto 객체반환예정) |
게시물 삭제 | DELETE, /api/posts/{id} | "삭제되었습니다." |
2-2 숙련 Lv2
1) 새로 추가하는 기능
기능 | 메서드, URL | 요청 | 응답 |
댓글 작성 | POST, /api/posts/{id}/comments |
{
"username" : "usualuser",
"comment" : "댓글을 작성했습니다."
}
|
{
"id": null,
"userId": 1,
"postId": 1,
"username": "usualuser",
"comment": "댓글을 작성했습니다."
}
|
댓글 수정 | PUT, /api/posts/{id}/{commentId} |
{
"username" : "usualuser",
"comment" : "댓글을 수정했습니다."
}
|
void 반환(추후 CommentResponseDto 객체반환예정) |
댓글 삭제 | DELETE, /api/posts/{id}/{commentId} | "삭제되었습니다" |
2) 수정하는 기능
기능 | 메서드, URL | 요청 | 응답 |
관리자 - 회원권한 부여하기 | POST, /api/posts/signup | { "username" : "administer", "password" : "passwword1@", "email" : "ddd@gmail.com", "role" : "AAABnvxRVklrnYxKZ0aHgTBcXukeZygoC" } { "username" : "usualuser", "password" : "passwword1@", "email" : "ddd@gmail.com", "role" : "" } |
success |
예외처리 |
3. 프로젝트 시작
추가하는 클래스
Entity User
UserService
UserRepository
SignupRequestDto
LoginRequestDto
JwtUtil
CommentController
CommentService
CommentRepository
CommentRequestDto
CommentResponseDto
Entity Comment
22.12.16 트러블 슈팅
- 클래스를 생성한 후 테스트를 위해 실행 : secret key 설정을 깜빡함 -> app 설정에 추가
- 회원가입 기능을 테스트 하기 위해 서버 구동 및 Postman으로 POST 쿼리 발송 :
email 값이 제대로 전송되지 않음 : Http 500, not-null property references a null or transient value 오류
-> 클래스 간 값의 이동이 제대로 되지 않는 경우, 내 경우엔 ajax 형식으로 UserController에서 값을 받기 때문에 @ResponeBody, 파라미터에 @RequestBody를 붙여줘야 했으나 이를 잊어 배달사고 발생 ~ 해결
- 회원가입 시 아이디, 비밀번호의 글자 수 및 속성 알파벳, 숫자 제한 조건 추가하기 : UserService에 추가
+ 정규표현식 사용
참조한 글: https://zzang9ha.tistory.com/322
- JWT 토큰 값이 올바르게 생성되지 않습니다 : 쿠키 헤더가 받은 Bearer 값이 올바르지 않은 쿠키라고 하며 JWT 토큰이 생성되지 않음(로그인을 제대로 하지 않고 글 작성한 경우 발생하는 오류였다) -> PostService의 createPost 메서드에서 토큰을 확인한 후 토큰에 저장된 사용자 정보를 조회 및 요청 DTO의 내용을 객체에 담아 Flush 하는 코드를 잊고 작성하지 않음 : 작성 후 테스트 : 로그인까진 잘 되나, 글 작성 POST 메서드를 날리면 오류는 없지만 DB에 저장이 되지 않고, null 출력 + 디버깅 : token 값이 null이다. -> Postman에서 JWT를 저장해야하는데 이를 놓침 -> JWT 만드는 방법을 공부하다 Postman에서 출력되는 것 확인 후 Postman에 입력 : 해결
22.12.19 (1)
수정/삭제 메서드 작성 중 동일한 에러 발생
"message": "Type definition error: [simple type, class jakarta.servlet.http.HttpServletRequest]"
원인을 도저히 알 수 없음 : 도움 요청
해답 : @ResponseBody 이놈.. DTO 앞에다 붙이는 것이다. 아직 개념이 완전히 자리잡지 못한 결과다.
해결!
타입간 반환에 대한 공부를 더 하고 있다. -> 수정 및 삭제후 결과를 PostResponseDto 타입으로 객체를 만들어 보내기 위한 작업 공부
22.12.19 (2) + 12.20 + 12.21
숙련 Lv2 과제 수행
1. 특수문자까지 필수로 요구하는 비밀번호 작성기능을 정규표현식을 사용하여 구현
~ (?= ) : 긍정형 전방탐색을 활용
참조 : https://okky.kr/articles/298826
2. 회원 권한 부여, 인증/인가 및 권한별 게시글 접근 권한 설정
3. 댓글 관련 기능 추가하기 :
1) 우선 댓글 관련 프로세스를 게시물 작성과 동일하게 처리하는 게 맞겠다는 판단 하에, Comment, CommentController, CommentService, CommentRepository, CommentRequestDto, CommentResponseDto 작성 및 구현
2) 댓글과 게시물 연관관계 설정 -> 게시물 : 댓글 : 사용자 = 1: N : 1
연관관계 설정에 관한 경험 부족 : 포스트 엔티티에서 코멘트 리스트에 대한 필드를 생성하고 관계설정을 해두고 어플리케이션을 실행시켜보려고 했지만, 빈 생성 에러 발생 -> 엔티티에 Timestamped 상속 표시를 안했기 때문..! (+ 왜 상속해야만 하지?)
3) 코멘트리스트에 댓글 추가하기 : 댓글을 추가하였지만 연관관계 설정이 미비하여 리스트에 추가되지 않음
+@Builder 어노테이션을 활용, 엔티티에서 객체를 생성해서 Service에서 메서드를 호출 후 댓글과 게시물을 연결하려는 시도 중..
4) 새로운 시도 : 교재 코드를 활용한 관계설정 후 List 생성, 서비스에서 객체를 생성하고 반복문을 사용하여 List에 객체를 담아 리스트로 반환 후 조회하기 시도
-> 생각하다 보니 Post - User - Comment - Post : n : 1 : n :1? 의 복잡한 관계를 생각하다.. 이게 뭐지..
다시 돌아와서 Post - Commnet의 관계만 1:n으로 설정하고 코드 시도
댓글을 작성할 때 그 게시물 안에 Comment 타입의 어레이리스트를 생성하고 CommentRequestDto의 값을 참조하는 Comment 타입의 객체를 생성, 그 객체를 리스트에 담아 댓글을 작성하는 방식이라는 매커니즘은 이해했지만, 현재 Dto에 적절한 값을 넣지 못한 부분에 도달했다.
12.22
5) 순환참조 에러:
Jackson의 동작원리를 보고 관련 어노테이션인 @JsonBackReference, @JsonManagedReference를 사용하여 문제를 해결했다! + 다만, 아직..
1) 댓글 추가 후 응답란에 댓글의 id가 null로 표시되는 것(DB에는 정상 저장 및 조회할 때도 정상 출력)
2) ResponseDto타입의 객체를 만들어 거기에 완성된 값을 담고 반환한 후 그 객체를 참조하여 순환참조 에러를 원천 차단하는 방식에 대한 이해가 아직 부족함 ~ 이렇게 처리되는 게 맞는지 아닌지도 아직 확실하지 않음
12.28
1) 댓글 생성 메서드의 퀄리티 높이기
@OneToMany(cascade = CascadeType.All) List<Comment> commentList = new ArrayList<>();에서 만들어지는 Post-CommentList 테이블로 인해 마치 다대다 관계에서 처리하는 것같이 값을 저장하는 부분 개선 노력
https://wordbe.tistory.com/entry/Spring-Data-Jpa-JPA
cascade : 연관관계가 있는 엔티티의 변화를 반영한다
fetch : 객체를 가져온다
https://www.youtube.com/watch?v=brE0tYOV9jQ
https://www.youtube.com/watch?v=hsSc5epPXDs
2) 더티체킹에 대한 경험치 +1 :
내가 코멘트 객체를 만들고 ResponseDto타입 객체로 반환하기 전에 DB에 저장을 하지 않았지만 DB에 저장이 된 이유:
Post타입의 객체를 만들 때 JPA가 내가 지시하지 않았어도 1차 캐시 공간에 미리 만들어진 Post타입의 객체가 있는지 확인한다. 이후 없을 때 새로 만들어서 1차 캐시 공간에 저장한다.
그 후 @Transactional 주기가 끝날 때, 나는 그 전에 Comment 타입의 객체를 만들고 그 곳에 RequestDto타입에서 받은 값을 할당한 후 그 객체를 Post 클래스에서 참조한commentList에 추가하고 주기를 끝낸다.
그렇게 되면 JPA는 더티체킹을 하며, post.commentList에 변화가 있다는 것을 알게 되고, 내가 별도로 명령하지 않아도 DB에 변경된 값인, comment가 추가된 commentList를 저장하는 것이다.
12.30
JWT를 추가한 게시물의 수정 및 삭제 기능 구현 시도
연관관계 설정 :
회원가입 하며 만들어 둔 JWT 토큰을 참조하여 게시물 작성 시 해당 토큰을 불러오고 검증을 통해 그 회원이 맞는 지 인증 후 게시물 작성 기능이 수행될 수 있도록 인가
수정/ 삭제 기능도 동일하게 적용, 다만 저번 과제 때 boolean으로 접근해 만들어둔 비밀번호 확인 기능이 더 이상 필요가 없어 수정/ 삭제 메서드 및 PostController에 있는 관련 메서드의 타입을 void로 변경 + 12.19일 트러블 슈팅과 연관되는 내용
4. 체크포인트
처음 설계한 API 명세서에 변경사항이 있었나요? 변경 되었다면 어떤 점 때문 일까요? 첫 설계의 중요성에 대해 작성해 주세요!
- 프로젝트를 수행하면서 새롭게 배우거나 기존에 알았던 내용이 오류가 있던 경우에 변경을 통해 개선했다. 주로 반환하는 값의 타입에 관한 수정이었고, 아직 배움의 뿌리가 자리잡지 못해 생기는 이슈라고 생각한다. 그럼에도 초기 설계를 통해 무에서 유를 창조하는 단계의 접근이 가능하고, 초기 설계를 바탕으로 사고의 확장이 이루어지기 때문에 초기 설계를 우선 완성하는 것이 정말 중요하다 생각했다.
ERD를 먼저 설계한 후 Entity를 개발했을 때 어떤 점이 도움이 되셨나요?
- 이번엔 ERD를 먼저 설계하지 못했다.
JWT를 사용하여 인증/인가를 구현 했을 때의 장점은 무엇일까요?
- 토큰이 매번 암호화 알고리즘을 통해 생성되므로 데이터의 보안을 강화할 수 있고, 토큰이 유지되는 한 Http 프로토콜 안에서 사용자 정보가 보안유지한 상태로 남아있기 때문에 지속성있게 작업할 수 있다고 느꼈다.
반대로 JWT를 사용한 인증/인가의 한계점은 무엇일까요?
- JWT를 활용해 보안을 강화할 수 있지만, 그만큼 구현해야 하는 코드가 증가하는 것이 가장 큰 단점을 다가왔다.
만약 댓글 기능이 있는 블로그에서 댓글이 달려있는 게시글을 삭제하려고 한다면 무슨 문제가 발생할까요? Database 테이블 관점에서 해결방법이 무엇일까요?
- 영속성 문제가 발생한다.
영속성 전이 : 객체를 저장하거나 삭제할 때 연관된 객체도 함께 저장하거나 삭제하는 것을 영속성 전이라고 한다.
DB 관점에서 이를 해결하기 위한 SQL 문을 사용하여 참조 테이블에 기본 테이블 삭제 시 참조 테이블도 같이 삭제되는 속성을 추가해야 한다.
5번과 같은 문제가 발생했을 때 JPA에서는 어떻게 해결할 수 있을까요?
- 고아 객체 제거 기능을 활용한다.
IoC / DI 에 대해 간략하게 설명해 주세요!
- Ioc : 제어의 역전, 사용자가 어떤 클래스의 인스턴스를 사용하기 위해 객체를 생성한 후 인스턴스를 사용하는 것이 아니라, 그 반대로 그 클래스에서 객체를 만들어두고 그 객체를 사용자가 호출하여 사용하는 형태
~ 장점 : 기존의 방식에 비해 수정해야 하는 코드의 양이 감소한다.
- DI : 의존성 주입, Ioc가 원활이 진행될 수 있도록 사용자가 서버에서 만들어진 객체에 의존하여 인스턴스를 사용할 수 있도록 의존성을 "주입"하는 것이다.
'내일배움캠프 4기 스프링 > 프로젝트📙' 카테고리의 다른 글
Spring 프로젝트 Check-list (0) | 2022.12.30 |
---|---|
~12. 19까지 중간 프로젝트 전 개인 과제 리뷰 및 개선할 점 정리 (0) | 2022.12.19 |
개인 과제 : Springboot를 활용한 블로그 Backend 서버 만들기 (0) | 2022.12.08 |
내일 배움 캠프 4기 스프링 두 번째 프로젝트 : 은행 관리 프로그램 (0) | 2022.11.30 |
프로젝트가 끝나고: KPT (0) | 2022.11.29 |