JMX와 VisualVM으로 remote 환경에 있는 앱 성능 분석

목표 stage 환경에서 Spring 애플리케이션이 컨테이너로 실행되고 있다. 해당 애플리케이션의 특정 API의 응답 속도가 늦어져서 원인을 파악한다. JMX JMX: JVM 애플리케이션을 관리하고 모니터링하기 위해 제공되는 API JMX 아키텍처 JMX는 3개의 계층으로 구성되어 있다. Instrumentation layer: 애플리케이션에서 관리하고자 하는 자원을 표현하는 MBean 객체를 관리 JVM에서 기본적으로 제공하는 MBean들이 있음 ThreadMXBean: 스레드 수, 스레드별 CPU 시간, 스레드들의 stack trace 정보 등을 제공 MemoryMXBean: 메모리 사용량 제공 JMX agent layer: MBeanServer 존재 MBean 객체들을 등록, 괸리하고 이를 접근할 수 있도록 인터페이스 제공 Remote management layer: JConsole, VisualVM 같은 툴을 가리키는 클라이언트 영역 VisualVM JVM 애플리케이션을 모니터링 하기 위한 툴 jstatd, JMX 등의 방식으로 JVM 애플리케이션과 통신해서 여러 메트릭 정보 확인 가능 Remote 환경의 컨테이너를 VisualVM으로 모니터링 하기 VisualVM을 JVM 애플리케이션과 JMX 연결하여 모니터링 할 수 있다....

2025-06-17 · 2 min · 354 words

5-트랜잭션과 잠금

트랜잭션은 작업의 완전성을 보장해준다. 잠금(Lock)은 트랜잭션과 비슷한 개념 같지만 동시성을 제어하기 위한 기능이다. 반면, 트랜잭션은 데이터의 정합성을 보장한다. 트랜잭션 MySQL에서의 트랜잭션 트랜잭션은 꼭 여러 개의 변경 작업을 수행하는 쿼리가 조합됐을 때만 의미 있는 개념은 아니다. 아래의 예를 본다. SLECT * FROM tab_innodb 트랜잭션을 지원하지 않는다면 1, 2가 부분 저장되고 3만 저장되지 않지만, 트랜잭션이 지원되기 때문에 1, 2, 3 모두 롤백이 되었다. 트랜잭션이 지원되는 않는 코드 부분 업데이트가 발생해서 쓰레기 데이터가 남을 수 있기 때문에, 복잡한 분기처리를 해줘야된다....

2025-06-12 · 9 min · 1705 words

4-유스케이스 구현하기

육각형 아키텍처는 도메인 중심의 아키텍처에 적합하다. 유스케이스 둘러보기 일반적으로 유스케이스는 다음과 같은 단계를 따른다. 입력을 받는다. 입력 유효성 검증은 다른 곳에서 처리한다. (유스케이스 코드가 도메인 로직에만 신경 써야하고 입력 유효성 검증으로 오염되면 안되기 떄문) 비즈니스 규칙을 검증한다. 도메인 엔티티와 유스케이스가 책임을 공유한다. 모델 상태를 조작한다. 영속성 어댑터를 통해 구현된 포트로 변경된 상태를 전달해서 저장될 수 있게 한다. 출력을 반환한다. 입력 유효성 검증 입력 유효성 검증은 입력 모델의 생성자 내에서 이루어진다....

2025-06-12 · 2 min · 391 words

3-카프카 프로듀서: 카프카에게 메시지 쓰기

프로듀서 개요 카프카에 메시지를 써야 하는 상황에 따라 요구사항이 다양하다. 메시지 유실이 용납되지 않는지 중복이 허용되도 상관없는지 반드시 지켜야할 지연이나 처리율이 있는지 이처럼 서로 다른 요구 조건은 카프카에 메시지를 쓰기 위해 프로듀서 API를 사용하는 방식과 설정에 영향을 미친다. 프로듀서 메시지 전송 과정 ProducerRecord 객체를 생성한다. 여기서는 레코드가 저장될 토픽과 밸류는 필수사항이지만, 키와 파티션 지정은 선택사항이다. ProducerRecord를 전송하는 API를 호출했을 때, 키와 값 객체가 네트워크 상에 전송될 수 있도록 직렬화해서 바이트 배열로 변환한다....

2025-06-12 · 12 min · 2400 words

15-실패와 지연 처리하기

