목록전체 글 (198)
밤빵's 개발일지
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/HBuQc/btsLbPebP0q/iGuwa8HmNQUlqKcwlK0811/img.webp)
현재 프로젝트에서 JWT 기반 인증을 구현하면서 로그아웃 처리 방식에 대한 고민이 있었다. JWT는 기본적으로 stateless한 인증 방식이다. 서버가 클라이언트의 상태를 기억하지 않는 것이 원칙이지만, 클라이언트에서만 로그아웃을 처리하는 방식이 사용자 경험 측면에서 불완전할 수 있다는 의견이 있었다. 그래서 백엔드 서버에도 로그아웃 기능을 구현하기로 결정했다. 1. JWT 로그아웃 처리JWT는 클라이언트가 자체적으로 보관하는 Self-contained Token으로, 로그아웃을 처리할 때 몇 가지 고민이 있었다.토큰 삭제 불가능: JWT는 발급 후 서버에 저장되지 않기 때문에, 특정 토큰을 삭제하거나 무효화 할 수 없다.발급된 토큰의 유효기간 문제: 로그아웃 시에도 기존 토큰은 만료 시간이 남아 있는..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/bB6hkm/btsLamkdaKE/AmXkiizDLR8MREK2ZUMweK/img.webp)
외부 API를 사용하는 프로젝트를 개발하면서 안정성에 대한 고민을 하게됐다. PUBG 데이터를 제공받는 샤드 기반 클래스들에서 예외 처리를 진행했지만, 예상하지 못한 외부 API의 장애나 네트워크 문제로 인해 시스템 전체가 영향을 받을 가능성을 발견했고, 그 문제를 해결하기 위해 서킷 브레이커패턴을 도입할지 고민하게 되었다. 1. 서킷 브레이커란?서킷 브레이커는 외부 API 호출 시 발생할 수 있는 장애로부터 시스템을 보호하는 디자인 패턴이다. 정상 상태에서는 API 요청을 그대로 처리하지만, 일정 비율 이상의 요청 실패나 타임아웃이 발생하면 회로를 열어 더 이상 요청을 보내지 않는다. 일정 시간이 지나고 나면 테스트를 위해 회로를 반쯤 열어 요청을 일부 허용하고, 성공 여부에 따라 회로를 닫는 과정을 ..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/dLQFO9/btsLbx5oc45/GkGTOzv8JRcxAE2cvJQTg0/img.webp)
프로젝트를 할 때 마다 enum을 사용하고 있지만, 왜 사용하는지 명확히 이해하지 못한 채 일단 편리하다? 상수를 나열한다?는 이유로 쓰고 있는 것 같다. 이번 개발일지에서는 enum의 개념과 그 필요성, 어떻게 활용할 수 있는지에 대해 구체적으로 정리하고싶었다. enumenum은 열거형이라는 의미로, 상수들의 집합을 정의할 수 있는 특수한 데이터 타입이다. Java에서 enum은 클래스처럼 보이지만, 특정 값들을 제한하여 사용할 수 있도록 하는 기능을 제공한다. 요일, 달, 상태(state)와 같이 제한된 값들만 허용해야 할 경우에 사용하면 유용하다.public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}→ ..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/cAOdXI/btsK9mwkeeD/tjsWUn1pUp0rV2bugwPX9k/img.webp)
equals()와 hashCode() 이 두 메서드는 객체의 동등성을 비교하고, 해시 기반 컬렉션에서 올바르게 동작하기 위해 중요한 역할을 한다. 이번 개발일지에서는 equals()와 hashCode()의 기본 개념, 그리고 왜 재정의해야 하는지와 그 결과로 얻는 이점에 대해 학습한 내용을 정리했다. equals()와 hashCode()란?equals(): 두 객체가 논리적으로 같은지를 비교하는 메서드이다. 기본적으로 Object 클래스에 정의되어 있고, 동일한 객체 참조를 가리키는지(메모리 주소가 같은지) 비교한다. 하지만 대부분의 경우 객체의 속성 값을 기준으로 논리적인 동등성을 판단해야 하기때문에 재정의가 필요하다.hashCode(): 객체를 해시 테이블과 같은 자료구조에 사용할 때 객체를 고유하..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/ljtK9/btsK8GAZkqx/LFUoYpU1WGn84SiJocMFu0/img.webp)
Spring의 Event Publisher는 애플리케이션에서 이벤트를 비동기적으로 처리할 수 있도록 도와주는 기능으로, 시스템의 결합도를 낮추고, 유연한 확장성을 가능하게 해준다. 이번 개발일지에서는 Event Publisher에 대해 처음 접한 초보 개발자로써 이 개념을 이해하고 적용했다. Event PublisherEvent Publisher는 특정 이벤트가 발생했을 때 이를 다른 객체에게 알리는 역할을 한다. 이벤트를 발생시키는 쪽과 처리하는 쪽을 느슨하게 연결해서, 서로의 존재를 알지 못해도 상호작용이 가능하게 한다. 이런 점은 대규모 애플리케이션에서 모듈 간의 결합도를 낮추고 유지보수성을 높이는 데 큰 장점을 제공한다. 예를 들어, 회원 가입 시 이메일 알림을 보내야 한다고 가정했을 때, 일반..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/TTZcj/btsK47Al9Fx/vYH2pky4cJyOKz8FZewfDk/img.webp)
프로젝트를 진행하면서 DTO와 Entity 간의 변환 방식에 대해 고민하게 되었다. 변환의 필요성은 크게 두 가지로 첫째, Entity는 데이터베이스와 직접 연관된 구조이기 때문에 외부 API 응답으로 적합하지 않다. 둘째, DTO를 이용해 비즈니스 로직의 변화에 유연하게 대처하자 였다. 다양한 변환 방식이 존재하는데, 각각의 장단점을 비교해보며 개발 일지로 정리하기로 했다. 1. of, from 정적 메서드 패턴of, from 같은 정적 팩토리 메서드를 활용해 변환을 구현하는 방식은, 코드의 가독성을 높이고 변환 로직을 명확히 정의할 수 있다.public class UserDto { private String name; private String email; public static U..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/dfhdJ1/btsK5ugH2yQ/oJQvtjqz8zxP1QDDLcJjNk/img.webp)
3주차 과제도 시작하기 전 여러 고민이 있었다. 코틀린의 문법에 익숙하지 않으니까 클래스 구조나 예외 처리 방법에 대해 어떻게 접근해야 할지 고민했고, 자바와는 다른 코틀린의 data class나 companion object 같은 개념들을 이론만 알지 적용하는건 어려웠다. 그리고 예외 상황을 어떻게 깔끔하게 처리할지에 대한 고민까지.... 과제를 해결하기 위해 코틀린 공식 문서를 참고하고, 여러 예제 코드를 살펴보면서 문법에 대한 이해를 넓혀 나갔다. 초기에는 간단한 기능부터 구현해 보며 자신감을 쌓고, 이후 단계적으로 복잡한 로직을 추가해 나가면서 문제를 해결할 수 있었다....! 과제 요구사항 분석이번 과제는 사용자가 로또 구입 금액을 입력하고, 로또를 구매하며, 당첨 번호를 입력받아 당첨 통계를 ..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/cODMv4/btsK4gWYMAQ/EWGhkRxNJt7Hqes2ql1Ko1/img.webp)
이번 클랜플레이어 기능 구현에서 TDD 를 먼저 적용해봤다. 테스트 코드를 먼저 작성하고 그 테스트를 통과하는 방향으로 구현을 진행하고싶었다. 기능 자체는 간단했기에, 테스트를 작성한 후 기능을 호다닥 구현할 수 있었다. 테스트가 명확한 방향을 제공해 주었기에 기능을 구현하는 데 있어 큰 어려움이 없었다! (기능 구현 보다 테스트 코드 작성하는게 더 어렵다. 잘 안해봤던거라 그런가....?) 먼저, ClanPlayersService의 주요 기능인 플레이어의 랭크 통계와 라이프타임 통계를 가져오는 메서드를 테스트하기 위한 테스트 케이스들을 정의했다. Mockito를 사용하여 OpenRankedStatsService, OpenLifetimeStatsService, PlayersRepository, Ranke..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/qFjWe/btsK4hOPd8u/96CKuEITnrKqc6hKsAcRb0/img.webp)
프로젝트에 Redis를 도입한다고 한다. 레디스는 데이터의 빠른 액세스를 가능하게 하는 인메모리 데이터 저장소로 알려져 있고, 데이터 캐싱, 세션 관리, 간단한 키-값 저장소로 많이 사용된다. 지금까지 레디스를 적용해본적이 없고, 본격적인 도입에 앞서 학습이 필요했기때문에, 기능구현을 빨리 끝마치고 레디스 적용을 위한 학습과 코드를 작성해본 걸 기록하게 됐다...!! 1. 레디스 도입 목적과 학습 시작레디스를 도입하려는 이유는 캐싱을 통한 응답 속도 개선과 자주 사용되는 데이터의 빠른 접근을 목적으로 한다. 특히, PUBG와 관련된 데이터들이 빈번히 호출되기 때문에, 일부 데이터를 캐싱하여 성능을 최적화 할 수 있다.레디스는 키-값 구조를 가지고, 데이터는 메모리에 저장되기 때문에 데이터 액세스 속도가..
![](http://i1.daumcdn.net/thumb/C150x150.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/G3jaT/btsK1yZvUMD/BA2xh3xXCLvpIkAOB8YGP0/img.webp)
코틀린은 자바와 유사한 객체지향 언어로, 클래스와 객체를 사용하여 프로그램을 구조화할 수 있다. 그리고 자바보다 더 간결하고 이해하기 쉬운 방식으로 클래스를 정의할 수 있다. 클래스 선언코틀린에서 클래스는 class 키워드를 사용하여 선언한다. 클래스는 속성과 메서드를 가질 수 있고, 객체를 정의하고 동작을 부여할 수 있다. class Car { var brand: String = "" var speed: Int = 0 fun drive() { println("$brand is driving at $speed km/h") }}→ Car 클래스는 brand와 speed라는 두 개의 속성을 가지고 있으며, drive()라는 메서드를 통해 자동차가 주행 중이라는 메시지를 출력..