전체 글 90

TestContainers로 MySQL + Redis 통합 테스트

이번 글에서는 CommentClosureQueryAdapter 통합 테스트와 PostCacheSyncAdapter 테스트를 TestContainers 기반으로 통합 테스트 환경으로 바꾸면서 겪은 삽질과 해결 과정을 정리해보겠습니다.1. 시작: 댓글 테스트에서 MySQL만 사용처음에는 댓글 테스트에서 MySQL 컨테이너만 사용했습니다.@Containerstatic MySQLContainer mysql = new MySQLContainer("mysql:8.0") .withDatabaseName("testdb") .withUsername("test") .withPassword("test");@DynamicPropertySourcestatic void dynamicPrope..

개발 2025.09.05

비밀로그 백엔드

소개깃허브 : https://github.com/BimilLog/BimilLog_main 백엔드폴더 프론트팀원 생길시 (향후 레포 분리)프레임워크 : springboot 3.4.4언어 : java21디비 : mysql 8.0, Redis데이터 관리 : querydsl, jpa외부 연동 : fcm, kakao실시간 알림 : sseCI/CD : 깃허브액션아키텍처 : 헥사고날서버 6개백엔드 서버프론트 서버RDS배스천호스트nat인스턴스로드밸런서그 외aws 람다현재모놀리식 -> 헥사고날 전환완료 테스트코드 작성, 로직 리팩토링 중목표테라폼연동 aws코드화웹소켓 카프카이용 실시간 채팅 구축기존 알림도메인를 분리 sse fcm 그리고 실시간 채팅에서 기타 모든 알림을 다루는 알림서버를 구축그리고 카프카를 도입하여 채..

개발 2025.08.22

[그래프] 코딩테스트에서 어떤문제에 어떤 알고리즘을 써야할까??

이 글은 각 알고리즘의 자세한 구현 방법에 초점을 맞추고 있지 않습니다.실전에서 어떤 문제에 어떤 알고리즘을 써야하는지를 빠르게 파악하는데 초점을 맞추고 있습니다. 실전에서는 문제에 어떤 알고리즘을 써야하는지 알려주지 않습니다.때문에 어떤 알고리즘을 써야하는지 빠르게 파악하고 불 필요한 혼란을 겪지 않는 것이 시간압박을 피하는 최고의 방법입니다. 크게 두 가지의 섹션으로 나누었습니다.1. 그래프에서 자주 쓰이는 알고리즘의 종류와 특징을 살펴본다.2. 각 알고리즘을 어떤 문제에 써야하는지 알아보겠습니다. 1. 그래프에서 자주 쓰이는 알고리즘의 종류와 특징을 살펴보겠습니다 1. BFS (넓이 우선 탐색) : 한 정점에서 다른 모든 정점까지의 최단거리를 계산하는 알고리즘특징 : 자신 주변의 노드부터 차례차례..

알고리즘 2025.08.18

데몬 스레드

스레드는 크게 2가지로 나눌 수 있다. 1. 사용자 스레드2. 데몬 스레드 사용자 스레드는 우리가 보통 생각하는 스레드이고 비즈니스 로직을 처리하는 바로 그 스레드 이다. 프로그램의 주요 작업을 수행하며 작업이 완료될 때 까지 실행된다. 모든 사용자 스레드가 종료되면 JVM도 종료된다. 데몬 스레드는 백그라운드에서 보조적인 작업을 수행한다. 모든 사용자 스레드가 종료되면 데몬 스레드는 자동으로 종료된다. JVM은 데몬 스레드의 실행 완료를 기다리지 않고 종료된다. 데몬 스레드가 아닌 모든 스레드가 종료되면, 자바 프로그램도 종료된다. 자바 프로그램이 끝난다는 거는 사용자 스레드가 종료되는 시점이다. 스레드의 종료란 각 스레드의 스택이 모두 빠져나가고 하나도 남지 않는 시점이다.

자바 2025.08.17

자바 메모리구조

메서드 영역 : 프로그램을 실행하는데 필요한 공통 데이터 관리. 이 영역은 프로그램의 모든영역에서 공유- 클래스 정보 : 클래스의 실행 코드 (바이트 코드), 필드 메서드와 생성자 코드등- static 영역 : static 변수 보관- 런타임 상수 풀 : 프로그램을 실행하는데 필요한 공통 리터럴 상수 보관 스택 영역 : 자바 실행 시, 하나의 실행 스택 생성. 각 스택 프레임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등 포함- 스택 프레임 : 스택 영역에 쌓이는 네모 박스가 하나의 스택 프레임. 메서드를 호출할 때 마다 하나의 스택 프레임이 쌓이고 메서드가 종료되면 해당 스택 프레임이 제거 됨 힙 영역 : 객체와 배열이 생성되는 영역. 가비지 컬렉션이 이루어지는 주요 영역 더 이상 참조되지 않는..

자바 2025.08.17

DTO와 의존성, 계층의 분리에 대한 고민