서킷 브레이커 이해하기 서킷 브레이커 패턴은 우리가 작성한 코드가 실행에 실패하는 경우에 안전하게 처리되도록 해준다. 마이크로서비스의 경우, 한 마이크로서비스의 실패가 다른 마이크로서비스의 연쇄적인 실패로 확산되는 것을 방지해야 하기 때문에 더 중요하다. 서킷 브레이커는 메서드의 호출을 허용하며, 서킷은 닫힘 상태에서 시작된다. 어떤 이유로 실패하면, 서킷 브레이커가 개방되고 실패한 메서드에 더 이상 호출이 수행되지 않는다. 대신 폴백을 제공하여 자체적으로 실패를 처리한다. 개방 상태의 서킷이 때때로 절반-열림 상태로 바뀌면서 실패했던 메서드의 호출을 서킷 브레이커가 다시 시도한다....

2025-06-12 · 4 min · 681 words

11-쿼리 작성 및 최적화

쿼리 작성과 연관된 시스템 변수 SQL 모드 MySQL 서버의 sql_mode 라는 시스템 설정에는 여러 개의 값이 동시에 설정될 수 있다. sql_mode를 설정할 때는 구분자(,)를 이용해 키워드를 동시에 여러 개 설정할 수 있다. MySQL 서버의 sql_mode 시스템 변수에 설정된 값들은 SQL 문장 작성 규칙뿐만 아니라 MySQL 서버 내부적으로 자동 실행되는 데이터 타입 변환 및 기본값 제어 등과 관련된 옵션도 가지고 있다. 그래서 일단 MySQL 서버에 사용자 테이블을 생성하고 데이터를 저장하기 시작했담녀 가능한 한 sql_mode 시스템 변수의 내용은 변경하지 않는 것이 좋다....

2025-06-12 · 34 min · 7184 words

8-프로파일링한 데이터에 고급 시각화 도구 적용하기

JDBC 접속 문제 감지 쿼리를 보내려는 앱이 DB에 커넥션을 맺을 때부터 문제가 생길때 원인 파악을 프로파일러로 할 수 있다. 호출 그래프를 보고 앱의 코드 설계 파악 언젠가 코드를 정확히 분석하게 되겠지만, 호출 그래프를 활용하면 어떤 일이 일어나느지 미리 신속하게 개괄할 수 있다. 플레임 그래프를 그려 성능 문제 밝히기 호출 그래프가 객체와 메서드 호출 간의 관계에 집중한다면, 플레임 그래프는 잠재적인 레이턴시를 발견하는 데 가장 유용하다. NoSQL DB에서의 쿼리 분석

2025-05-26 · 1 min · 68 words

8-인덱스

디스크 읽기 방식 하드 디스크 드라이브(HDD)와 솔리드 스테이트 드라이브(SSD) 데이터베이스 서버에서는 항상 디스크 장치가 병목이 된다. 이러한 기계식 하드 디스크 드라이브를 대체하기 위해 전자식 저장 매체인 SSD가 많이 출시되고 있다. 디스크의 헤더를 움직이지 않고 한 번에 많은 데이터를 읽는 순차I/O에서는 SSD가 하드 디스크 드라이브보다 조금 빠르거나 거의 비슷한 성능을 보이고 있다. SSD의 장점은 기존 하드 디스크 드라이브보다 랜덤 I/IO가 훨씬 바르다. 랜덤 I/O와 순차 I/O 디스크의 성능은 디스크 헤더의 위치 이동 없이 얼마나 많은 데이터를 한 번에 기록하느냐에 의해 결정된다....

2025-05-26 · 17 min · 3485 words

Bean Validation 꼼꼼하게 사용하기

목표 복잡한 구조의 클래스의 bean validation 적용 방법을 이해한다. nested child object의 검증 방법 Java bean validation은 기본적으로 검증하고자 하는 클래스에도 @Valid 어노테이션을 붙여줘야된다. @Valid 어노테이션은 field나 getter에 붙여줄 수 있다. data class Project( @field:NotBlank(message = "Project title must be present") @Size(min = 3, max = 20, message = "Project title size not valid") private val title: String, @field:Valid private val owner: User, ) data class User( @field:NotBlank(message = "User name must be present") @field:Size(min = 3, max = 50, message = "User name size not valid") private val name: String, @field:NotBlank(message = "User email must be present") @field:Email(message = "User email format is incorrect") private val email: String, ) 이유 Java bean validation이 nested child object 를 자동으로 스캔해서 검증해준다면, @Valid 어노테이션을 매번 직접 명시하지 않아도 되어서 편리할 것이라고 생각할 수 있다....

2025-05-20 · 2 min · 300 words

5-로그를 활용하여 앱 동작 감시하기

