본문 바로가기

전체 글89

[Java] 객체 지향 설계 5원칙 - SOLID 원칙 JAVA를 사용한다면 객체지향에 대해서 한 번 쯤은 들어봤을 것이다. (ex. OOP 4대 특징 : 추상화, 상속, 캡슐화, 다형성)이러한 객체지향의 특징을 더 잘 사용하기 위해서 객체지향 설계(OOD) 원칙이 존재한다.그 중 5대 원칙을 나열하여 SOLID 원칙이라고 불리게 되었고 아래에서 이 5가지 원칙을 자세하게 알아보도록 하자.SOLID 원칙은 소프트웨어 설계에 있어 이해하기 쉽고 유연하며, 유지보수 및 확장이 편하다는 장점을 가지게 해준다.1. S (SRP)SRP (Single Reponsibility Principle) : 단일 책임 원칙하나의 클래스 및 메소드는 하나의 책임만 가져야 한다. 수정되어야 하는 이유 및 시기가 다르다면 그 클래스는 단일 책임 원칙이 적용되지 않은 .. 2024. 4. 19.
[리뷰레인저] JWT 토큰에 포함된 유저 정보를 제거하자 - 4 해당 게시글은 프로젝트 '리뷰레인저'에 대해 개인 리팩토링 과정을 정리한 시리즈 글입니다. 이번 게시글의 주제는 'JWT 토큰의 Payload에 포함된 유저 정보로 인한 개인정보 유출 위험에 대한 개선안'입니다. 기존 로직의 문제점 위 사진은 JWT 구조를 설명하고 있다. 이 중 내용(payload)에 집중해서 보면 ‘사용자의 권한 정보’와 ‘사용자 데이터’가 들어있음을 알 수 있다 여기서 중요한 것은 아래 주의 문구를 보자 즉, 페이로드에 중요한 값을 넣어두면 누구든 디코딩을 통해 값을 열람할 수 있기 때문에 민감한 정보는 포함하면 안된다는 내용이다. 그렇다면? 지금 나의 코드는 어떠한 정보를 포함한 JWT 토큰을 생성하고 있는지 확인해보자 UserPrincipal은 Spring Security의 Us.. 2024. 4. 13.
[리뷰레인저] 페이징에 사용되는 Slice 도메인 객체의 노출 범위를 조정하자 - 3 해당 게시글은 프로젝트 '리뷰레인저'에 대해 개인 리팩토링 과정을 정리한 시리즈 글입니다. 이번 게시글의 주제는 '페이징에 사용되는 Slice 객체가 외부에 노출되는 현상에 대한 개선안'입니다. 개요 Slice 객체는 spring.data 패키지에 존재하는 것을 바탕으로 리팩토링을 진행하자! (패키지 범주를 잘 생각해보자) 우리가 왜 controller에서 entity를 노출하지 않는가? 외부에 의해 수정될 위험이 있기때문이다 entity는 domain영역이다. 마찬가지로 slice 객체도 domain영역에 존재한다. 그래서 entity 대신에 우리는 Response라는 객체를 만들어 사용한다 이와 똑같은 맥락으로 생각해보면 된다 Slice 객체의 범주 Controller → Service → Repo.. 2024. 4. 12.
[리뷰레인저] DB에 불필요하게 쌓이는 RefreshToken을 해결하자 - 2 해당 게시글은 프로젝트 '리뷰레인저'에 대해 개인 리팩토링 과정을 정리한 시리즈 글입니다. 이번 게시글의 주제는 '유효한 refreshToken뿐만 아니라 무효한 refreshToken까지 DB에 무의미하게 쌓이는 현상에 대한 개선안'입니다. 기존 로직의 문제점 RefreshToken이 불필요하게 DB에 주기적으로 저장되어 문제가 발생했다 지금은 local에서 테스트 한 환경이지만 refreshToken의 유효시간은 24시간으로 만약 사용자가 많아지고 24시간이 지난다면 이러한 불필요한 만료 토큰 데이터가 계속해서 쌓이게 될 것이다 그리고 위 데이터를 보면 알 수 있다싶이 refreshToken이 `user_id`를 가지고 있어야한다 그렇다면 차라리 user가 refreshToken을 가지고 있다면 어떨.. 2024. 4. 10.
[리뷰레인저] 확장성을 해치는 swtich 분기문을 없애자 - 1 해당 게시글은 프로젝트 '리뷰레인저'에 대해 개인 리팩토링 과정을 정리한 시리즈 글입니다. 이번 게시글의 주제는 'swtich문에 의한 로직의 유지보수성, 확장성이 저하되는 현상에 대한 개선안'입니다. 기존 로직의 문제점들 서비스 로직은 이름과 내부를 봤을 때 어떤 기능을 수행하는지 딱 알 수 있어야 한다 위 사진이 내부와 이름으로 어떤 기능을 수행하는지 바로 알 수 있는 예시이다 `getAllFinalReveiwResults` 메소드는 모든 최종 리뷰 결과를 가져오는 메소드 이름 + 유저id와 상태로 모든 최종 리뷰를 가져오는 기능임이 한번에 보인다. 1) 최종 리뷰를 생성하고 조회하는 로직은 어떤 기능을 수행하는지 알기 힘든 문제 위의 사진이 최종 리뷰를 생성하는 로직이다. 하지만 create라는 이.. 2024. 4. 9.
[Java] Java의 static 키워드는 상속이 불가능한 이유와 Hiding '켄트벡의 구현 패턴' 책을 다시 정독하던 날이었다.. 10장의 내용인 프레임워크 개발 패턴 읽다가 의문이 들어 작성하게 되었다 부모클래스의 static 메소드를 자식클래스에서 오버라이딩(Overriding)하지 못한다는 내용이었다. 즉, 정적 메소드는 오버라이딩 할 수 없다. 이 내용이 왜 그런지에 대한 개념이 제대로 잡혀있지 않는 것 같아 정리하고자 글을 작성한다 Dynamic Method Dispatch = 다이나믹 메소드 디스패치 메소드 디스패치: 어떤 메소드를 실행시킬지 결정하고 실행시키는 과정 Dynamic하므로 컴파일러가 어떤 메소드를 실행시킬지 모르기 때문에 런타임 과정에서 호출할 메소드를 선택하는 것이다. c.f) Static 메소드 디스패치도 있는데 가장 큰 예시론 자바의 main함수가.. 2024. 3. 28.
[Java] 객체지향 생활 체조 원칙 9가지 1. 한 메서드에 오직 한 단계의 들여쓰기만 한다. = 메서드의 깊이는 최대 1 즉, 맡은 일을 작게 가져가라. 깊이가 깊다면 그만큼 맡은 일이 많다(책임이 많다)는 의미이다. 이는 객체지향적이지 못하다는 의미와 같다. 2. else 키워드를 쓰지 않는다. -> 핵심은 `early return` 동시에 1번 규칙인 "깊이 제한은 1"까지 동시에 지키게 된다 문제코드를 한 번 보자 public class JamieObject { String JamieStatus(int hour, boolean isStudy) { String status = ""; if (hour > 4 && hour 4 && hour 정답은 "ㄴㄴ 마찬가지로 문제있음"이다. `early reeturn`의 목적은 "분기를 태우지 않는다"인.. 2024. 3. 9.
Query DSL을 통한 커서기반 페이징 [먼저 페이징에 대한 개념이 부족하시다면 아래의 글을 참고해주면 감사하겠습니다] [Paging] 페이지네이션을 알고 사용하자 해당 게시글은 "프로그래머스 데브코스 4기"의 팀 내 프로젝트 기록용으로 TECH BLOG에 직접 작성한 글입니다. 페이징(Paging, Pagination)이란? 프로젝트를 진행하면서 “베스트 상품 페이징”처리가 bestsu.tistory.com 위의 포스팅은 페이징에 대한 이론을 설명하고 있고 이제 작성 하는 글은 페이징을 실전에 사용하는 방법에 대해 쭉 정리한다 1. query dsl 설정 처음 query dsl을 사용해보면서.. 기본부터 테스트를 진행해야겠다고 하면서 아래 블로그 글을 따라하고 있었다 일단 query dsl 설정 파일을 생성해 주었다. package com... 2024. 3. 7.
[Spring Security] jwt RefreshToken 구현하기 프로젝트를 수행하던 중 access token만으로는 사용자에게 편리한 로그인을 제공하기가 어려움을 느끼게 되었다 가장 크게 느낀 이유론 access token 특성상 지속시간이 짧기 때문에 만료되면 짧은 주기로 이용자가 다시 로그인해야 하는 불편함이 생기는 것이다. 이를 해결하기 위해 refreshToken을 구현해야겠다고 생각하게 되었고 그 과정을 정리해 보았다. refreshToken 전체로직 처음에는 아래와 같은 전체로직으로 구현을 생각하게 되었다 나는 사실 구현하다보니 여러가지 방법이 있는 것을 알게 되었고 굳이 refreshToken을 취약하게 외부에 드러낼 필요가 없다고 생각이 들어서 아래와 같은 로직으로 구현하게 되었다 즉, 만료된 accessToken을 받았을 때 해당 accessToke.. 2024. 1. 29.