모놀리식아키텍처는 컨트롤러 비즈니스 레포지터리의 계층을 나누고 계층간의 이동은 DTO로 변환해서 관리한다.이것은 엔티티는 영속성에 종속되어있고 이것을 계층간에 전달하게 되면 강한결합을 유발하기 때문이다. 순수한 비즈니스로직을 영속성에 오염시킬 수 있고 보안 문제의 예방도 있다. 종합하자면 단일원칙책임을 준수하기위해서 DTO를 활용한다고 볼 수 있다.하지만 헥사고날아키텍처에서는 외부세계 (어댑터)밖으로 나가기 직전에 DTO로 변환시키고 그 이전엔 엔티티를 활용한다.이것은 도메인 모델과 영속성 분리의 완벽한 분리를 추구하기 때문이다. 엔티티는 JPA나 외부기술의 영향을 받지않는 가장 순수한 계층이다. 헥사고날에서의 DTO는 도메인과 외부 세계를 연결하는 계약의 역할을 한다.이때! 엔티티는 가장 순수하다고 했..

비밀로그 프론트엔드 팀원 모셔요!

함께 성장할 프론트엔드 팀원 한 분을 찾습니다! 안녕하세요, 익명 롤링페이퍼 서비스 '비밀로그'에서 프론트엔드 개발을 함께할 팀원을 모집합니다. 저는 백엔드 개발을 담당하고 있고 개인 프로젝트 였습니다. 현재 V2 개발을 진행 중입니다.이 프로젝트는 취업을 준비하면서 실질적인 프론트엔드 개발 경험을 쌓고 싶은 분에게 큰 도움이 될 것입니다. 실제 사용자가 있는 서비스를 함께 만들어가면서 포트폴리오에 담을 수 있는 의미 있는 성과를 만들어낼 수 있습니다.비밀로그는 어떤 서비스인가요?서비스: 익명 롤링페이퍼 서비스 '비밀로그'사이트: https://grow-farm.com/기술 스택:Frontend: Next.js (TypeScript)Backend: Java (Spring Boot)Deployment: A..

개발 2025.08.14

헥사고날 아키텍처 리팩토링 (1)

배경소셜 로그인 흐름을 정리하는 과정에서 도메인 경계와 책임 배치가 뒤섞여 있었다. 인증 서비스가 사용자 도메인의 내부 포트를 직접 참조하고, DTO에서 쿠키를 만들거나, FCM 토큰 이벤트가 중간 계층에서 발행되는 등 응집도가 낮았다. 목표는 기능 안정성을 유지하면서 아키텍처 원칙을 지키고, 책임을 올바른 계층으로 되돌리는 것이었다.상황인증 서비스가 사용자 도메인의 인바운드 포트를 직접 호출해 계층 의존 방향이 어긋남.쿠키 생성이 DTO 내부에서도 이뤄져 책임이 분산됨.블랙리스트 확인 위치와 시점이 일관되지 않음.로그인의 결과를 담은 DTO에서 “기존/신규” 분기 정보가 빠지며 흐름 제어가 모호해짐.임시 데이터 저장 포트의 메서드 시그니처가 구현/호출부와 어긋나 빌드 오류 발생.인증 데이터 저장 포트의..

개발 2025.08.12

모놀리식 -> 헥사고날 전환 도메인 경계 문제 해결

문제발생비밀로그 프로젝트를 헥사고날 아키텍처로 정리하는 과정에서 가장 먼저 눈에 들어온 문제는 도메인 경계의 침범이었다. 회원가입과 로그인 흐름을 담당하는 auth 도메인의 AuthDataAdapter가 알림 도메인의 구현체인 FcmTokenRepository와 FcmToken 엔티티를 직접 사용하고 있었고, 이로 인해 FCM 토큰의 저장과 삭제까지 auth가 떠맡고 있었다. 더 나아가 포트 설계도 이 결합을 부추겼다. ManageAuthDataPort가 본래 인증 데이터만 다뤄야 함에도 String fcmToken을 파라미터로 받으며 책임이 섞여 있었다. 심지어 JWT에도 fcmTokenId를 클레임으로 넣고, JwtFilter에서 이를 꺼내 재발급에 사용하면서 인증과 알림이 구조적으로 강결합된 상태였..

헥사고날 아키텍처

포트 - 벽에 달린 콘센트 즉 '표준 규격'이다 규격이란 인터페이스 일 뿐 스스로 아무런 일도 하지 않는다.도메인 - 드라이기의 모터처럼 실제 '일'을한다어댑터 - 플러그 또는 가전제품 본체 외부 기술을 뜻한다 포트라는 표준 규격에 맞게 제작되어 도메인에 전기를 전달해준다. in-어댑터 : Driving Adapter - 주도하는 어댑터외부의 요청을 받아 애플리케이션을 주도(Drive)하고 도메인이 이해할 수 있는 형태로 바꿔 in-port(UseCase) 를 호출한다예시로 : 컨트롤러가 있다 - HTTP 요청을 받아 JSON 데이터를 DTO객체로 변환한뒤 도메인 로직을 실행한다.두번째 예시는 메시지 큐 리스너다 - 메시지를 받아서 도메인이 이해할 수 있는 명령으로 바꿔 UseCase를 호출한다. ou..

아키텍처 2025.08.12