목록개발Article (143)
밤빵's 개발일지

현재 프로젝트에서 JWT 기반 인증을 구현하면서 로그아웃 처리 방식에 대한 고민이 있었다. JWT는 기본적으로 stateless한 인증 방식이다. 서버가 클라이언트의 상태를 기억하지 않는 것이 원칙이지만, 클라이언트에서만 로그아웃을 처리하는 방식이 사용자 경험 측면에서 불완전할 수 있다는 의견이 있었다. 그래서 백엔드 서버에도 로그아웃 기능을 구현하기로 결정했다. 1. JWT 로그아웃 처리JWT는 클라이언트가 자체적으로 보관하는 Self-contained Token으로, 로그아웃을 처리할 때 몇 가지 고민이 있었다.토큰 삭제 불가능: JWT는 발급 후 서버에 저장되지 않기 때문에, 특정 토큰을 삭제하거나 무효화 할 수 없다.발급된 토큰의 유효기간 문제: 로그아웃 시에도 기존 토큰은 만료 시간이 남아 있는..

외부 API를 사용하는 프로젝트를 개발하면서 안정성에 대한 고민을 하게됐다. PUBG 데이터를 제공받는 샤드 기반 클래스들에서 예외 처리를 진행했지만, 예상하지 못한 외부 API의 장애나 네트워크 문제로 인해 시스템 전체가 영향을 받을 가능성을 발견했고, 그 문제를 해결하기 위해 서킷 브레이커패턴을 도입할지 고민하게 되었다. 1. 서킷 브레이커란?서킷 브레이커는 외부 API 호출 시 발생할 수 있는 장애로부터 시스템을 보호하는 디자인 패턴이다. 정상 상태에서는 API 요청을 그대로 처리하지만, 일정 비율 이상의 요청 실패나 타임아웃이 발생하면 회로를 열어 더 이상 요청을 보내지 않는다. 일정 시간이 지나고 나면 테스트를 위해 회로를 반쯤 열어 요청을 일부 허용하고, 성공 여부에 따라 회로를 닫는 과정을 ..

프로젝트를 할 때 마다 enum을 사용하고 있지만, 왜 사용하는지 명확히 이해하지 못한 채 일단 편리하다? 상수를 나열한다?는 이유로 쓰고 있는 것 같다. 이번 개발일지에서는 enum의 개념과 그 필요성, 어떻게 활용할 수 있는지에 대해 구체적으로 정리하고싶었다. enumenum은 열거형이라는 의미로, 상수들의 집합을 정의할 수 있는 특수한 데이터 타입이다. Java에서 enum은 클래스처럼 보이지만, 특정 값들을 제한하여 사용할 수 있도록 하는 기능을 제공한다. 요일, 달, 상태(state)와 같이 제한된 값들만 허용해야 할 경우에 사용하면 유용하다.public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}→ ..

equals()와 hashCode() 이 두 메서드는 객체의 동등성을 비교하고, 해시 기반 컬렉션에서 올바르게 동작하기 위해 중요한 역할을 한다. 이번 개발일지에서는 equals()와 hashCode()의 기본 개념, 그리고 왜 재정의해야 하는지와 그 결과로 얻는 이점에 대해 학습한 내용을 정리했다. equals()와 hashCode()란?equals(): 두 객체가 논리적으로 같은지를 비교하는 메서드이다. 기본적으로 Object 클래스에 정의되어 있고, 동일한 객체 참조를 가리키는지(메모리 주소가 같은지) 비교한다. 하지만 대부분의 경우 객체의 속성 값을 기준으로 논리적인 동등성을 판단해야 하기때문에 재정의가 필요하다.hashCode(): 객체를 해시 테이블과 같은 자료구조에 사용할 때 객체를 고유하..

Spring의 Event Publisher는 애플리케이션에서 이벤트를 비동기적으로 처리할 수 있도록 도와주는 기능으로, 시스템의 결합도를 낮추고, 유연한 확장성을 가능하게 해준다. 이번 개발일지에서는 Event Publisher에 대해 처음 접한 초보 개발자로써 이 개념을 이해하고 적용했다. Event PublisherEvent Publisher는 특정 이벤트가 발생했을 때 이를 다른 객체에게 알리는 역할을 한다. 이벤트를 발생시키는 쪽과 처리하는 쪽을 느슨하게 연결해서, 서로의 존재를 알지 못해도 상호작용이 가능하게 한다. 이런 점은 대규모 애플리케이션에서 모듈 간의 결합도를 낮추고 유지보수성을 높이는 데 큰 장점을 제공한다. 예를 들어, 회원 가입 시 이메일 알림을 보내야 한다고 가정했을 때, 일반..