로그 메시지는 스트링일 뿐이라서 이론적으로는 어떤 문장이라도 남길 수 있지만, 깔끔하고 사용하고 편한 로그를 남기려면 앞으로 이 장에서 설명한 몇 가지 베스트 프랙티스를 따르는 것이 좋다. 개발자가 문제를 조사할 때는 무엇보다 로그를 가장 먼저 확인해야 한다. 로그를 보면 이상한 동작이 바로 보이기 때문에 어디서부터 조사를 시작해야 할지 정확하게 진단할 수 있기 때문이다. 로그가 모든 질문에 정답을 제공하는 것은 아니지만, 출발점을 찾아내는 일은 매우 중요하다. 로그를 이용하여 조사하기 로그는 과거 특정 기간의 앱 실행에 초점을 맞춘다....

2025-05-13 · 4 min · 715 words

4-원격 앱 디버깅

원격 디버깅이란? 앱을 개발할 때에는 적어도 세 가지 환경을 사용한다. 개발 환경(development environment, DEV): 앱을 배포할 환경과 유사한 환경이다. 개발자는 주로 로컬 시스템에서 개발을 진행하고 이 환경에서 새로운 기능과 수정 사항을 테스트한다. 사용자 인수 테스트 환경(user acceptance test, UAT): 개발 환경에서 테스트를 마친 앱은 사용자 인수 테스트 환경에 설치된다. 사용자는 새로운 구현체와 수정된 코드를 시험하고, 실체 데이터가 있는 프로덕션 환경에 앱을 배포하기 전에 정상 작동하는지 확인한다. 프로덕션 환경(production environment, PROD): 새로운 구현체가 예상대로 잘 작동되고 사용상 문제가 없다면 프로덕션 환경에 앱을 설치한다....

2025-05-13 · 2 min · 399 words

MMM(Multi-Master Replication Manager)

목표 MMM이 무엇인지 이해한다. MMM의 동작 과정을 이해한다. MMM MMM은 MySQL에서 failover 및 모니터링을 수행해주는 스크립트다. MMM 구조 monitor-agent 통신 방식 monitor: MMM 내에 있는 DB 노드들을 모니터링하고 관리한다. agent: MMM 내의 DB 노드들에 설치해서 monitor에 의해 관리된다. agent는 monitor에 의해 읽기, 쓰기 모드가 관리된다. 기본 구성 2개의 마스터가 존재한다. active master: read, write 가능 standby master: read만 가능 active master와 standby master가 양방향 복제된다. slave 추가 구조 active master로부터 단방향 복제된다....

2025-05-12 · 2 min · 231 words

3-고급 디버깅 기법으로 문제의 근본 원인 찾기

조건부 브레이크포인트로 조사 시간 최소화 조건부 브레이크포인트: 특정한 조건을 만족할 경우에만 코드 라인에서 앱 실행을 중단시키는 방법이다. 조건부 브레이크포인트를 잘 활용하면 조사하려는 특정한 케이스를 찾아 헤매지 않고 소중한 시간을 절약할 수 있다. 단점: 조건부 브레이크포인트는 스코프에 있는 변숫값을 디버거가 지속적으로 가로채서 브레이크포인트 조건을 평가해야 하므로 실행 성능에 상당히 큰 영향을 미친다. 조건부 브레이크포인트의 또 다른 용도는 여러 가지 표현식 값 또는 특정 조건에 대한 스택 트레이스 등의 세부 정보를 기록하는 것이다....

2025-05-12 · 2 min · 331 words

1-카프카 시작하기

데이터의 모든 부분은 의미가 있으며, 그 다음 처리되어야 하는 작업과 같이 뭔가 중요한 정보를 담고 있다. 이것이 무엇인지 알기 위해서는 데이터를 생성된 곳에서 분석할 수 있는 곳으로 옮겨야 한다. 데이터를 옮기는 작업을 빠르게 해낼 수록 조직은 더 유연해지고 더 민첩해질 수 있다. 우리가 데이터를 이동시키는 작업에 더 적은 노력을 들일수록 핵심 비즈니스에 더욱 집중할 수 있다. 발행/구독 메시지 전달 발행/구독 메시지 전달 패턴의 특징은 전송자가 데이터를 보낼 때 직접 수신자로 보내지 않는다는 것이다....

2025-05-04 · 7 min · 1444 words

2-디버깅 기법으로 앱 로직 이해하기

코드 분석만으로는 불충분한 경우 코드 읽는 법이 시 읽는 법과 다른 점 코드는 선형적이지 않다. 코드는 한 라인 한 라인 그냥 읽는 대상이 아니다. 시와 달리 코드는 항상 모든 사람에게 동일한 의미를 지닌다. 아무리 작은 코드 조각이라도 커맨드를 더 자세히 들여다봐야 할 때가 많다. 어떤 커맨드는 조사를 생략해서 전체 프로세스를 단순하게 가져갈지, 아니면 프로세스가 더 복잡해지더라도 자세히 살펴보고 개별 커맨드를 확실하게 이해할지 선택해야 한다. 디버거를 이용한 코드 조사 디버거를 사용하면 조사 프로세스가 간소화된다....

