Today I Learned
-
[QueryDSL] Entity 쿼리 로직의 데이터베이스 접근 횟수를 최소화해 리소스 생성 동작 성능 개선하기Today I Learned 2023. 6. 23. 01:50
최종보스 프로젝트를 진행하면서 코드를 구현하는 데 가장 많은 시간을 써야 했고, 가장 마지막까지 방치했던 부분은 목록과 관련된 리소스를 반환하는 로직이었다. 하나의 리소스를 조합하는 데 여러 Entity들이 필요한 동작이 있었다. 경기 목록이나 검색 결과와 같은 리소스를 반환하는 식의 동작들이었는데, 본 글에서는 검색 결과 리소스를 구성하는 예시를 살펴보려 한다. 기존에는 경기 목록을 구성하는 리소스 하나를 생성하기 위해 다음의 Entity들이 필요했다. - Post 하나 - Place 하나 - Post, Place와 연결된 Game 하나 - Game과 연결된 Register 여러 개 경기에 참가하는 사용자를 키워드로 경기 목록을 검색하는 Service는 다음과 같은 로직으로 작성되어 있었다. 비록 Po..
-
[Spring] ApplicationEventPublisher를 활용해 Event 기반 동작 구현하기Today I Learned 2023. 6. 20. 12:36
이벤트(Event)란? 프로그래밍에서 이벤트란, 애플리케이션 내에서 발생시킬 수 있는 어떠한 사건을 의미한다. 애플리케이션에는 어떠한 이벤트를 발생시키는 주체와, 정해진 이벤트의 발생을 탐지해 동작을 처리하는 주체가 존재할 수 있다. 애플리케이션을 개발하는 과정에서 발생하는 문제들 중, 어떤 문제들을 이벤트 개념을 적용해 해결할 수 있을까? 특정 동작을 수행하는 과정에서 그 동작과는 개별적으로 추가적으로 수행해야 하는 외적인 동작이 존재할 경우, 그 외적인 동작을 처리하기 위한 이벤트를 발생시키고, 발생한 이벤트를 처리하는 로직에서 필요한 동작을 수행하게 할 수 있다. 경기를 생성했을 때, 경기 생성에 대한 알림을 같이 생성하는 경우를 생각해보자. 가장 간단하게 생각해볼 수 있는 구현 방식은 Game을 ..
-
[Java][JPA] 추상 클래스 개념을 적용해 알림 객체 설계 개선하기Today I Learned 2023. 6. 17. 18:36
로버트 C. 마틴이 언급한 객체지향 설계를 위한 5대 원칙 중 하나로 개방-폐쇄 원칙(Open-closed Principle)이 있다. '소프트웨어의 구성 요소는 확장에는 열려 있고, 변경에는 닫혀 있어야 한다'는 원칙으로, 간단히 이야기하자면 소프트웨어의 특정 모듈의 기능이 추가되어야 할 경우, 기존에 작성한 코드를 가급적 변경하지 않으면서 기능을 추가할 수 있어야 한다는 것이다. 기존 프로젝트의 알림 구조 프로젝트 애플리케이션에는 '알림'과 관련된 기능들과 Entity들이 존재했다. 특정 기능들을 수행했을 때 (이를테면 어떤 경기에 참가신청했다던가, 참가신청이 작성자에 의해 수락되었다던가와 같은 것들) 그와 관련된 정보를 담은 Notice 객체를 생성해 저장하는 부가적인 기능이었다. 본래 알림 기능을..
-
[Java] Reflection API란 무엇인가?Today I Learned 2023. 5. 27. 17:36
private 메서드를 클래스 외부에서 억지로 호출할 수 있다고? 이펙티브 자바에서 싱글턴을 다루는 부분을 살펴보다가 다음의 내용이 눈에 들어왔다. 권한이 있는 클라이언트는 리플렉션 API인 AccessibleObject.setAccessible을 사용해 private 생성자를 호출할 수 있다. private으로 선언한 메서드를 어떻게 호출할 수 있는 것인지 싶어 ChatGPT의 도움을 받아 통해 간단한 예시를 작성해보았다. 예시에 사용할 객체를 살펴보자. 단 하나의 인스턴스만 존재함을 보장하기 위해 전역에서 해당 객체의 인스턴스에 직접 접근할 수 있도록 public static으로 인스턴스를 정의한 뒤, 맨 처음에 생성된 뒤로는 불변 상태를 유지하도록 final 예약어를 부여했다. 그리고 해당 객체는 ..
-
소스코드에 주석은 어느 정도로 활용되어야 할까?Today I Learned 2023. 5. 26. 03:38
(해당 글은 저서 'Docs for Developers'를 참고하여 작성했으나, 다소 주관적인 견해를 담고 있습니다. 다른 견해가 있으실 경우 자유롭게 제안해주시면 감사하겠습니다.) 시간이 지나면 나조차도 내 코드를 이해하기 어렵게 된다. 프로젝트를 진행하면서 가졌었던 생각 중 하나로, 주석을 아예 작성하지 않고 단지 코드를 읽는 것만으로도 이해할 수 있는 소스코드를 작성할 수 있어야 한다는 생각이 있었다. 이를 위해 코드를 작성할 때 줄곧 다음과 같은 것들을 고려했었다. - 축약어를 사용하지 않는다. ex) a, b, i, idx, cnt, ... - 변수, 메서드 등을 네이밍할 때는 의미를 최대한 나타낸다. 이 규칙들을 지킨다고 해서 항상 읽기 좋은 코드가 만들어지지는 않았다. '의미를 최대한 나타내..
-
[Java] testcontainers를 활용해 통합 테스트 수행하기Today I Learned 2023. 5. 20. 03:57
통합 테스트란 무엇인가? 일반적으로 코드를 작성하는 과정에서 가장 빠르게 작성할 수 있는 테스트는 단위 테스트이다. 기능을 구성하는 가장 작은 식이나 메서드 단위에서부터 빠르게 테스트를 작성하고 검증할 수 있기 때문이다. 그러나 단위 테스트만으로 전체적인 동작이 올바르게 이루어지는지 검증하기에는 부족할 수 있다. 이를테면 서버와 데이터베이스가 상호작용해 수행하는 기능에 대해 서버 범위 내에서만 동작을 검증할 경우에는, 실제로 동작이 실행되었을 때 서버 범위 바깥의 모듈과 상호작용하는 과정을 포함해서 모든 영역에서 문제 없이 완전하게 수행할 것이라고 확신하기는 쉽지 않을 것이다. 그래서 특정 기능에 관여하는 둘 이상의 모듈들을 함께 동작시켰을 때 요구되는 동작을 정상적으로 수행하는지 검증하는 방식으로도 테..
-
[Java] interface 활용하기: 함수형 인터페이스, Comparator<E> 구현체를 이용해 List 정렬하기Today I Learned 2023. 5. 16. 16:13
interface의 구현체를 정의해 특정한 로직에 활용하는 방식을 좀 더 적극적으로 활용해보자. List를 원하는 기준에 맞추어 정렬해야 하는 상황이 생겼다고 한다면, 어떻게 할 수 있을까? Java의 List interface에는 다음과 같이 정렬을 위한 default 메서드 sort()가 존재한다. 다음의 코드를 살펴보자. // List.java @SuppressWarnings({"unchecked", "rawtypes"}) default void sort(Comparator
-
Java에서 interface와 구현체 class들을 이용해 소스코드의 중복 제거하기Today I Learned 2023. 5. 12. 03:46
... 구체적으로는 내가 구상한 방식을 따를 때 코드의 중복을 최소화할 수 있는 방안을 마련할 수 있어야 했는데 이를 고려할 시간이 부족했고, 결국 코드의 중복이 상당 부분 존재하는 상태로 코어 로직을 구현하게 되었다. (2023년 5월 1주차 주간회고 중) 이 소스코드의 중복이 도저히 눈 뜨고 넘어갈 수준이 아니었다. 마감까지 남은 시간이 굉장히 촉박한 상태에서 코어 로직을 구현한 관계로 구현 과정에서 무거운 기술 부채를 쌓게 되었다. 어떤 문제가 발생했는지 살펴보면서 이를 조금씩 개선해나가는 것을 시도해보자. 상황 살펴보기 특정 강의에 수강신청한 학생들의 수강신청 상태를 정해진 우선순위 기준들을 바탕으로 성공 상태로 변화시키거나, 실패 상태로 변화시키는 프로세스를 구현해야 하는 상황을 가정해보자. 우..