프로젝트를 진행하면서 DTO와 Entity 간의 변환 방식에 대해 고민하게 되었다. 변환의 필요성은 크게 두 가지로 첫째, Entity는 데이터베이스와 직접 연관된 구조이기 때문에 외부 API 응답으로 적합하지 않다. 둘째, DTO를 이용해 비즈니스 로직의 변화에 유연하게 대처하자 였다. 다양한 변환 방식이 존재하는데, 각각의 장단점을 비교해보며 개발 일지로 정리하기로 했다. 1. of, from 정적 메서드 패턴of, from 같은 정적 팩토리 메서드를 활용해 변환을 구현하는 방식은, 코드의 가독성을 높이고 변환 로직을 명확히 정의할 수 있다.public class UserDto { private String name; private String email; public static U..

이번 클랜플레이어 기능 구현에서 TDD 를 먼저 적용해봤다. 테스트 코드를 먼저 작성하고 그 테스트를 통과하는 방향으로 구현을 진행하고싶었다. 기능 자체는 간단했기에, 테스트를 작성한 후 기능을 호다닥 구현할 수 있었다. 테스트가 명확한 방향을 제공해 주었기에 기능을 구현하는 데 있어 큰 어려움이 없었다! (기능 구현 보다 테스트 코드 작성하는게 더 어렵다. 잘 안해봤던거라 그런가....?) 먼저, ClanPlayersService의 주요 기능인 플레이어의 랭크 통계와 라이프타임 통계를 가져오는 메서드를 테스트하기 위한 테스트 케이스들을 정의했다. Mockito를 사용하여 OpenRankedStatsService, OpenLifetimeStatsService, PlayersRepository, Ranke..

프로젝트에 Redis를 도입한다고 한다. 레디스는 데이터의 빠른 액세스를 가능하게 하는 인메모리 데이터 저장소로 알려져 있고, 데이터 캐싱, 세션 관리, 간단한 키-값 저장소로 많이 사용된다. 지금까지 레디스를 적용해본적이 없고, 본격적인 도입에 앞서 학습이 필요했기때문에, 기능구현을 빨리 끝마치고 레디스 적용을 위한 학습과 코드를 작성해본 걸 기록하게 됐다...!! 1. 레디스 도입 목적과 학습 시작레디스를 도입하려는 이유는 캐싱을 통한 응답 속도 개선과 자주 사용되는 데이터의 빠른 접근을 목적으로 한다. 특히, PUBG와 관련된 데이터들이 빈번히 호출되기 때문에, 일부 데이터를 캐싱하여 성능을 최적화 할 수 있다.레디스는 키-값 구조를 가지고, 데이터는 메모리에 저장되기 때문에 데이터 액세스 속도가..

디미터의 법칙이란 객체 지향 설계에서 결합도를 낮추고, 유지보수성을 높이는 중요한 원칙이다. 객체 간의 관계를 제한함으로써 복잡성을 줄이고, 응집도를 높이는 것을 목표로 하는 이 법칙을 이해하고, 이를 실제 코드에 어떻게 적용할 수 있을지 고민하면서 학습한 내용을 정리하기로 했다. ▶디미터의 법칙디미터의 법칙은 객체 지향 설계에서 캡슐화와 정보 은닉을 잘 지키도록 돕는 원칙이다. "친구하고만 대화하라"( 객체는 자신이 직접 참조하고 있는 객체와만 상호작용하고, 다른 객체의 내부 구조를 알지 않도록 설계해야한다는 의미)는 규칙을 통해 객체 간의 의존성을 줄이고, 각 객체가 자신의 역할에 충실하도록 설계할 수 있다. 결합도를 낮추고, 코드의 유연성을 높이는 것을 목표로 한다. 객체 간의 의존성을 줄임으로써..

프로젝트 작업 중 발생한 @Value 애노테이션 충돌 문제를 해결하기 위해 @PostConstruct를 사용했다. 실무에서도 종종 발생한다고 하는 Spring 어노테이션간의 충돌과 설정초기화의 순서 문제로, 이 과정을 통해 Spring 애노테이션 간의 충돌 문제와 초기화 순서에 따른 문제를 어떻게 해결했는지에 대해 기록하기로했다.▶문제 상황처음 프로젝트에서는 JwtUtil 클래스에서 @Value 애노테이션을 사용해 JWT 서명 키를 설정하려고 했다. 하지만, 같은 프로젝트 내의 다른 클래스에서도 @Value 애노테이션을 사용하여 PUBG API 키를 설정하고 있었기 때문에 충돌이 발생했다. 충돌의 원인은 Spring 컨텍스트에서 빈이 생성되는 시점에 값이 주입되는 Spring 라이프사이클의 문제였다. ..