| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- 테스트코드
- DLT
- rdb
- 메시지브로커
- 마케팅 #퍼플카우 #새스고딘 #혁신 #독서 #이북
- 메세지브로커
- retry
- blockingqueue
- jedis
- 비동기처리
- redisstreams
- 레디스스트림
- god object
- 자연어캐싱
- 배치처리
- SaaS
- redis
- springboot
- OOP
- 객체지향적사고
- 장애복구
- 임베딩
- 코사인
- redissearch
- 레디스
- 데이터유실방지
- 시맨틱캐싱
- aof
- 백엔드
- Kafka
- Today
- Total
목록개발 (16)
pandaterry's 개발로그
모던 자바의 새로운 API들은 개발자에게 더 나은 코드를 작성할 수 있는 도구를 제공합니다. 하지만 이러한 API들의 설계 의도를 제대로 이해하지 못하고 사용하면 오히려 코드 복잡도를 높이고 성능을 저하시키며, 시스템 설계에 구조적인 문제를 야기할 수 있습니다. 이는 해외 자바 커뮤니티와 언어 설계자들도 지적하는 중요한 문제입니다. Optional: 메서드 반환 타입으로만 설계된 API 설계 의도: null을 명시적으로 표현Optional의 핵심 설계 의도는 "null을 반환할 수 있는 메서드의 반환 타입"으로 사용하는 것입니다. Java Language Architect Brian Goetz는 "Optional은 메서드 반환 타입으로만 사용하도록 설계되었다"고 명시했습니다. 안티패턴: 메서드 파라미터..
JPA와 도메인 모델을 함께 사용하면서 객체지향적으로 설계하다 보면, 조회 쿼리가 복잡해지는 문제에 직면하게 됩니다. 특히 페이지네이션이 필요할 정도의 복잡한 조회에서는 이 문제가 더욱 두드러집니다. 이는 해외 스프링부트 및 자바 커뮤니티에서도 오래 논의된 주제입니다. 실무에서 겪는 문제들 객체지향과 SQL의 근본적 불일치도메인 모델은 비즈니스 로직과 불변성 보장을 위해 풍부한 연관관계를 가져야 합니다. 하지만 이는 조회 쿼리를 복잡하게 만듭니다. JPA는 CRUD 보일러플레이트를 피할 뿐만 아니라 관리되는 엔티티에서 작업할 때 대부분의 수동 레포지토리 호출을 피할 수 있게 해줍니다. 하지만 동작이 신비롭게 느껴질 수 있으며, 쓰기에는 편리하지만 읽기에는 제어권이 부족한 것이 문제입니다. N+1 문제연관..
CH5. 책임 할당하기 도입부 공감이 되는 문장 책임 할당하는 것의 가장 어려운 지점은 어떤 객체에게 어떤 책임을 할당할지 정하는 것이다. 객체지향 설계에서 가장 중요한 것은 올바른 책임 할당입니다. 하지만 어떤 객체에게 어떤 책임을 할당해야 할지 결정하는 것은 쉽지 않습니다. 책임 할당 작업 자체가 트레이드오프 과정이며, 다양한 관점에서 설계를 평가할 수 있어야 합니다. 이번 장에서는 GRASP 패턴을 사용하여 책임을 올바르게 할당하는 방법을 학습합니다. GRASP는 General R..
옛날에도 읽었지만 업무를 하면서 체화가 안되었다고 판단해서 다시 읽어보면서 정리해보려 합니다. 여러번 읽어도 괜찮은 책이라 생각하기도 하고, 더 광범위한 사례가 필요할 때 다른 책도 구매해보려 합니다. 암튼 목표는! 데이터 중심 사고에서 어느정도 벗어나서 객체지향적인 사고를 해봐야겠습니다. 1. 협력협력이란?다양한 객체들이 영화 예매라는 기능을 구현하기 위해 메시지를 주고 받으며 상호작용하는 것여기서 협력에 참여하기 위해 수행하는 로직이 책임협력 안에서 수행하는 책임들이 모여 역할을 구성 메시지 전송객체 사이 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단왜 유일하냐면, 내부 구현에 직접 접근할 수 없기 때문. 메시지 전송만을 통해 요청을 전달가능메시지 발신자가 메서드를 실행하여 메시지를 보내고, ..
서비스 클래스가 점점 무거워질 때, 우리는 한 번쯤 이런 생각을 합니다.“나는 오케스트레이션만 하니까 괜찮지 않나?”“도메인 객체는 그냥 데이터 구조잖아.”“유효성 검사는 서비스에서 다 하면 되는 거 아냐?” 실제로 몇몇 개발자들도 이런 구조를 문제 삼지 않고 넘기곤 합니다. SRP를 지켰다거나, 도메인을 분리했다는 형식적 명분으로 충분하다고 느낄 수도 있기 때문입니다. 하지만 진짜 중요한 건 그 구조가 정말 도메인의 책임과 역할을 반영하고 있는가입니다. 이번 글에서는 흔히 "이 정도면 괜찮다"라고 여겨지는 코드들이 실제로는 어떤 문제를 유발할 수 있는지를 검토하고, 그에 대한 개선 방향을 구체적인 코드와 함께 살펴보았습니다. 총 4가지 예시를 준비해봤습니다 :) 예시 1. OrderService – ..
웹 백엔드를 운영하다 보면 캐시는 거의 본능처럼 사용하게 됩니다. 대부분은 Redis나 Memcached에 “정확히 일치하는” 키를 기반으로 결과를 저장하곤 합니다. 예를 들어, product:summary:2024-05 같은 키는 5월 상품 요약 데이터를 조회할 때 잘 맞는 구조입니다. 이렇게 명확히 정해진 키로 식별할 수 있는 요청은 캐시하기가 쉽습니다. 그런데 최근에는 자연어 기반 인터페이스가 많아지고 있습니다. LLM을 활용해 데이터를 조회하거나, 자연어로 분석 보고서를 생성하는 시스템이 점점 늘어나고 있습니다. 문제는 이런 자연어 요청은 매번 다르다는 점입니다. 예를 들어 사용자가 이런 식으로 요청할 수 있습니다.“5월 매출 요약 보여줘”“지난달 실적 정리해줘”“이번 분기 매출 추이는?”이 요..
운영 중 발생한 장애를 원인부터 끝까지 추적하려면, 신뢰할 수 있는 로그가 반드시 필요합니다. 특히 JPA를 사용하는 시스템에서는, 엔티티가 변경될 때마다 무엇이 바뀌었고, 누가 변경했으며, 언제 어떤 요청에서 발생했는지 그 이력을 상세히 남기는 일이 중요합니다. 많은 시스템에서는 Kafka나 Redis Stream, 또는 Change Data Capture 기반 구조를 활용합니다. 하지만 다음과 같은 환경에서는 그런 선택이 불가능합니다.외부망과 완전히 단절된 폐쇄망 환경 (군/금융기관 등)Kafka, Redis, ELK 등 인프라 설치 자체가 제한된 경우외부 브로커 없이도 로그 유실 없는 처리가 요구되는 상황실제로 제가 경험한 한 시스템은 배치 업로드 한 번에 수만 건 이상의 엔티티가 변경되는 구조였습..
배경요즘 SQL ResultSet을 받아 데스크톱 앱에서 바로 엑셀 파일로 내려주는 서비스를 개발 중입니다. 초기에는 수만 건 단위의 다운로드만 고려했지만,“고객사의 요구에 따라 향후 수백만 건, 심지어 수천만 건까지 조회량이 늘어날 수도 있겠다” 는 생각이 들었습니다. 아직 실제로 그런 대규모 요청이 들어온 것은 아니지만, 미리 대비하지 않으면 나중에 갑작스러운 부하에 허용하지 못할 수 있습니다. 그래서 이번에는 JVM 힙 2 GB 환경에서 잠재적인 극한 부하를 가정해 보고자 합니다. 다음 세 가지 기법을 동일 조건에서 비교·검증하며, “어떤 구조가 가장 안정적으로 견딜 수 있을까?”를 확인해 보겠습니다. 근데 왜 JVM 힙을 2GB로 제한했는가?이번 실험에서 JVM 힙을 2GB로 제한한 이유는 단..