2025-04-28 · 2 min · 387 words

1-앱에서 모호한 부분 밝히기

디버깅은 원래 ‘문제를 찾고 해결하는 것’이라는 뜻이지만, 개발자는 코드의 작동 방식을 분석하는 다양한 목적으로 디버깅을 수행한다. 새로운 프레임워크 배우기 문제의 근본 원인 찾기 기본 로직을 이해하여 새로운 기능으로 확장하기 앱을 더 쉽게 이해하는 방법 코드 조사: 소프트웨어 기능의 특정한 동작을 분석하는 프로세스 ‘소프트웨어 에러를 찾아 고치는’ 디버깅이라는 용어를 혼용해서 사용하고 있다. 코드 조사를 하는 이유 어떤 문제를 찾아낸다. 어떤 소프트웨어의 기능이 어떻게 작동되는지 알아야 개선할 수 있다. 어떤 기술 또는 라이브러리를 학습한다....

2025-04-10 · 3 min · 535 words

16-트랜잭션과 락, 2차 캐시

트랜잭션과 락 트랜잭션과 격리 수준 트랜잭션 특성 원자성: 트랜잭션 내에 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하든가 모두 실패해야 한다. 일관성: 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다. 격리성: 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. 지속성: 트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되어야 한다. 트랜잭션은 원자성, 일관성, 지속성을 보장한다. 문제는 격리성인데 트랜잭션 간에 격리성을 완벽히 보장하려면 트랜잭션을 거의 차례대로 실행해야 한다. 이렇게하면 동시성 처리 성능이 매우 나빠진다....

2025-03-19 · 6 min · 1249 words

Kotlin Couroutine 기본 개념

목표 코루틴의 기본 개념을 이해한다. 코투린을 사용하기 위한 기본 kotlin 문법을 이해한다. 코루틴 특정 코드 블럭을 다른 커드와 동시에 실행한다는 점에서 스레드와 비슷하다. 하지만 코루틴은 특정 스레드에 바인딩되지 않는다. 한 스레드에서 실행을 일시 중지했다가 다른 스레드에서 다시 시작할 수 있다. 스레드를 사용하면 메모리를 많이 소모하게되지만, 코루틴은 JVM에서 사용 가능한 메모리 제한에 부딪히지 않고 표현할 수 있다. fun main() = runBlocking { // this: CoroutineScope launch { // launch a new coroutine and continue delay(1000L) // non-blocking delay for 1 second (default time unit is ms) println("World!...

2025-03-18 · 2 min · 397 words

Spring Boot Applicatoin Event 와 애플리케이션 시작 과정

배경 SpringApplicationEvent 에서 Spring 프레임워크가 애플리케이션에 관련된 이벤트를 발행하는 것을 이해할 수 있었다. Spring Boot에서 어떤 이벤트를 전송하고 있는지 이해한다. 이벤트 목록 애플리케이션 실행 시 아래 순서대로 이벤트가 발생한다. ApplicatoinStartingEvent: 애플리케이션 실행 이전에 발생한다. ApplicationContextInitializer 들과 ApplicationListener 들의 등록을 제외한 모든 처리 이전에 발생한다. ApplicationContextInitializer: ApplicationContext가 초기화되기 전에 실행되어야 하는 로직이 있을 때 정의하는 콜백 인터페이스 ApplicationListener: 애플리케이션에서 발생하는 이벤트를 감지하고 처리하는 역할의 인터페이스 ApplicationEnvironmentPreparedEvent: Environment가 준비 되었지만, ApplicationContext가 생성되기 전에 발생한다....

2025-03-17 · 2 min · 250 words

3-이론

소프트웨어 설계는 인간관계 속에서 벌어지는 활동 팀원끼리 견해 차이가 있을 때는, 이론적인 틀을 공유하는 것이 유용하다. 원칙에 동의하지 않더라도 서로의 원칙에 대해 논의할 수 있다면 더 빨리 합의할 수 있는 기회가 생긴다. 요소들을 유익하게 관계 맺는 일 소프트웨어 설계의 의미: 요소들을 유익하게 관계 맺는 일 요소: 경계가 있고 계층 구조를 선호한다. 관계: 요소들은 서로 관계를 가진다. 함수 호출 발행(publish) 대기(listen) 참조 유익하게: 기계를 위한 명령어가 아닌, 일종의 중간 요소들이 서로 도움이 되도록 예) 함수 A는 함수 B가 계산의 복잡한 부분을 덜어간다....

2025-03-16 · 2 min · 241 words