분류 전체보기 44

[클러버] Spring Logging 전략 수립하기

https://minjun98.tistory.com/133 [클러버] 운영을 위한 초기 인프라 구축 과정실제 운영을 위해 인프라를 구성하였다. 프리티어 EC2 인스턴스 하나로 운영 예정인 작은 사이드 프로젝트이긴 하지만, 장애가 발생하였을 때 대처할 수 있는 시스템을 구축하는 것 자체가 의미minjun98.tistory.com 앞선 블로그 글에서 언급했듯이, 실제 운영 상의 문제 발생 시 빠르게 원인을 파악하고 대응하기 위해 적절한 로깅 전략을 수립하여 사용자들의 요청 및 응답 정보를 통일된 형식으로 상세히 기록하는 것의 필요성을 느꼈다. 목차는 다음과 같다. 1. 로깅 포맷 구성 2. 로깅 위치3. 비동기 작업 로깅4. 로깅 구현 방법(요청, 응답 캐싱) 1. 로깅 포맷 구성@Builderpublic..

클러버 2025.04.24

[클러버] @Builder을 활용한 Fixture 셋업 개선

이 글에서는 Spring Boot 테스트 코드에서 Given 절의 Fixture 셋업에서 겪은 고민을 다룬다.기존 방식1. 구현별도의 ServiceTest라는 클래스 파일에서 하나의 @BeforeEach 작업을 통해 모든 테스트 코드의 Fixture을 셋업하고 있었다. Native Query를 활용하여 1. Fixture 객체 생성 2. DB 저장 작업까지 수행한다. Given절에서 반복되는 작업을 하나의 함수에서 담당하게 하기 위함이었다. 2. 문제1) 현재 테스트 함수에서 어떤 데이터가 셋업되었는지 명시적으로 알 수 없다. 테스트 함수에서 바로 확인할 수 있는 것이 아니라, 매번 셋업 함수(@BeforeEach)에서 어떤 데이터가 셋업되었는 지 확인해봐야 한다. 2) 테스트 함수를 독립적으로 수행하..

클러버 2025.03.17

[클러버] Java Enum을 활용한 프로젝트 개선기 (3)

https://minjun98.tistory.com/108 에 포함하여 작성하게 되었습니다. 감사합니다 [클러버] Java Enum을 활용한 프로젝트 개선기 (1)문제 상황 현재 진행하고 있는 클러버(clubber) 프로젝트에서는 카테고리 값들이 많은데, 이러한 값들을 별도의 테이블로 분리해서 관리를 해야할지 고민이 많았다. 대표적인 항목으로는 다음과minjun98.tistory.com

클러버 2025.02.13

[클러버] 운영을 위한 초기 인프라 구축 과정

실제 운영을 위해 인프라를 구성하였다. 프리티어 EC2 인스턴스 하나로 운영 예정인 작은 사이드 프로젝트이긴 하지만, 장애가 발생하였을 때 대처할 수 있는 시스템을 구축하는 것 자체가 의미있는 경험이라고 생각하고 있다.  [로그, 모니터링 시스템] 1. Promatil , Loki , Grafana 기존에는 Spring Boot에서 발생한 로그를 도커 볼륨을 이용해서 EC2에 저장하고, 해당 파일들을 조회했다. 일일히 파일 열고, vi로 에러 로그를 검색하는 것 자체에 대한 불편함이 계속 있었던 거 같다. 이를 해결하기 위해 PLG 스택을 위한 로그 수집기 & 모니터링 시스템을 구축하였다. vs ELK ELK 스택의 경우 질의가 훨씬 정교하지만, 현재 EC2의 리소스 상황으로는 운영되긴 힘든 무게였다. ..

클러버 2025.02.12

[Docker] host.docker.internal

host.docker.internal이란? host.docker.internal은 Docker 컨테이너가 호스트 머신(컨테이너를 실행하는 실제 컴퓨터) 에 접근할 수 있게 해주는 호스트 이름이다. 왜 필요한가?Docker 컨테이너는 기본적으로 격리된 네트워크 환경에서 동작한다.하지만 가끔 컨테이너 내부에서 호스트 머신에 있는 서비스(예: DB, API 서버)에 접근해야 할 때가 있다. vs localHost컨테이너 내부의 localhost는 자기 자신을 가리킨다. 컨테이너의 관점에서, Ec2와 같은 호스트 머신을 의미하는 것이 아니다.  예시 아래 예시의 서비스들은 모두 컨테이너로 배포되었다고 가정한다. Prometheus & Spring Actuator Prometheus 컨테이너에서는 같은 호스트이지..

Docker 2025.02.04

