Seminar6 + 7 과제 제출 #7
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📝 Work Description
⭐️ 필수 과제
🥇 선택 과제
💡 키워드 과제
그럼 왜 리버스 프록시를 사용할까?
트래픽이 몰릴 경우 하나의 서버만 사용하는 것이 아니라 여러 서버에 요청을 분산시켜 서버의 부담을 줄이고, 서비스가 끊기지 않도록 유지할 수 있다.
클라이언트는 실제 서버의 위치를 알 수 없고, 모든 요청은 프록시 서버를 통해 들어오기 때문에 외부 공격으로부터 내부 서버를 보호할 수 있다.
HTML, CSS, 이미지 등 자주 바뀌지 않는 파일은 프록시 서버가 미리 저장해두었다가 빠르게 응답해줄 수 있어 전체 서비스 속도가 빨라진다.
=> Nginx, Apache, Cloudflare, AWS Load Balancer 등 다양한 도구들이 리버스 프록시 역할을 한다.
쿠키는 주로 서버와 통신할 때 필요한 정보를 저장하는 데 사용된다. 브라우저가 서버에 요청을 보낼 때마다 쿠키에 저장된 데이터도 함께 전송되기 때문에, 로그인 상태 유지나 사용자 인증에 자주 사용된다. 다만 저장 용량이 작고, 서버로 매번 전송되기 때문에 속도와 보안 측면에서 주의가 필요하다.
웹 스토리지는 클라이언트에서 데이터를 저장하는 공간으로, 서버와는 자동으로 데이터를 주고받지 않는다. localStorage는 데이터를 브라우저에 영구적으로 저장하고, sessionStorage는 브라우저 탭을 닫을 때까지만 유지된다. 용량도 크고, 속도도 빠르기 때문에 프론트엔드에서 임시 데이터나 사용자 설정 값을 저장하는 데 자주 쓰인다.
OAuth란 무엇이고 어떤 이유에 의해 필요하게 되었을까요 ?과거에는, 어떤 서비스를 이용하려면 직접 내 계정의 아이디와 비밀번호를 입력해야 했는데.. 보안상 위험하기 때문에
OAuth를 사용해서 비밀번호 없이, 외부 서비스가 일정한 권한만을 가지고 내 계정 정보를 사용할 수 있게 해주는 것이다. 사용자가 외부 앱에 로그인 요청을 하면, 실제 인증은 구글/카카오에게 맡기고, 사용자가 동의하면 access token을 발급해 외부 앱이 그 토큰으로 제한된 정보를 조회할 수 있게 해준다.
🔥 Trouble Shooting
@notblank
Long타입에 @notblank를 써서 400에러가 계속 떴는데 @notblank는 string 타입에만 적용되고 다른 타입에는 @NotNull 또는 @notempty를 써야한다. @NotNull과 @notempty의 차이는 @notempty가 null 뿐만 아니라 비어있는 경우도 허용하지 않는다는 것이다.("" 허용 안함)
따라서,,,
Long에 쓴다면 → @NotNull
List에 쓴다면 → @notempty
String에 쓴다면 → @notblank
토큰 앞뒤에 불필요한 공백 포함 -> trim()을 통해 공백 제거
spring bean validation을 써서 message를 넣어줬음에도 응답 message에는 해당 validation message가 안들어갔었음
NotBlank, @notempty 등 Spring Bean Validation에서 message를 지정해도, GlobalExceptionHandler에서 메시지를 꺼내지 않으면 응답에 포함되지 않는다는 점을 몰랐어서 메시지를 응답에 포함하도록 수정
🤔 고민해본 점
기존에 한개만 선택 가능했던 태그였어서 post 엔티티가 tag도 함께 가지도록 했었는데 최대 두개 선택으로 바뀌면서 엔티티가 수정 필요,..
이때 고민했던 부분은 Post 엔티티 안에 tag1, tag2처럼 두 개의 필드를 따로 둘지, 아니면 Tag 테이블을 따로 만들고 PostTag라는 중간 테이블을 두어 다대다(N:M) 관계로 연결할지를 결정하는 부분이었습니다!
저는 후자를 선택했는데 이유는
예를 들어, "서버" 태그가 포함된 게시글을 조회하는 경우에도 JOIN만으로 효율적인 검색이 가능
2.확장성과 유연성 측면에서 유리.
현재는 최대 두 개지만, 이후 요구사항이 변경되어 무제한으로 늘어나더라도 테이블 구조를 바꿀 필요가 없다고 생각했습니다.
동일한 태그가 여러 게시글에서 중복되더라도 하나의 Tag 레코드를 참조함으로써 데이터 일관성을 유지할 수 있다고 생각했습니다.
좋아요 누르기/취소하기 -> save/delete 방식 선택
좋아요 기능을 구현할 때 여러 가지 방법이 존재했는데, 저는 좋아요를 누르면 Like 객체가 생성되고, 취소하면 삭제되는 방식(save/delete) 으로 구현했습니다.
처음에는 boolean 상태값으로 구현할까도 고민했지만, 이 경우 좋아요를 누른 뒤 취소한 레코드도 계속해서 DB에 남게 되어 데이터가 불필요하게 많이 쌓일 수 있다는 점이 걱정되었습니다. 실제로는 유저가 한 번만 좋아요를 눌렀다가 취소하는 경우도 많기 때문에, 삭제하는 것이 더 깔끔하다고 판단했습니다.
다만 이 방식은 좋아요 누르기와 취소 시마다 insert/delete 쿼리가 발생하기 때문에, boolean 필드를 update하는 방식보다 성능적으로 불리할 수 있다는 우려도 있었습니다. 특히 좋아요/취소가 반복되는 경우엔 write I/O가 더 많아질 수 있습니다.
하지만 현재 서비스 규모에서는 이 방법이 낫다고 생각했고, 좋아요 수를 구할 때도 count 쿼리로 쉽게 처리할 수 있어 실용적이라고 느꼈습니다.
서비스가 커지게 되면 어떤 방식을 많이 사용하고 다른 분들은 어떤 방식을 쓰셨는지 궁금합니다!
@AuthenticationPrincipal 사용
userId를 HTTP 헤더에 직접 넣지 않고 JWT 필터에서 Authentication 객체를 만들고 그 안에 userId를 principal로 설정해서 이후 Spring MVC가 @AuthenticationPrincipal로 등록된 파라미터를 Authentication.getPrincipal()에서 꺼내서 주입하도록 했습니다.
이렇게 할 경우,,
HTTP 요청은 Stateless하기 때문에, 매 요청마다 JWT를 통해 인증 여부를 확인해야하는데 이 과정을 필터에서 수행하고, SecurityContext에 한 번 등록하면,그 뒤에는 Spring이 알아서 @AuthenticationPrincipal에 주입해주기 때문에 컨트롤러에서 인증에 신경을 쓸 필요가 없기 때문에 @AuthenticationPrincipal 를 사용했습니다!
📢 To Reviewers
다들 바쁘신데 시간 내 리뷰해주셔서 감사합니다🙇♀️
📷 Screenshot