2025 스프링캠프 내용 정리와 후기
개요
매년 스프링캠프를 지원했지만 올해 처음으로 당첨됐다. 최근 안좋은 일도 있었지만 안좋은 일만 있는 건 아닌 것 같다. 올해는 스프링 캠프 10주년이라 힘을 주고 준비했다는데... 제법 기대를 하고 들으러 왔다.
세션은 다음과 같았다.
첫 세션이 제일 고민됐다. 다양한 종류의 세미나를 들으러다니는 이유가 가능한 많은 사례들을 보고 싶어서인데, 첫세션을 ML이 아니라 SaaS를 개발하는데 있었던 일들을 듣는 것도 충분히 재밌어보였기 때문이다.
하지만 ML쪽도 재밌어보였고 HR이란 분야가 너무 핏한 분야 같아서, 일단은 리젠시홀로 스타트를 끊었다. 후기를 작성할 때마다 내 생각도 주석을 조금씩 남기는데, 파란색이 내가 한 생각들이다.
1. 난 spring에서 ml 서빙을 해봤어요
오랫동안 ml에서 주로 사용하는 언어는 파이썬이라는 것을 부정할 수는 없다. 하지만 spring 생태계 안에서 spring-ai가 꽤 활발하게 작업되고 있어서, 어떻게 사용하고 있을지 궁금해서 첫 세션으로 선택했다. 발표자 분 이력이 네이버-토스-스타트업이라 내가 추구하는 방향의 반대라 대단하다는 생각이 들었다.
JVM에서 ML 서빙을 하는 이유, 어떻게할 수 있는가? 이번 세션에서는 스프링에 국한된 이야기라기보다는 JVM에서 ML을 다루는 방법을 다룬다.
회사에서 ML을 서빙해야하는 상황에 놓이면 어떻게해야할까?
파이썬을 빼놓고 이야기할 수는 없다. ML을 만드는 라이브러리 모델들이 전부 파이썬에서 이루어지기 때문이다. 그래서 파이썬으로 서빙을 해볼까? 하는 생각이 가장 쉬운 접근법이다.
그러나 파이썬으로 대규모 프로덕션을 처리하는건 어려움이 많다.
- GIL이 파이썬의 철학. 싱글 스레드로 동작하게 하는게 파이썬의 철학이기 때문에 성능과 운영의 한계가 있다.
- 패키지 및 환경 관리가 Gradle에 비해 복잡성이 크다.
- 타입 관리 등등의 문제...로 인해 어렵다. 실제로 활용하는 회사들도 있지만 난이도가 너무 높다.
다른 방법을 찾아보자.
그래서 ML 추론 서버/엔진을 클라우드 벤더사들이 제공을 많이해주니까 이용해보면 어떨까? nvidia, aws, oci 등.
클라우드 서비스 엔진을 쓰면 쉽고 간편하게 사용할 수 있을 것 같다.
- 구축 및 운영 복잡성. 고성능 네이티브 언어(C, 러스트)로 구성되어 있어서 장애 대응이 어려움. 설정하나에 큰 성능이 좌우됨.
- 벤더 종속성과 기술 지원의 한계
- 리소스 및 비용 부담
JVM에서 해보자. 어떻게하는게 좋을까?
ONNX, TensorFlow : 저수준 라이브러리, SLA가 필요하다면 하드웨어를 쥐어짜면서 할 수 있다.
DJL(Deep Java Library) : 고수준 라이브러리, 추상화가 잘 되어있어서 잘 몰라도 하는데 불편함이 없을 것 같다. 추천!
DJL을 통한 JVM에서의 ML 서빙 특징
1. 파이썬과 ML, AI 전문가가 아니더라도 사용할 수 있게 해주는 머신러닝 서빙을 할 수 있게 지원해주는게 DJL의 철학.
2. 다양한 모델(Model Zoo)를 활용할 수 있다 : Hugging Face(전세계들의 모델러들이 자체 개발해둔 모델, 튜닝한 모델을 공유한 허브)와 연결되어 있음. 모든걸 다 지원하진 않지만 포맷에 맞춰서 개발해줬으면 사용 가능.
서빙 예시
검색, 추천, 리뷰 분석, 제품 검수 - 리뷰 분석 분야로 예시를 들어보자
리뷰를 가지고 어떤 테스크를 할 수 있을까? 리뷰 노출과 판매자 패널티 등을 할 수 있다.
리뷰를 분석하기위해 감성 분석 모델을 가져오고, 분석하라는 함수 하나로 처리할 수 있다. 코드로도 쉬워보임 - 넷플릭스에서도 DJL을 이용해 분석한 예시가 있다. https://aws.amazon.com/ko/blogs/opensource/how-netflix-uses-deep-java-library-djl-for-distributed-deep-learning-inference-in-real-time/
But DJL은 저수준 제어가 힘들다. 서비스 개발은 2코어 4기가로도 잘 사용하는데... ML은 그렇지 않다.
CPU 48코어를 주기도 하고, 메모리를 몇 백기가 할당하기도하고, 하드웨어 성능을 0.000001%까지 쥐어짜기도 한다. 그러나 이런게 DJL에서는 어렵다. 결국 ONNX와 TensorFlow를 써야한다.
TensorFlow로 어떻게 고성능을 짜낼 수 있을까?
하드웨어에 대한 상세 설정(GPU 병렬처리 등), 동적 배치 처리(동시에 몇개 실행할 건가), Zero-copy 메모리 최적화 등 모델 내부에서의 연산들도 최적화 할 수 있다.
Storm 솔루션 : 질의 -> 문서 탐색(질의와 가장 관련이 높은) -> 문서 내용 + 질의 쿼리 -> 답변 생성
코사인 유사도 코드 - 모델 추론과 유사도 비교를 상세하게 옵션 설정을 한다. 모델의 내부 상세 옵션들과 인풋 가공으로 유사한 답변을 얻기 위해 노력한다. 코사인 유사도 비교도 세부 옵션을 튜닝할 수 있기 때문에 성능을 더 높일 수 있을 것이다.
천만개의 문서를 찾는데 1초도 안걸리게 설정함!
그렇지만 JVM이 정답은 당연히 아니다. 단점도 많다.
모델 구조를 일일히 다 만들어야하고, 추론 코드를 일일히 다 짜야함. 모델에 대한 이해도가 없으면 어렵고, 하드웨어 튜닝도 필요함
spring-ai를 쓰는게 도움은 되지만, 1.0이 나온게 지난달(2025년 5월임)이라 자바 생태계에서의 지원은 여전히 느리다. 파이썬은 몇 년이 지났기 때문에 차이가 많이 나는건 어쩔 수 없다.
정답은 없기 때문에 각자의 환경과 해야하는 태스크를 잘 고려해서 만들어보세요.
QnA
spring-ai와 직접 서빙했을 때의 차이? spring-ai는 내부에서 개발된 모델을 서빙하는 ai가 아님. 외부 LLM을 쉽게 가져와서 서빙할 수 있게 지원하는 라이브러리라 현재 조건과 차이가 있음. spring-ai가 현재하는 지원하는 방향성과 모델링을 전문적으로 하는 회사의 취지와는 다르다 생각함.
반드시 파이썬에서만 한다? ML 테스크를 지원하는게 파이썬 라이브러리에만 있는 경우. 빠르게 치고나오는 기술을 Java 생태계에서는 지원해주지 않음. 최신성을 반영해야하면 파이썬을 쓰는게 좋다.
일반적인 웹서버와 다르니 JVM 튜닝 전략? 스케일 아웃으로 해결되지 않고, 메모리와 코어를 얼마나 쓰냐가 더 중요하다. 그래서 이쪽을 지원하는 옵션을 설정하는 전략을 사용. 결국 JVM쪽도 장점은 있지만 결국 파이썬 투트랙이 필수 불가결하게 생긴다.
회사에서 사용할만한 모델은 어느정도가 좋을까? 크기가 천차만별이라 코어/메모리가 얼마나 필요하다고 확답하기 어려움. 클라우드 환경과 온프레미스 둘다 활용한다.
발표자분이 발표를 너무 잘하시고, 난이도 설정도 잘하셔서 듣기 편했다. 내가 작업하던 10년전에는 파이썬도 Tensorflow, Keras가 막 등장하던 시기라 레퍼런스도 많이 없어 튜닝 작업이 매우 어려웠었다. 그런데 이제는 JVM 생태계 내에서 DJL이라는 라이브러리까지 등장한 것 보면 많이 발전한 것 같다... 기회가 되면 꼭 써보고 싶다.
2. Amazon Q Developer와 함께하는 생성형 AI시대 헤쳐나가기
빅테크와 미국쪽에서 LLM 모델이 빠르게 발전하면서 개인이 AI 관련 서비스를 개발하는 것 보다 AI를 어떻게 활용할지가 중요해지고 있다 생각한다. 특히 개발분야는 어떻게 개인의 생산성을 올릴 수 있을지가 중요해지고 있고 미국에서는 다양한 AI 개발 Tool들이 만들어지고, 인수되면서 엄청나게 발달하고 있지만, 난 아직 AI Tool들을 엄청나게 잘 활용하고 있지 못하다고 생각한다. 그래서 다른 곳은 어떻게 쓰나 궁금해서 이 세션을 선택했다(커뮤니티는 재미없어보였음). 발표자는 삼성전자에서 오래 일하다가 AWS 아키텍트로 들어가신 분.
몇년 전만하더라도 쿠버네티스 CNCF와 같은 분야에 대해서만 이야기했지만, AI 등장 후 새로운 개발 패러다임의 시작됨.
바이브 코딩 : LLM에 프롬프트를 입력하여 문제를 해결하는 AI기반 프로그래밍 기법,
비결정적 프로그래밍이라는 완전한 새로운 패러다임의 전환
코드 생성(개발 회사 경영진 600명 중 51%가 관심) 관점에서 AI 툴을 만드는게 기업관점에서 도움이 될 것이다.
Amazon Q Developer
- AWS 인프라 문제를 질문할 수 있고, 구축해달라고도 할 수 있다곤 하는데... 알아봐야겠음
- 에이전트 AI : LLM에게 도구를 쥐어줘서 특정한 무언가를 잘 할 수 있게 만드는 것. Q Developer는 이걸 잘 지원해줌
- 자율 행동형 AI(Agentic AI) : 주어진 목표를 위해 스스로 판단하고 행동하는 인공 지능 시스템. 실패하면 자기가 알아서 다시 함
신뢰할 수 있는 코드 생성을 어떻게 할 수 있을까? : 코드베이스를 종합적으로 분석하고, 생성한 코드를 어떻게 만들어갔는지 과정을 보여준다.
/dev - 코드 개발 에이전트
자연어를 활용한 코드 개발, 버그 수정, IDE 내에서 직접 코드 변경 및 생성, 기존 코드 분석 후 구현 계획 수립
/test - 유닛 테스트 생성
코드베이스 기반 테스트 케이스 자동 식별, 자동화된 단위 테스트 생성, 격리 테스트를 위한 목(mock)/스텁(stub) 생성, Java와 Python 프로젝트 지원
/review - 코드리뷰
코드 리뷰 해줌
/doc - 코드 이해와 문서화
READ.ME를 대신 작성하거나 주석과 문서화를 대신 해줌
/transform
메인 프레임, 브이엠웨어 워크로드, 닷넷 프레임워크, 자바어플리케이션 버전업과 마이그레이션/포팅된 레포트를 작성해줌. SpringBoot 업데이트도 잘 반영해줌.
Amazon Q Developer CLI도 있음. 올 연말 쯤이면 IDE를 안쓰게 될거다라는 이야기를 한다고 함. gemini cli, claude cli 등이 대표적인 예.
QnA
Rule을 줄 수 있나? 코드를 일괄 변경되는데 스텝 바이 스텝 변경이 가능한가? rule 지정 가능. 시스템 프롬프트 지정 가능. 마크다운 설정, 한글만 말해 설정 가능. 파일 변경 사항 있을 때, 변경하기 전에 물어보라고 할 수 있으며, 시스템 프롬프트로 변경 사항들을 기록해두라고 남겨 둘 수도 있다.
리팩토링 시 중간 맥락을 빼먹는 문제는 해결 할 수 있나? 컨텍스트 윈도우의 양이 달라서 모델의 한계 때문에 어쩔 수 없지만, 큰 모델들도 있다. 툴의 문제라기보다는 모델의 성능에 따라 해결될 문제고, Q developer에도 있는 현상이긴 함.
https://aws.amazon.com/ko/q/ 일단 광고 세션이었다. copilot과 엄청난 차이가 있어보이지는 않는데, 아직 cursor도 많이 사용해보지 않은 입장에선 그렇게 매력적으로 느껴지지는 않는다. 그래도 프리티어를 제공해주기도하고, 문서 생성이 꽤나 매력적이었는데 다이어그램도 그려준다니 Lite 버전정도는 써볼만 하지 않을까 싶다. haril님은 별로 안좋아 한다하셨는데, 잘 쓰던 cli가 amazon Q로 팔려갔다고 한다(https://fig.io/)
올리브영 물류시스템 개선기
작년 Google I/O에서는 올리브영의 전시 화면을 개선한 과정을 정리한 세션을 들었었다. 그 세션에서 보고 느낀게 많았기 때문에 이번 세션도 꽤나 기대하고 있다. 올리브영이 멀티 플랫폼도 지원해야하고, 엄청난 양의 상품과 다양한 이벤트로 인한 다양한 전시 화면도 필요하고, 이벤트 마다 발생하는 스파이크 트래픽, 글로벌 서비스로 확장 등등 많은 문제가 있는 것으로 알고 있는데 물류쪽에는 어떤 문제가 있을지 궁금해서 선택한 세션.
올리브영은 한시간 이내에 모든 매장에서 상품을 받을 수 있게 물류 시스템을 구축해놨음
개선하기 전의 상태
발주-주문 테이블에서 모니터링 배치를 통해 인터페이스 테이블로 이동하고 EAI에서 인터페이스 테이블을 모니터링 배치를 해서 또다시 센터-발주 테이블로 적재하고 또다시 모니터링 배치를 돌아서 연동을 시킴. 3단 모니터링 배치로 인해서 지연이 발생함.
입고가 지연되면 -> 입고 포기 케이스가 생김 -> 현장에서는 무한대기 상태에 빠짐 -> 매출감소의 사이클
1. 실시간성 미흡과 정합성 보장 어려움 : 배치 실행 중 변경이 발생하면 정합성 문제가 생김
2. 성능 저하 및 시스템 부하 유발 : 데이터가 배치 간격만큼 쌓임.
3. 장애 복구의 비효율성 : 장애 복구가 어려움
4. 운영 복잡성 증가 : 단계별로 운영/주관부서가 달라서 운영이 어려움
개선 후
대한통운이나 배송사의 요청을 카프카(AWS MSK)를 통해 메시지를 발송하고, ECS에서 프로듀서와 컨슈머를 운영. 오류가 발생하면 DLQ에 적재시키고 firehose로 s3에 저장시키는 동시에, 알람을 슬랙으로 발송함.
운영 복잡도 증가, 기존 시스템과의 연계 부담, 메시지 순서와 중복 처리, 개발자 및 운영자 학습곡선이 문제가 됐었음. 하지만 플랫폼 엔지니어링 팀의 지원을 받아서 해결함.
배치였을 때 발생한 문제들... 출고처리는 새벽에 진행됨.
- 배치 실행 시간 후, 데이터가 들어와서 갱신이 되지 않는 일이 있었음.
- 제품이 존재하는데, 매대 상품 정보에 SOLD으로 표기됨
- 대응을 위해 야간, 주말에도 대비를 하고 있었어야 함
-> 출고처리 모니터링 체계를 만들어 99% 대응이 안되면 개발자에게 온콜(전화..)이 오도록 만들어뒀음
-> 데이터 센터(콘솔 로그), 데이터 센터(메모리사용량, CPU 사용량), 슬랙 알림 로그 등등 봐야할 게 많다 : Datadog으로 해결
실시간성과 확장성을 위한 RDB 중심의 구조 탈피
온라인 재고 도메인과 오프라인 재고 도메인 두개가 있다 : 성격도 다르지만 물리적 데이터 베이스가 분리가 되어있음
온라인 재고 도메인
대한통운 물류센터의 데이터가 변경되면 싱크를 맞추는 방식으로 구현되어있음. 그러나 상품 가짓수가 2만개가까이 됨
오프라인 재고 도메인
올리브영 매장의 재고를 담당. 자사 시스템에서 변경되는 재고를 오프라인 DB에 직접 반영.
상품 가짓수 1100만개, 온라인 재고에 비해 500배 많음. 매장 하나당 8천개의 상품을 보유하기 때문에 그렇다.
올리브영 오늘드림 서비스... 3시간 안에 집앞까지 드림
상품 주문 -> 배달 대행사 -> 집근처 올리브영 매장에서 배달대행 기사가 제품을 픽업 -> 상품 수령
오늘 드림 때문에 온라인 몰에서 재고조회 API가 필요하고 자주 사용할 수밖에 없는 환경.
23년 6월 대규모 이벤트에서 전사 장애가 발생함 : 장사가 너무 잘됨....
정기 대규모 이벤트마다 매출 신기록 달성해 증가하는 트래픽이 기존 RDB가 감당이 안되는 상황까지 오게됨
3천만/DAY 호출: RDB가 감당할 수 있는 양이 아니라 전사 오류가 발생한 것. 결국 Redis를 구축함. 요청이 잦은 DB에 redis를 갱신하는 배치 서버를 두고 redis를 갱신하고 redis에서 데이터를 받아가도록 함
redis를 도입하면서 발생한 문제들
동시성 제어 이슈 : RDB에서는 락이 걸려서 내부적으로 동시성이 보장이 되지만, redis는 별도의 동시성 제어 로직이없으면 정합성 이슈가 발생할 수 밖에 없다. RDB에 Write 하는시점과 redis에 Read하는 시점의 차이가 발생
- Redisson의 분산락 기능을 사용해서 동시성을 제어하도록 함 : 이건 좀 알아볼 필요가 있겠다
조회 성능 이슈 : 메모리 DB가 디스크 기반 DB보다 성능이 우위임. ns와 ms 차이. 복수건 조회는 스캔 기반의 패턴 탐색으로 인해서 오라클 대비 성능상 불리. 인덱스가 없어서 전체 키를 패턴기반으로 스캔 반복 조회를 하게 됨. ms vs s 차이가 발생함.
- 조회 용도별로 성능을 최적화 하기 위해서 다양한 데이터셋 3개 종류로 미리 만들어 둠... 상품 상세, 전자라벨, 검색엔진 등
10배정도의 성능향상 : 343ms -> 37ms
안정성 이슈 : redis는 휘발성 데이터베이스기 때문에 안정성 이슈가 발생할 수 밖에 없다. AWS에서 사용 중이라도 1년에 한두번씩 장애가 발생하긴 함. 서킷 브레이커 패턴으로 Redis의 장애 상황에서는 오프라인 RDB로 요청을 돌려서 장애 전파를 방지.
여전히 오프라인 RDB와 Redis의 싱크를 맞추는 작업은 배치로 돌고 있기 때문에 CDC로 배치를 완전히 제거하는게 단기 목표.
Reids를 도입하는게 항상 안정적이고, 속도를 보장하진 않으니 기술과 도메인 이해를 한 후에 도입하길 권장함.
재미있게 잘 듣긴했지만, 요약하면 모니터링 배치로 데이터베이스를 업데이트하던 것을 카프카로 데이터 스트리밍 방식으로 변경하여 실시간성을 보장했다와 redis 캐시로 데이터베이스를 보호하고 안정성과 속도를 보장할 수 있었다였다. 설계 자체는 잘 알려진 방식이라 설계하는 것보다 라이브 서버에서 순단없이 마이그레이션하는 부분이 가장 큰 고민이었을 것 같다. 데이터가 꼬이면 전사적으로 엄청난 문제가 발생할 수 있기 때문에 어떤 것들을 고려해서 작업했는지도 궁금했는데, 이쪽 부분에 대한 언급은 따로 없었다. 이것도 좋은 주제였지 싶고, 다음엔 이런 내용도 추가됐으면 좋겠다.
실전! MSA 트랜잭션 개발 가이드
멀지 않은 미래에 MSA로 개선하는 일이 잡혀 있다. 첫 분리작업에서는 트랜잭션을 디테일하게 고려해도 되지 않는 상황이라 예상된다. 하지만 한발짝만 나간다면 이 문제가 나타날 것 같아서 깊이 생각하지 않고 세션을 고를 수 있었다. 작년에도 동일한 주제로 발표하신 분이라 작년 세션도 한번 들어보길 바란다고 하셨음.
MSA에서 서비스 간의 데이터 쓰기를 어떻게 하면 좋을지를 강조해서 세션을 진행할 계획.
MSA는 각 팀이 서로 독립적으로 일하는 것이 목적(나랑은 목적이 다름)
그렇지만 MSA를 구성하는 서로 다른 서비스는 각각이 관여하는 테이블에 크로스 액세스하면 안된다. 관여된 사람이 많아질 수록 문제가 되기 때문에 분리. 그렇지만 이럴 경우 서비스간 트랜잭션 보장이 안된다.
2PC와 같은 분산 트랜잭션은 사용이 권장되지 않는다. 그러면 어떻게 해결해야할까? 여러 서비스에 걸친 쓰기는 트랜잭션 보장이 안된다.... 서비스를 분석하고 담당자 간의 논의를 통해 각자 관리하도록 하자?(맞나)
데이터 오너십 원칙 : 오너십을 가진 서비스만 데이터를 쓴다. 여러 서비스가 쓰기 권한이 있으면 안된다.
- 컬럼 단위로도 서로 다른 서비스에게 쓰기 권한을 줄 수 있다.
- 로우 단위로도 나눌 수 있다. 각 서비스에서 특정 컬럼값을 갖는 로우만 관리하도록 한다.
실패한 트랜잭션과 롤백 관리 : 중간에 실패하면 시작 전의 상태로 정리하는 기능
- 하나의 트랜잭션이라면 실패할 경우 그냥 롤백하면 된다.
- 여러개의 트랜잭션으로 처리 될 때는 보상트랜잭션과 재시도하도록 함.
- 피벗 트랜잭션으로 관리해서 피벗까진 성공하면, 그 기능까진 성공한 것으로 본다. 그 이후엔 이벤트로 실패할 경우 재시도하도록 함. 피벗 트랜잭션 전에 실패도 피벗 전까지 재시도하도록 구현. 반복 실패시 개발자가 관여함
- 피벗 트랜잭션을 잘 관리하면 보상 트랜잭션이 필요 없어져서 개발이 용이해진다. 다른 서비스에 쓴 후 실패할 경우 삭제 API를 발송해 싱크를 맞춘다.
트랜잭션의 동시성 제어와 일관성 문제
트랜잭션이 반영되지 않았는데 읽음 : 같은 조건으로 두 번 읽었는데 값이 다르게 나옴
트랜잭션 중간에 볼 수 있음 : A -> B(Commit) -> C -> D (ACD Commit) 이라면 싱크가 안맞음
변경 중인 데이터를 다른 트랜잭션이 덮어 쓸 수 있음
- 해결법 Semantic Lock, TCC(Try, Confirm, Cancel),Offline Lock
- 중간 상태를 설정해서 다른 트랜잭션의 쓰기를 차단
앞서 조회한 데이터를 다른 트랜잭션이 별경할 수 있음
- select for update 문제 락을 잡는 동안 다른 어플리케이션에서 접근을 불가하도록 처리한다.
신뢰할 수 있는 트랜잭션 구현
- 두 저장소에 쓰기 어려움. 특정 사건을 데이터로 저장하고 API/이벤트 호출하는 것은 의외로 까다로움
- 트랜잭션 아웃박스 패턴: 이벤트와 데이터를 한번에 생성하고, 이벤트 발송과 전송 결과를 업데이트 하는 식으로 구현.
- 불안정한 네트워크 통신으로 인해 실패할 경우 동일한 요청에 대해서는 동일한 결과를 뱉도록 해야한다. 멱등성에 대한 이야기
- 그래서 진짜 실패와 가짜 실패를 잘 정의해야한다.
- 실패 정보의 유실 방지를 위해서 시작 전에 DB에 insert하고 결과를 받고 update 하도록 한다.
멱등성있게 처리하기
중복 실행 : 유니크 값으로 식별, 중복 체크는 사전 체크 or 사후 에러 무시
순서꼬임 처리 : 버전을 통해 실패 요청의 업데이트를 반영하도록 한다.
정말 말씀하고 싶은 내용이 많으셨는데, 발표 시간이 너무 짧았다. MSA에서 생길수 잇는 문제들과 트랜잭션이 발생시킬 수 있는 서비스 상에서의 문제까지.... 다루는 이야기가 너무 광범위하고 많았다. 우리 시스템에서 필요한게 뭔지 설계를 먼저해보고 필요한 것들을 갖추는 방식으로 개발하길 권장하셨다. 내가 지금 서비스 모듈 분리 작업과 아키텍처를 적용하면서 많이 느끼고 있는 감정이기도 하다.
패널 Talk - 기술 Talk
이 세션보다는 카카오뱅크 쪽이 조금 더 재밌어보였지만 Talk 주제를 보고나선 생각이 바뀌었다. 내가 항상하는 고민들과 정답이 있을지 궁금한 객체 설계와 어디까지 확장성을 고려해야하는지에 대한 이야기들이 주제였다. 그리고 전부터 한번쯤 제대로된 강연을 들어보고 싶었던 이동욱, 조영호 개발자님들의 이야기라 선택하게 됐음.
객체에게 역할과 책임 부여를?
이) 데이터 지향, 함수형 등의 프로그래밍이 많이 나오고 있기 때문에 OOP가 예전에 비해 관심도가 줄어들고 있는건 사실임.
조) 순서가 있다. 이미 존재하는 객체에게 책임과 역할을 부여하는게 아니라 내가 어떤 맥락에서 설계를 하고 있는지 고민해라.
객체들이 어떤 역할을 담당해야 컨텍스트가 잘 굴러갈지 고민하는게 먼저다. 패널 톡을 예를 들면 사회자와 패널의 역할이 있고, 질문을 할 책임 대답할 책임이 있다. 어떤 등장인물들이 상호작용을 하는지를 고민하고 역할 책임을 뽑고 분배한다면, 재사용성 가독성 응집도를 고려해서 잘 설계할 수 있을 것이다.
안) 모던 소프트웨어 엔지니어링 책추천. 모듈화는 자신의 분야에 통달한 전문가가 작성한 코드와 뉴비의 코드의 차이가 발생함.
어떻게 트레이닝?
조) 사용자에게 제공할 기능을 먼저 생각한다. 클래스부터 생각하는 방식은 안좋음. 머리 속에서 시각적인걸 떠올리고 어떤 식으로 동작하면 이 기능을 잘 지원할 수 있는지를 고민. 사람들에게 설명했을 때 듣는 사람이 납득할 수 있으면 된다. 내가 구현하려고하는 객체들의 상호작용을 남들하게 깔끔하게 설명할 수 있으면 좋은 객체 지향을 설계할 수 있으리라 생각함.
JPA 엔티티를 Domain 객체로?
JPA를 활용한 OOP를 떠오르기 쉽다. 엔티티와 도메인 객체를 왜 나누는지 나누면 왜 좋을까?
이) 클린 아키텍처가 남긴 의문점이 아닐까?
조) 무조건 좋은 건 없다. 트레이드 오프와 취사선택의 문제임. 비즈니스 로직을 처리하는 Domain 객체와 데이터베이스와 매핑되는 Entity 객체. 반드시 나눠서 가야하는 경우는 DB의 스키마가 바뀔때 도메인 객체에 영향이 가지 않았으면 좋겠다. 변경이 있을 때 둘 다 바꾼다. 바뀌는 속도와 방향을 정확히 내가 알지 못하면 합쳐라. 비즈니스 로직이 어떻게 변화할지 모르고, 서비스가 어떻게 진화할지 모르면 나누는 것보다 그대로 쓰는게 좋다. 서비스 개발 초기엔 특히 더 그렇다.
우리 조직이 독점적인 데이터베이스를 쓰면 이슈가 없기 때문에 굳이 나누지 않아도 좋다. 하지만 데이터베이스를 중복해서 쓰면 문제가 있어서 엔티티와 도메인을 분리하는게 맞다(내가 원하지 않는 방식으로 변경될 수 있기 떄문이지 싶다). 혹은 레거시가 너무 복잡해서 객체 관리가 힘들면 도메인 객체를 분리해서 핸들링하는게 좋다.
안) OOP, 함수형,다음 패러다임은 agentic ai를 이용한 프로그래밍이지 않을까?
코틀린으로 개발할 때 JPA Entity는 mutable or immutable?
두가지가 충돌. JPA Entity는 기본적으로 mutable하다고 가정함. 하지만 코틀린은 언제나 immutable이기 때문에 이때도 도메인 객체로 나눠서 쓰는게 좋다. 그렇지 않을 경우 코틀린 객체의 멤버가 다 nullable이 될 가능성이 있음. 이게 아니면 대안적인 기술들을 찾아보는게 좋다. 굳이 ORM을 JPA만 쓸 필요는 없다.
확장성과 오버엔지니어링 사이의 설계 : 어디까지가 예언이고 어디서부터가 오버엔지니어링인가?
안) 잘 안될수도있기 때문에 처음부터 확장성을 보고 개발하는건 그렇게 좋지 않다고 생각한다. 맞고 틀리고라는 방식으로 접근하지 않았으면 좋겠다. 앞으로 어떻게 될지 알 수가 없기 때문에, 창발적인 결과물이 나올 수 있도록 허용하려면 어느정도까진 변화에 대해서 열려있는 것도 중요하다.
조) 코드를 짤 때 변경을 적게하고 싶은 욕구는 있을 수 밖에 없다. 변경이 좋은 설계는 인터페이스 합성으로 유연하게 만드는게 아니라, 문제의 복잡도에 맞는 가장 단순한 설계이다. 문제를 푸는데 가장 적합한 수준의 복잡도를 선택하는게 중요하다. 내가 알고 있는 수준의 가장 단순한 방식으로 설계를 해둔다. 한달 후에 변경이 된다하면 안넣는게 좋다. (실제로 안들어오는 경우가 매우매우 높다)
현재에 최적화된 설계를 해라.
이) 현재 상황에서 가장 적절한 상태로 구현을하고, 미래는 열어둔 채로 가자로 정리가 된다. 하지만 이 논리는 레거시를 만드는 사람들의 방어 논리로 쓰기 좋은 변명이다. 이 논리로 기술을 머물게 하는 팀원이 발생할 수 밖에 없을 것 같은데 어떻게 해야 좋을까?
안) 설득하지 않음. 본인들이 자기 코드가 안쓰이게 되면 정서적으로 영향을 받고, 성과적으로 결과가 나오기 때문에 본인이 느낄 것. 옳다 그르다로 지적하기보다는 서로 이해하는 방식으로 가게하는게 좋다. 알아서 바꾸도록 함
조) 질문을 나눠서 생각. 현재 아는 것을 최적화와 기존에 있는걸 그대로 쓰자는 다른 이야기. 후자는 판단을 안하겠다는 말. 최적화되어있던 코드를 그대로 사용하겠다는 건 당연히 옳은 선택. 이거에 대한 룰은 가져가는게 좋다. 널리 알려진 좋은 설계가 팀에 좋은 설계가 아닐 수 있으니 룰을 잘 정해서 가기.
설계 철학 vs 조직의 제약 : 내가 생각하는 좋은 설계와 빠른 결과의 사이
안) 질문의 이분법은 동의할 수 없음. 취미로 개발하는게 아니라 돈을 받고 개발하는 것이기 때문에, 회사에 가장 유리한걸 택해야한다. 내가 추구하는 방식은 설득할 논리가 없으면, 다음 기회를 계속 노려라. 조직 탓보다는 계속 변화를 시도해라. 내 코드가 점점 커져서 시니어 분을 먹어버릴 수도 있고, 다른 주변사람을 설득할 수 있고 여러 방법을 강구해봐라.
조) 왜 설계를 하느냐를 생각해봐라. 설계 철학과 조직의 방향이 다르면 안됨. 설계하는 이유는 작업할 때 와닿지는 않지만 누군가 보거나 고칠 때 문제가 된다. 나의 설계철학보다는 조직의 설계 철학을 따르는게 중요. 버그 없이 오랜기간 개발/운영해왔기 때문에 조직의 설계로 채택된 것이다. 그래서 조직의 설계 방식을 따르는게 중요하다.
ex) 그 코드를 잘 읽기 위해서는 그 코드에 대한 사전 지식이 가장 중요하다.
ai 코드와 협업을 위한 코드 : 사람 대 사람이 협업하기 위한 코드는 의미가 사라질까?
안) 미래에 그럴 것이다는 기대. 그러나 미래는 언제 올지 모르고 현재는 필요함. 언젠가 사라질 것이다라는 말에 현혹되지말고, 현재 네가 필요한지를 생각하고 코드를 작성해라. 생산성만이 삶의 의미는 아니고 취향이 반영해서 짜도 괜찮다.
안영회님은 하나의 팀, 회사 전체의 성장이 중요하다는 것을 강조하고 싶으신거 같았고, 조영호님은 본인의 주관이 분명한 것 같았다. 이동욱님이 정리를 참 잘해주셨다. 배울점이 너무 많았고 생각해볼 것도 많았던 세션
빅뱅 방식으로 최선의 개발기
이동하기 힘들어서 들어보기로한 세션. 레일웨이 개발방식에 대한 좋은 글을 본 기억이 있어서 그쪽을 갈까하다가, 빅뱅방식이 뭔지 궁금해서 선택했는데 빅뱅방식이 별건 아니었다.
빅뱅 방식 : 처음부터 끝까지 한번에 개발하는 방식
- SI에서 주로 작업하는 방식.
- 기간이 짧고 양이 많고, 클라이언트도 본인이 원하는 걸 모르거나 설명을 잘 못함. 프로젝트의 구조, 도메인을 파악하기 어려움. 인원이 추가될수록 문제가 증가(인원이 증가될 수록 생산성이 증가하지 않음)
SI는 외주다. 그래서 확정된 일정, 인원, 금액 제시가 필요한데 경쟁이 붙어서 무리한 요구사항을 안된다고 하기 어려움
현실적으로 이터레이션 방식을 적용하기 어려운 분야
기획팀의 리소스가 절대적으로 부족함.
BE는 개발을 시작할 때는 모든 기획 문서를 확인하고 리뷰해야 한다. FE는 제일 밑단에서 고통받게 됨.
개발 끝나고 클라이언트가 원한게 아닐 수도...
묘안이 없기 때문에, 업무 복잡도를 낮추고 태스크를 줄여보자.
해결방안
1. 트리구조로 정리 : 도메인 개념을 정리하는 방식, depth가 계속 깊어진다.
2. 도메인 분석 : 잦은 기획 변경에도 도메인 구조 자체는 변경 가능성이 거의 없음. 코드만 간단히 변경할 수 있도록 조치
3. 모든 API 스펙 정리 : 피그마 화면, API spec 정리
4. 멀티모듈 도입 : 병렬 작업 가능하도록 프로젝틀 정리. 추가된 인원만큼 생산성 향상
프로젝트에 사용되는 내용들을 어떻게 정리할지에 대한 방법론을 다루는 이야기였다. 빅뱅으로 개발하게 된다면, 초기 설계가 너무너무 중요하기 때문에 개발에 들어감에 있어서 필요한 도메인 지식과 API spec을 트리 방식으로 정리한 경험을 이야기해주셨다. 나도 SI 프로젝트를 빅뱅으로 개발해봤지만, 말이 빅뱅이지 기획검토과정 개발과정 검증과정에서 크고작은 잡음과 수정사항들이 나왔었기 때문에 빅뱅이란 말이 맞는지 모르겠다. 아직까지도 진짜 빅뱅으로 개발하는 곳이 있나 싶기도 하다. 트리형태의 데이터 정리 방식은 좋아보였다.
마치며
Lob님이 이번 스프링캠프가 10주년이라서 준비를 많이하셨다고 한다. 아침부터 얼굴에 피곤함이 묻어있으셨다.
(정말 고생하셨습니다)
HR SaaS, 가상 스레드, 레일웨이 지향프로그래밍 쪽을 선택하는게 더 좋을 것 같았어서 아쉬움이 컸다. 세션 소개에 어떤 내용을 다루는지 정보를 담아줬으면 좋았을 것 같다.
사실 스프링 쪽 세션보다는 그냥 개발에 도움이 되는 세션이 많았다. 기억하고 싶은 내용들이 많아서 이번 포스팅이 엄청나게 길어졌다. 세션이 재미는 있었는데... 내가 듣고 싶은 세션들이 자꾸 다른 방에서 진행되서 방을 계속 옮겨야했다. 나만 그런게 아니었는지 세션간 이동이 너무 혼잡했다. 주어진 공간에 비해서 사람이 너무 많았다...
가장 힘든건 집에서 성수가 너무 멀어서 힘들었고, 날이 너무 습해서 이동할 때 너무 더웠다.
힘들었지만 얻은건 많았지... 싶다.