OOM(Out Of Memory)이 발생하는 상황을 만들어보자
·
서버 개발(생각과 구현)/서버 생각
OOM(Out Of Memory) 실제로 메모리를 터트려보자 💥들어가며"메모리 관리 잘 해야 해요", "페이징 처리는 필수입니다" - 이런 말들을 수없이 들어왔다. 하지만 솔직히 말하면, 실제로 OOM이 발생하는 걸 직접 경험해본 적은 별로 없었다. 개발 환경은 메모리가 넉넉하고, 테스트 데이터는 항상 소량이니까.그래서 오늘은 의도적으로 메모리를 터트려보기로 했다. 실제 프로덕션 환경에서 발생할 수 있는 다양한 OOM 시나리오를 직접 구현하고, 하나씩 실행해보면서 어떤 일이 벌어지는지 관찰해보았다.⚠️ 주의: 이 글의 모든 코드는 학습 목적입니다. 절대 프로덕션 환경에서 사용하지 마세요!테스트 환경 구축먼저 OOM을 쉽게 재현하기 위해 JVM 힙 메모리를 제한했다.java -Xmx512m -Xms128..
나는 검색도 같이 한다.
·
서버 개발(생각과 구현)/서버 생각
부제: AI는 정답을 알지만, 경험을 알려주지 않는다.안녕하세요, 3년차 주니어 백엔드 개발자입니다. 이 글은 AI가 코드를 생성하고, 버그를 디버깅해주는 2025년에도 불구하고 왜 제가 여전히 검색이라는 고전적인 행위에 먼저 접근하는지에 대한 개인적인 고찰입니다.1. 나의 문제 해결 프로세스저의 업무는 궁금증에서 시작됩니다. "이 새로운 기술 스택을 왜 도입해야 할까?", "운영 환경에서 발생한 이 로그는 정확히 무엇을 의미할까?", "더 효율적인 아키텍처는 없을까?" 이런 질문이 생기면 저는 먼저 문제의 본질을 파악하려 합니다. 문제를 명확히 정의하고, 키워드를 뽑아냅니다. 그리고 바로 이 지점에서, 2025년의 개발자인 저에게는 두 가지 선택지가 주어집니다. AI에게 질문하기 또는 검색 엔진에 입력..
보여지는 시간대(타임존)은 누구의 책임인가
·
서버 개발(생각과 구현)/서버 생각
기본적으로 애플리케이션을 타임존 설정 없이는 시스템에 설정된 기본 타임존을 따라간다. 내용은 아래와 같다.JVM은 시작 시 운영 체제에서 설정된 시스템 타임존을 읽어 들여 초기화한다.예를 들어, Linux, macOS, Windows에서 각각 설정된 타임존 (/etc/localtime 또는 GUI 설정 등)이 JVM의 기본 타임존으로 설정된다.이 값은 JVM의 시스템 속성 user.timezone에 저장된다.기본 시간대코드로 확인해 보자.val defaultTimeZone = TimeZone.getDefault()println("기본 타임존 (TimeZone): ${defaultTimeZone.id}")// java.time.ZoneId를 사용한 기본 타임존 확인val defaultZoneId = Zon..
단일 프로젝트 구조와 멀티 모듈 구조
·
서버 개발(생각과 구현)/서버 생각
처음 개발을 시작하는 단계에서는 보통 단일 프로젝트 구조에서 시작한다. 하지만 그 크기가 증대하고 각각의 역할들이 무수히 많아지면 관리와 복잡도도 매우 증가하게 된다. 그렇기 때문에 이를 해결하고자 나오는 해결책으로 대부분 모듈 구조화를 얘기하곤 한다.문제점은?예를 들어 Member라는 도메인이 존재한다. 단일 프로젝트 구조라면 Member라는 하나의 큰 도메인을 중심으로 여러 개의 서버들이 이에 대해 깊은 의존관계를 띄며 (ex - Internal Service (application serving..), Admin Serving, Exception, Utils..)등 여러 가지가 한 도메인 구조에서 존재하게 된다.⇒ 즉, 여러 개의 IDE를 켜서 하나의 도메인을 바라보는 코드를 수정해서 배포하고 이를..
Custom Swagger를 통해 협업, 업무 효율성 동시에 잡기
·
서버 개발(생각과 구현)/서버 생각
Swagger는 개발한 Rest API를 편리하게 문서화해주고, 이를 통해서 관리 및 제3의 사용자가 편리하게 API를 호출해 보고 테스트할 수 있는 OpenApi에서 만든 양식이다.OpenAPI Specification - Version 3.1.0 | Swagger OpenAPI Specification - Version 3.1.0 | Swagger swagger.io 일반적으로 굉장히 많이 쓰이고 이를 통해 클라이언트, 모바일 개발자 분들과 소통하며 개발을 이어나가곤 한다. 그래서 Swagger는 서버 개발자의 의도를 명확하게 나타내야 한다.이에 따라 각각 서버에서 사용하는 양식들은 굉장히 많다. 대표적으로 REST Docs와 Swagger annotation으로 나타내는 경우가 많다.문제그 중 살펴..
JPA N+1의 의도와 문제 해결
·
서버 개발(생각과 구현)/서버 생각
JPA를 사용하다 보면 N+1 문제를 생각보다 많이 마주치게 된다. 대부분 이는 구글링을 통해 블로그 글이나 레퍼런스로 해결할 수 있는 방법을 알려주고 있다. 하지만 개인적으로 N+1에 대한 문제점이나 원인 혹은 JPA N+1을 의도한 바가 있는지를 면밀히 살펴볼 것이다.JPA N+1 문제대부분의 사람들이 정의하는 N+1이란 아래와 같다.연관관계가 있는 엔티티를 조회할 때 조회된 개수 N개만큼의 쿼리가 추가로 발생하는 것 위와 같이 Team-Member는 1:N 양방향 매핑 관계이다. 이때 N+1이 발생하는 상황은 다음과 같다.Team A, Team B 2개의 Team 엔티티가 존재하는 상황각 팀에 엔티티에 비어있는 멤버가 없다고 가정, 즉 2팀에 모두 멤버가 있는 것.여기서 TeamRepository의..
외부 API와 트랜잭션의 관계를 조심하자
·
서버 개발(생각과 구현)/서버 생각
Spring을 활용하여 트랜잭션을 관리하다 보면 @Transaction Annotation을 사용하게 된다.그런데 만약 해당 Annotation이 적용된 로직에서 외부 API Call이 있다면 어떻게 될까?롤백가장 먼저 고민이 드는 부분이 롤백이다.만약 중간에 Exception이 발생하여 rollback이 되었다고 외부 호출은 rollback 될까?@Transactionalfun test() { testRepository.save(Test().apply { name = "test" }) apiCallClient.testCall() throw RuntimeException()}@Serviceclass ApiCallClient { private val restClient = RestCl..
락의 필요성과 실제 사용을 위한 분산 락, 낙관적 락, 비관적 락 탐구
·
서버 개발(생각과 구현)/서버 생각
보통 서버 개발을 하다 보면 자주 마주치는 단어들이 존재한다. 동시성, 정합성 등… 특정 동시성 상황에서 데이터 정합성을 보장할 때 특히 락들을 활용하는 타이밍이 자주 온다. 그래서 크게 자주 사용되는 락들을 알아보고 어떻게 동작하는지 어떤 상황에 적합한지를 예제를 통해 알아볼 것이다.1. 락이 필요한 이유예를 살펴보자.알리익스프레스 같은 쇼핑 어플의 월간 사용자수는 약 4억 명정도이다. 그 이유는 가격이 저렴한 것도 있지만, 추가적인 할인을 해주는 쿠폰을 나눠주기도 한다. 이 쿠폰까지 사용하면 어느 쇼핑몰보다 저렴하게 상품을 구매할 수 있다. 그러나 쿠폰 재고 소진으로 쿠폰을 못 받을 수 있다. 여기서 생각을 해보면, 쿠폰 이벤트를 시작할 때 동시에 수많은 사용자가 쿠폰 발행을 할 텐데 쿠폰 잔여 개수..
서킷 브레이커(CircuitBreaker)가 필요한 경우
·
서버 개발(생각과 구현)/서버 생각
만약 특정 서버에서 장애가 발생했을 때, 해당 장애가 전파되고 여러 서비스에 영향을 끼친다면 어떻게 할까? 이럴 때 사용하는 것이 서킷 브레이커(CircuitBreaker)이다.서킷 브레이커란?단순한 개념은 다음과 같다.서킷 브레이커는 문제가 발생할 경우 서비스의 호출을 차단하고 fallback 메서드를 이용할 수 있도록 하는 패턴으로 서비스 호출이 실패하거나 지정된 임계값을 초과할 때, 서킷 브레이커는 OPEN 상태가 되어 후속 호출을 차단하고, 시스템이 회복될 때까지 대기한다. 서킷 브레이커의 상태는 3가지로 분류 된다. (이미지 출처)닫힘(Closed) 상태:서킷 브레이커는 기본적으로 닫힌 상태에서 시작.(정상 상태)실패율이 정해진 값을 초과하면 서킷 브레이커는 OPEN 상태로 전환된다.열림(Ope..
Spring Retry(재시도)가 필요한 경우
·
서버 개발(생각과 구현)/서버 생각
Spring Retry란실패할 경우 그 동작을 자동으로 다시 호출하는 기능이 담긴 라이브러리로, Spring Retry 라이브러리를 통해 사용한다. 간단하게 예를 들어, 특정 비즈니스 로직에서 실패 후 재시도 처리가 필요한 경우가 존재한다. 특정 A라는 로직이 실패한 경우 재시도하는 경우가 될 것이다. 이는 비즈니스 요구 사항에 따라 사용되기도 하며 일시적인 에러가 발생했을 때 재시도 메커니즘을 활용하기도 한다.Guide to Spring Retry | Baeldung Guide to Spring Retry | BaeldungA quick and practical guide to implementing retry logic with Spring Retrywww.baeldung.com Spring Retr..