👩🏫 오늘의 출석
(캡쳐하는 걸 깜빡해서 오늘은.. 사진은 없지만..! 출석했다는거!!)
❓마흔아홉 번째, 9 to 9을 해 본 소감❓
지금껏 진행해 온 팀 프로젝트 중에 가장 완벽했다고 생각한다. 이 팀원 그대로 다시 만나서 다시 팀 프로젝트를 진행하고 싶을 정도로 큰 문제도 없고, 단 하나의 불만도 없었고, 다들 열심히 하고, 내가 가장 중요하게 생각하는 소통까지 부족함 없이 완벽하게 잘했던 팀이었다. 팀원 모두가 답변도 빠르게 잘해주면서 서로 배려하며 소통하고, 각자의 파트를 부족함 없이 해내고, 발표면 발표, PPT면 PPT, 튜터님께서 만족하실 정도의 튜터님 및 팀원 서로의 피드백 반영, 거기다 팀장님의 완벽한 코드 리뷰까지 더해져서 진짜, 가장 만족스러웠던 팀 프로젝트였다! 🤗 계속 이 팀원 그대로 남은 팀 프로젝트들을 진행하고 싶을 정도로 만족도가 최고였다! 너무 고마운 우리 자바죠조 팀원들, 또 만날 수 있었으면 좋겠다!
📑오늘 학습한 내용
😎 프로젝트 회고 😎
🗂️ 프로젝트 설명
🪝 아웃소싱 프로젝트 : 치떡치떡 - 치킨, 떡볶이 배달 주문 사이트
치킨과 떡볶이를 판매하는 자바죠조(팀명)만의 가게인 치떡치떡 음식 주문 서비스
이번 프로젝트는 3가지의 주제(1. SNS 사이트, 2. 배달주문 사이트, 3. 익명커뮤니티 사이트) 중에서 하나를 선택하여 진행하는 프로젝트였다.
이번 프로젝트 역시 필수 구현 기능 외에 추가 구현 기능 등이 있었지만 필수 기능 구현을 목표로 진행하였다.
🛠️ 기술 스택
- Java 17
- IntelliJ
- Spring
- SpringBoot 3.3.0
- MySql
🔊 협업 툴
Git, Github, Notion, Zep, Slack
🪄 구현 기능
❗ 공통 조건❗
클라이언트는 Postman이고 프론트엔드는 별도 구현하지 않습니다. 사용자 인증 기능 공통 조건 username, password를 클라이언트에서 전달받습니다. Spring Security와 JWT를 사용하여 설계 및 구현합니다. JWT는 Access Token, Refresh Token을 구현합니다. Access Token 만료 시 : 유효한 Refresh Token을 통해 새로운 Access Token과 Refresh Token을 발급 Refresh Token 만료 시 : 재로그인을 통해 새로운 Access Token과 Refresh Token을 발급 API를 요청할 때는 Access Token을 사용합니다. Access Token, Refresh Token은 동시에 전달을 하는 게 아니고 용도에 맞게 사용되어야 합니다.
1. 사용자 인증 기능
-
회원가입 기능
- 회원 권한 부여
- ADMIN
- USER
- 본인이 작성한 주문, 리뷰에 한하여 수정과 삭제 가능
-
로그인 기능
- 성공
- DB에서 username을 사용하여 회원가입 된 사용자인지 확인한다.
- 회원가입 된 사용자라면 password를 비교하여 로그인한다.
- header에 토큰을 추가하고 성공 상태코드와 메시지를 반환합니다.
-
로그아웃 기능
- 조건
- 로그아웃 시, 발행한 토큰은 초기화합니다.
- 로그아웃 후 초기화 된 Refresh Token은 재사용할 수 없고 재로그인해야 합니다.
-
프로필 관리
- 비밀번호 수정 조건
- 비밀번호 수정 시, 본인 확인을 위해 현재 비밀번호를 입력하여 올바른 경우에만 수정할 수 있습니다.
- 비밀번호는 현재 비밀번호 및 최근 사용한 세 개의 비밀번호와 다르게 설정해야 합니다.
- 프로필 수정 기능
- 이름, 한 줄 소개와 같은 기본적인 정보를 볼 수 있어야 하며 수정할 수 있어야 합니다.
2. 주문 CRUD 기능
- 주문 작성, 수정, 삭제는 인가(Authorization)가 필요합니다.
- 유효한 JWT 토큰을 가진 작성자 본인만 처리할 수 있습니다.
- 조회
- 기본 정렬은 생성일자 기준으로 최신순으로 정렬합니다.
- 페이지네이션 - 페이지네이션하여 각 페이지 당 게시물 데이터가 5개씩 나오게 합니다.
- ADMIN
- 주문한 USER에 상관 없이 전체 주문 목록을 한 페이지에 5개씩 나오도록 하였다.
- USER
- 본인이 주문한 목록에 대해서만 한 페이지 5개씩 나오도록 하였다.
3. 리뷰 CRUD 기능
- 조건
- 사용자는 게시물에 댓글을 작성할 수 있고, 본인의 댓글은 수정 및 삭제를 할 수 있습니다.
- 내용만 수정이 가능합니다.
- 리뷰 작성, 수정, 삭제는 인가(Authorization)가 필요합니다.
- 유효한 JWT 토큰을 가진 작성자 본인만 처리할 수 있습니다.
파트 분배 [4명의 인원, 서로 연관이 있는 기능에 맞게 파트를 나눔]
로그인 / 권한부여 | 회원가입 / 회원탈퇴 / 로그아웃 / 프로필 수정 | 주문 CRUD / 메뉴, 주문 상세 | 리뷰 CRUD |
---|
🏹 트러블 슈팅
1. 주문 CRUD - Order와 OrderDetail 엔티티 사이의 순환 참조 문제
@Entity
public class Order {
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderDetail> orderDetails;
}
@Entity
public class OrderDetail {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
private Order order;
}
문제점 : 위의 코드를 보면 Order 엔티티가 여러 OrderDetail 엔티티를 참조하고, OrderDetail 엔티티는 하나의 Order 엔티티를 참조하고 있음.
이 상태에서 Jackson 라이브러리가 Order 객체를 직렬화할 때, orderDetails 필드를 직렬화하게 되고 각 OrderDetail 객체를 직렬화할 때, order 필드를 직렬화하면서 다시 Order 객체를 참조하는데 이 과정이 반복되어 무한 루프가 발생하여 에러가 났음.
@Entity
public class Order {
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
@JsonIgnore // 순환 참조 방지를 위해 추가
private List<OrderDetail> orderDetails;
}
@Entity
public class OrderDetail {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
@JsonIgnore // 순환 참조 방지를 위해 추가
private Order order;
}
해결 방법 : @JsonIgnore를 사용하여 순환 참조의 문제를 해결함.
Order 직렬화 시, @JsonIgnore를 사용하여 orderDetails 필드를 직렬화하지 않기 때문에 OrderDetail 객체로의 순환 참조가 발생하지 않도록 하였으며, 동일하게 OrderDetail 직렬화 시 @JsonIgnore를 사용하여 order 필드를 직렬화하지 않기 때문에 Order 객체로의 순환 참조가 발생하지 않도록 하여 문제를 해결함.
2. 리뷰 CRUD
문제점 : 데이터 생성 시, 외부 Entity자체를 가지고 있는 Entity를 반환 시, 'Duplicate entry '...' for key '...'' 라는 OneToOne 관계를 가질 때, FetchType.LAZY로 설정된 외부 Entity를 한 번에 조회하지 못해 값이 비어 생기는 오류가 발생함.
해결 방법 : 해당 오류를 고치기 위해 FetchType을 수정하거나 Entity 전체 저장을 하지 않는 방법이 있었고, 전자는 서버에 부담이 가는 방식이므로 후자를 선택함.
3. 프로필 수정
문제점 : 최근 3번의 비밀번호를 user 엔티티에 Queue로 저장을 하여 효율적이지 못하고 유지보수에 좋지 않다는 문제 발생함.
해결 방법 : 새로운 테이블을 만들어서 효과적으로 관리함.
4. 회원가입
문제점 : 회원가입 시 비밀번호가 인코딩 되어 DB에 저장될 때, 엔티티의 정규식 때문에 DB에 저장하지 못함.
해결 방법 : 정규식을 DTO로 옮겨서 해결함.
🤗 좋았던 부분
- Code Convention & Github Rules를 미리 정하고 진행한 점
- 드디어 팀 프로젝트를 진행하기 전에 Code Convention과 Github Rules를 미리 정하고 프로젝트를 진행하였다. Code Convention은 알고 있었는데 팀 프로젝트만 진행하면 할게 많아 잊어버리고 매번 팀 프로젝트 회고 때 아쉬워했었는데 이번 프로젝트 땐 팀원들도 이 부분에 대해 아쉬움을 갖고 있어서 초반에 바로 Code Convention부터 정하고 진행을 했다. 사실 크게 우리 팀만의 새로운 Code Convention을 진행한 건 아니었지만 그래도 사소하지만 잘 지키지 못하는 부분부터 다시 한번 리마인드 하며 진행할 수 있도록 코드 컨벤션을 정하고, 이를 잘 지키며 프로젝트를 진행하다.
- 그 결과 초반에 말했던 한 사람이 작성한 것 같은 깔끔한 코드를 작성할 수 있었고, 튜터님께서 피드백 주실 때도 이 부분을 잘했다고, 정말 한 사람이 작성한 것 같이 주석 스타일부터 해서 잘 맞추어 작성했다고 말씀해 주셨다.
- Github Rules는 잘 몰랐는데 이번 팀 프로젝트를 진행하면서 제대로 알게 되었다. 특별하게 규칙을 정한 건 아니고, 깃헙 커밋 규칙을 지켜서 커밋 메시지를 작업 타입과 작업 내용에 맞게 영어로 첫 문자를 대문자로 작성하여 푸시하도록 정해서 프로젝트를 진행하였다.
- 확실히 지금 누가, 어떤 작업을 어디서 진행했구나 한눈에 알 수 있어서 좋았다.
- 빠른 응답, 활발하게 소통을 진행한 점
- 진짜 지금까지 진행한 그 어떤 팀보다 소통이 잘 되었다. 누군가 질문을 하면 그에 대한 응답이 아주 빨랐고, 슬랙 이모티콘도 잘 달아주고 답변도 누구 한 명 빠지지 않고 열심히 해주었다. 이렇게 빠르게 소통이 되니 코드 작성을 하면서 피드백도 아주 원활하게 진행이 되고, 팀원들의 답변을 기다리느라 아무것도 못하고 시간을 낭비하거나, 소통이 제대로 되지 않아 잘못된 길로 빠지지 등의 문제가 발생하지 않을 수 있어 좋았다.
- GitHub Issue 기능을 사용한 점 & 민감 데이터 환경변수화한 점
- 이 부분은 전에 팀에서부터 계속 진행해 왔던 점이기 때문에 더 말할 것도 없이 좋았다. 하지만 환경변수를 할 때 나는 무조건 yml로만 할 수 있는 줄 알았는데 properties에서도 가능하다는 점을 새로 알게 되었다.
😣 아쉽다고 생각한 부분 & 🤔 개선하고 싶은 부분
- PostMan으로 테스트를 진행하지 말고 IntelliJ http를 사용하여 테스트했으면 어땠을까?
- Postman으로 테스트를 진행할 때 user와 admin을 동시에 로그인하여 번갈아가며 테스트를 진행했어야 했는데 창을 번갈아가며 테스트를 진행하고, IntelliJ log까지 함께 확인을 하려니까 너무 정신이 없고, 테스트 진행하는데 불편함이 있었는데 이 부분을 IntelliJ http를 통해서 해결할 수 있었다. 다른 팀원분이 마지막에 작성을 해주셔서 어떻게 작성하는 건지 제대로 알지는 못했지만 이런 게 있다는 것을 알았고, 다음 프로젝트 때도 적용해보고 싶다.
- 테스트 코드 작성 시간을 조금 더 여유롭게 갖고 작성해 보았으면 어땠을까?
- 이번 개인 주차에서 배운 부분이 테스트 코드를 작성하는 것이었는데 팀 프로젝트 때 이 부분을 잘 적용하지 못한 점이 아쉬웠다. 테스트 코드를 배운 지 얼마 안 되기도 했고, 솔직히 어떻게 작성하는지도 제대로 잘 모르겠어서 도전은 했지만 제대로 작성했다고는 할 수 없었다. 게다가 프로젝트 제출이 얼마 안 남았어서 테스트 코드를 작성할 수 있는 시간이 얼마 되지 않았다. 다른 팀원들도 비슷한 상황이었고 그래서 결국 테스트 코드를 진행해 봤다는 점에만 의의를 두기로 하고 프로젝트를 마무리했다. 다음 프로젝트부터는 테스트 코드도 제대로 작성해서 조금 더 개발자 다운 프로젝트를 진행해 보고 싶다.
- 그동안 진행했던 CRUD 파트가 아니라 로그인 또는 회원 가입 파트를 도전했으면 어땠을까?
- 지난번 팀 프로젝트에서도 게시글 CRUD를 진행했는데 이번에도 내용만 바뀌었지 CRUD를 구현한다는 점에서는 큰 차이가 없어서 다른 파트에 대해 잘 알지 못하는 점이 아쉬웠다. 하지만 아직 실력이 부족해서 CRUD도 겨우겨우 하고 있기 때문에 무사히 팀 프로젝트를 진행하였다는 점에서 만족한다. 나중에 더 실력이 늘면 다른 파트들도 구현해보고 싶다.
- 백오피스까지 진행했었다면 어땠을까?
- 백오피스란 서비스를 제공하기 위하여 상품을 등록하고 마케팅을 설정하고 결제와 매출, 수익 등을 관리하는 서비스를 제공하는 페이지인데, 나는 백오피스라는 것도 이번 프로젝트를 통해서 처음 들어보았다. 우리 팀 프로젝트의 목표가 필수 구현 기능 완성이었지만 백오피스까지는 하고 싶다는 내 개인적인 바람이 있었지만 여기까지는 진행하지 못했다. 다음 프로젝트 때도 만약 필요하다면 꼭 백오피스까지 진행을 해보고 싶다.
💞 이번 팀 프로젝트를 통해 내가 배운 것
1. Github Rules
- 코드 컨벤션이 아니라 Github Rules이 있고, 깃허브 규칙뿐만 아니라 깃허브 커밋 규칙도 있다는 것을 이번 프로젝트를 통해 제대로 알게 되었고, 진행을 해 본 것도 이번 프로젝트가 처음이었다.
2.IntelliJ http를 통한 api 테스트
- 내가 아는 테스트 방법은 IntelliJ log 창으로 확인하는 방법이나, Postman을 사용해서 테스트하는 것이었는데 이번 팀 프로젝트를 통해 IntelliJ http를 사용해서 테스트할 수 있다는 점이었다. 완전 처음 들어보는 테스트 방법이라 어떻게 하는 건지 감도 못 잡고 팀장님께서 작성해 주신 코드를 보고서야 방식을 조금 알았다. 미리 초기 데이터를 만들어준 이유가 IntelliJ http를 사용해서 테스트하기 위함이었다.
- 이 방법을 사용하면 Postman과 IntelliJ를 왔다 갔다 하거나 창을 두 개 이상 띄워두고 테스트할 필요 없다는 장점이 있었다. 다음 프로젝트 시에 다른 팀원들에게 공유하여 이 방법을 또 사용해 봐야겠다고 생각했다.
3. 페이지네이션
- 지난번에는 페이지네이션이 추가 구현 기능 중에 하나였어서 우리 팀은 진행하지 않았는데, 이번 팀프로젝트에서는 내 파트의 필수 구현 기능이어서 진행을 하게 되었다. 배운 적도 없고, 어떻게 하는지도 잘 모르겠어서 시작하기 전에는 조금 겁이 났었는데 그렇게 어려울 건 없어서 이 부분은 큰 문제없이 잘 구현하였다.