쿠버네티스에서 MySQL dump 하기 (uuid 필드를 사용할 때)
·
Kubernetes
이번 포스팅은 네이버 클라우드(NKS)에서 구글 클라우드(GCP)로 마이그레이션을 하며 MySQL dump를 수행했을 때 일어났던 문제를 다룹니다.문제 상황MySQL 덤프한 파일로 import 수행 시 아래와 같이 `ERROR 1062 (23000)` 에러가 발생했는데요,ERROR 1062 (23000) at line 347: Duplicate entry '\xEF\xBF\xBB\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF' for key 'letter.PRIMARY'command terminated with exit code 1PK에 중복된 값이 있어서 실패했음을 알 수 있습니다.원인PK 필드를 UUID로 사용했는데, 타입을 BINARY(16)로 사용했습..
프로젝트 리팩토링 (5) - HTTP 요청 비동기 처리
·
Project
이번 포스팅에서는 여러 번 반복되는 HTTP 요청을 비동기로 처리해 응답 속도를 단축시키는 과정을 담았습니다.문제이전 포스팅 마지막에서 다뤘던 문제는 반복문 안에서 HTTP 요청을 보내는 것이었습니다. 기존 코드public void preCreateDailyReport(UUID userId, LocalDate startDate, LocalDate endDate) { // 편지 서비스에게 `분석 가능한 편지들` 찾기 위임 List analyzableLetters = letterService.findAnalyzableLettersInRange(userId, startDate, endDate); for (DailyLetters dailyLetters : analyzableLetters) { ..
프로젝트 리팩토링 (4) - 책임 재할당과 트랜잭션에서 외부 API 분리하기
·
Project
이전 포스팅에서는 객체들의 책임이 올바르게 할당되지 않았던 문제를 다뤘습니다.그러다 보니 거대한 몬스터 메서드들이 생겨났고, 이로 인해 유지보수와 확장이 어려웠었죠. 이 문제를 해소하기 위해 책임의 재할당을 다뤘었는데요, 이번 포스팅에서도 객체 지향 관점에서 책임의 재할당을 다룹니다.책임의 재할당 과정에서 트랜잭션에서 외부 API 호출 로직을 분리하고, 데이터 주도 협력 관계에서 책임 주도 협력 관계로 나아가는 과정을 담았습니다.의미 있는 타입으로 묶기이전 포스팅에서 책임 재할당의 결과왼쪽은 `편지 서비스`가 해야 할 책임이 `데일리 리포트 서비스`에 있었던 부분입니다. (코드 20줄)오른쪽은 `편지 서비스`에게 책임을 재할당하고, 해당 서비스에게 요청을 보내는 부분으로 개선된 코드입니다. (코드 1줄)..
프로젝트 리팩토링 (3) - 책임 재할당과 실행 계획 분석으로 검증하기
·
Project
문제 상황간략한 위클리 리포트 서비스 소개위클리 리포트 서비스는 이름대로 한 주 동안 유저가 작성한 편지(또는 일기)에 대한 분석을 제공합니다.서비스 정책 안에서 왕성히 활동한 유저의 7일 치 글을 모두 합치면 최대 16만 글자가 넘을 수 있습니다. 현실적으로 16만 글자를 생성형 AI에게 전달하는 것은 비용 문제와 서비스 품질 문제로 이어질 수 있기 때문에 `데일리 리포트`를 이용하는데요, `데일리 리포트`에 하루치가 요약되어 있는 내용을 이용해 `위클리 리포트`를 생성합니다.서비스 정책 간략 소개`위클리 리포트`는 절대적으로 `데일리 리포트`에 의존하기 때문에 반드시 `데일리 리포트`가 존재해야 합니다.위의 의존성 문제 때문에 우리 서비스의 정책은 유저가 한 주간 편지를 작성만 하고 `데일리 리포트`..
프로젝트 리팩토링 (2) - 도메인 모델 리팩토링
·
Project
이번 포스팅은 올려 올려 라디오 프로젝트의 도메인 모델 개선에 대해 다룹니다.현재 도메인 모델의 문제점을 짚어보고, 더 나은 도메인 모델을 제시하면서 그 근거를 정리하겠습니다. 시작하기 앞서, 프로젝트 리팩토링 과정을 잘 이해하기 위해 우리 프로젝트가 어떻게 동작하는지 간단하게 짚고 넘어가겠습니다.프로젝트 동작 구조답장 서비스 동작 구조위 그림은 우리 프로젝트의 첫 번째 MVP인 `답장 서비스`가 동작하는 구조입니다.유저가 `편지`를 써서 전달하면 생성형 AI가 `답장`을 생성해 응답합니다.우리 프로젝트는 유저가 작성한 `편지`와 `답장`을 각각 별개의 엔티티로 관리합니다.두 엔티티 간 관계는 1:1 관계를 갖고 있습니다. 데일리 리포트 서비스 동작 구조우리 프로젝트의 두 번째 MVP인 `데일리 리포트..
프로젝트 리팩토링 (1) - 객체 지향 설계
·
Project
데이터 주도 설계에서 책임 주도 설계로프로젝트를 유지보수하고 새로운 기능을 개발할 때마다 `데이터 주도 설계`를 해오고 있다는 느낌을 지울 수 없었습니다.해커톤 기간은 10일만 주어졌고, 이 기간 동안 개발하던 프로젝트가 한 번 엎어져 남은 기간이 6일밖에 안 됐던지라 객체 지향적인 협력 관계를 고려하지 못한 채 개발을 이어나갔습니다. 해커톤 종료 후 고도화 기간 동안 설계를 재점검하지 않고 유지보수와 새 기능들을 개발했는데, 코드를 읽을 때마다 여기저기 중복된 코드와 제각기 다른 구현 방식 때문에 코드 읽기가 힘들었습니다.원인은 객체의 행동이 아닌 상태에 초점을 둔 데이터 주도 설계 때문이라고 생각되어 문제 해결을 위해 조영호 님의 오브젝트를 다시 읽었습니다. 이번 포스팅을 시작으로 `책임 주도 설계`..
Java Memory Model(JMM)과 동시성 규칙
·
Java
Java Memory ModelJava Memory Model(JMM)은 JVM 내에서 메모리에 데이터를 읽고(read) 쓸 때(write)의 규칙을 말한다.JMM는 메모리를 두 가지의 공간 개념으로 다룬다.하나는 스레드 간 공유되는 메모리로,다른 하나는 스레드 내에서만 사용되는 메모리로 다룬다.JVM에서 스레드 간 공유되는 영역은 Heap(Method Area도 포함)이다.스레드 내에서만 사용되는 영역은 JVM Stack이다. (JVM Stack 내의 Stack Frame들을 아우르는 스택 영역이라 생각하자.) 메모리 모델의 이해를 위해 쉬운 예시를 들어보자 가정Heap에는 `Object 1` 객체와 `Object 2` 객체가 들어있다.메서드 내용은 primitive 타입인 int 변수를 생성하고, `..
JVM 아키텍처 정리
·
Java
JVM(Java Virtual Machine), JMM(Java Memory Model) 관련 글들을 읽다가 "논리적인 개념"과 그 개념을 구현한 "구현체"를 헷갈려했다. 이 글을 통해 JVM 아키텍처에 대해 제대로 정리해 보자.JVM 명세To implement the Java Virtual Machine correctly, you need only be able to read the class file format and correctly perform the operations specified therein. Implementation details that are not part of the Java Virtual Machine's specification would unnecessarily co..