5.4 MySQL의 격리 수준

트랜잭션 격리 수준이란? 여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지를 결정하는 것 READ UNCOMITTED(Dirty Read 발생)은 일반적인 데이터베이스에서 사용하지 않는다. SERIALIZABLE은 동시성이 중요한 데이터베이스에서 거의 사용되지 않는다. SERIALIZABLE 격리 수준이 아니라면 크게 성능의 개선이나 저하는 발생하지 않는다. REPEATABLE READ 격리수준에서 PHANTOM READ는 Inno DB 한정해서 발생하지 않는다.  READ UNCOMMITED 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다. 해당 예시에서 사용자 A가 Inse..

Real MySQL 2024.08.15

[JPA] Fetch join과 pagination

문제상황현재 프로젝트에서는 모집글(Recruit)와 모집글에 들어갈 이미지(RecruitImage)가 1대다의 관계로 존재하며 양방향 매핑이 되어있는 상황이다. N + 1문제를 방지하고자 둘을 fetch join하여 가져오려고 하였다.  위의 쿼리를 실행하였더니 다음과 같은 경고 메시지가 발생하였다.  HHH000104: firstResult/maxResults specified with collection fetch; applying in memory! 사실 페이징하려는 대상이 join 이후에 컬럼을 페이징하는 것이 아니라 모집글을 대상으로 하여 페이징을 처리를 하고 다의 관계에 있는 모집글 이미지를 양방향 매핑 조회 객체를 통해 끌어오기 위함이기 때문에, 결과 자체는 원하는 대로 반환이 되었다.  하..

JPA 2024.08.12

[클러버] Java Enum을 활용한 프로젝트 개선기 (2)

지난번엔 클러버 프로젝트에서의 동아리 리뷰 작성 시 고정된 키워드, 동아리의 소속 분과 등과 같이 값이 변경될 일이 거의 없는 값들의 모음들을 별도의 테이블이 아니라 Enum을 활용해 관리하는 방법에 대해 포스팅을 했다. https://minjun98.tistory.com/108 [java] Java Enum 활용 프로젝트 개선기 (1)문제 상황 현재 진행하고 있는 프로젝트에서는 변경되지 않는 값들의 모음이 많은데, 이러한 값들을 별도의 테이블로 분리해서 관리를 해야할 지 고민이 많았다. 대표적인 항목으로는 다음과minjun98.tistory.com 이번에는 프로젝트의 Enum 항목들 중 둘 사이의 포함관계를 가지고 있는 값들을 어떻게 구성하고 관리했는 지에 대해 얘기해보고자 한다.  문제 상황 프로젝트..

클러버 2024.07.07

[클러버] Java Enum을 활용한 프로젝트 개선기 (1)

문제 상황 현재 진행하고 있는 클러버(clubber) 프로젝트에서는 카테고리 값들이 많은데, 이러한 값들을 별도의 테이블로 분리해서 관리를 해야할지 고민이 많았다. 대표적인 항목으로는 다음과 같다. - 중앙 동아리 분과 (교양분과, 연행예술분과 등 7개) - 소모임 소속 학과 및 단과대 (학과 약 20개 , 단과대 약 8개)- 동아리 리뷰 키워드 항목 5개 (회비가 적당, 커리어에 도움 등 5개) - 동아리 분류 해시 태그 (개발, 요리, 시사 등 약 10개) 리팩토링 이전에는 프론트엔드와 백엔드 간의 요청, 응답은 문자열로 주고 받았고 (ex: 해시태그가 요리인 동아리 조회) 별도의 테이블로 저장하지 않았기 때문에 프런트엔드에서 문자열로 하드코딩해서 넘겨주기로 했다. 코드 테이블 (DB) 별도의 ..

클러버 2024.07.07

[java] enum 클래스에서의 @AllArgsConstructor

enum에서의 생성자를 사용하기 위해 lombok의 @AllArgsConstructor을 함께 사용하는 경우가 많다. 프로젝트에서 생성자의 접근제어자를 최대한 좁게 설정하는 중에 enum에서도 @AllArgsConstructor를 생성한 기억이 났다. 근데 문제는  1. enum은 package-private, private 생성자를 허용한다. (아니면 아예 컴파일 에러가 난다.) 2. @AllArgsConstructor의 기본 접근 제어자는 이 둘이 아니라 public이다.  나는 따로 accesslevel을 private, package-private 하게 설정을 안해줬는데 왜 컴파일이 되지?라는 생각을 했다. 그래서 컴파일된 파일을 보니까 값을 따로 지정 안해줬는데 생성자가 private하게 생성되..

java 2024.06.27