Spring Camp 2026 후기

3년 만에 Spring Camp 컨퍼런스에 참여했습니다. 올해만 벌써 세 번째 컨퍼런스인데, 그중에서도 Spring Camp는 매번 내용이 알차고 도움이 많이 되는 편이라 기대가 컸습니다.

제 기억으로 예전에는 큰 홀에서 모두가 같은 세션을 들었는데 이번에는 세션 선택지가 생겼습니다. 케이터링 타임을 기준으로 전반부는 AI 관련 세션이 주를 이뤘고, 후반부에는 아키텍처와 성능 튜닝 같은 다른 주제들이 배치됐습니다.

각 세션을 되짚으며 기억에 남은 내용들을 남겨두려 합니다.


Spring I/O 2026 — 변화하는 스프링, 떠오르는 AI, 그리고 우리의 준비

카카오뱅크에 재직 중인 발표자들이 Spring I/O 2026에 다녀온 후기와 함께, AI 시대에 우리가 현장에서 어떤 방향성으로 Spring을 활용해야 할지에 대해 공유해 준 세션이었습니다.

Spring WebFlux의 복잡함을 해결해 줄 Virtual Thread

동시성과 비동기를 통해 Blocking I/O의 단점을 해결해 줄 방법으로 WebFlux가 각광을 받았습니다. 하지만 WebFlux에는 다음과 같은 제약 사항이 존재했습니다.

기대 현실
Non-blocking
높은 처리량
DB I/O, Redis, Batch 등 다른 블로킹 포인트 존재
Reactive 스트림
효율적 처리
블로킹이 하나라도 있으면 Reactive 이점 반감
팀 전체가 Reactive 코드 작성 기술 이해도와 비즈니스 숙련도를 동시에 갖추기 어려움
명확한 장애 진단 Reactor 콜백/Operator 체인으로 스택 트레이스가 비즈니스 로직을 가리키지 않음 (원인 추적 비용 급증)

이제는 가상 스레드를 사용해서 Spring MVC에서도 성능을 충분히 향상시킬 수 있습니다. 그래서 비즈니스 로직 중심의 서비스는 WebFlux를 선택할 이유가 적어졌습니다. WebFlux가 유효한 포지션은 Gateway 등 요청의 양 끝단과 백프레셔가 필요한 스트리밍 서비스입니다.

카카오뱅크도 WebFlux를 사용 중이었지만 Spring MVC로 마이그레이션을 진행 중이라고 합니다.

AI 시대에 더 주목받는 Spring Modulith

AI의 성능 향상으로 모든 코드를 직접 작성하는 업무들이 많이 변하고 있습니다. 개발자가 Spec을 정의하면 AI가 코드를 생성하고, 다시 개발자가 검증하는 방식입니다. 업무 방식이 변화하면서 Spring Modulith는 더 각광받고 있습니다.

Spring Modulith를 사용하면 AI에게 코드의 경계를 자연스럽게 알려 줄 수 있고, 작성된 잘못된 구조의 코드를 CI가 자동으로 감지할 수 있게 됩니다. AI 때문에 작성할 수 있는 코드의 상한선이 엄청나게 많아진 만큼 자동화된 구조 강제가 더 중요해졌습니다.

카카오뱅크에서도 이전에는 선택 사항이던 Spring Modulith의 사용이 앞으로 개발할 신규 시스템에는 필수적으로 포함된다고 합니다.

Java가 AI 통합에 최적인 이유

MCP 서버 및 Agent 개발에서 Node.js와 Python을 많이 사용하고 있지만, Java로 개발하는 것도 좋은 선택지로 보입니다. TM Dev Lab에 따르면 MCP 서버 구현 언어별 벤치마크에서 Latency 기준으로 Java가 두 언어보다 훨씬 성능이 좋고, 심지어 Go 언어보다도 더 좋은 수치를 기록했습니다.

Java는 Go와 함께 탑티어의 성능을 보여 주며, 동시에 Spring 생태계 통합 비용이 없다는 장점이 있습니다. 그래서 기존 Product가 Spring 기반이라면 Spring AI를 사용해서 Agent나 MCP 서버를 개발하는 것도 좋아 보입니다.

결론적으로 Virtual Threads로 더 단순한 코드를, Spring Modulith로 더 구조화된 아키텍처를, Spring AI로 기존 비즈니스 로직과 AI의 통합을 시도해 보자는 메시지를 전해 주었습니다.

이외에도 카카오뱅크에서 MCP 인증을 위해 사용하고 있는 mcp-security 라이브러리, Keycloak을 사용한 공통 IdP, GitHub Spec-kit을 소개해 주었습니다.


자율 에이전트를 활용한 AI 네이티브 자바 개발

AWS 테크 에반젤리스트인 최용호님이 발표한 세션입니다. 전반적으로 AI 활용 개발을 위한 AWS의 여러 도구를 설명해 주셨는데, 전달력이 좋아서 기억에 남는 세션이었습니다.

AI가 변화시킨 소프트웨어 개발과 KIRO

AI가 개발 현장과 소프트웨어를 많이 변화시키고 있습니다. 2024년에는 개발자의 코딩을 지원하는 어시스턴트, 2025년에는 사람은 질문을 하고 AI가 답하며 코드를 생성하는 에이전트, 2026년에는 End-to-end로 AI가 자율적으로 개발하고 필요시에만 사람이 개입하는 자율성으로 AI의 주요 키워드가 변화해 왔습니다.

AI의 아웃풋을 최대한 정확하게 받기 위해서는 모호한 프롬프트만 전달하는 것이 아니라 Spec을 정의해야 합니다. 그래서 요즘 추세는 Codex, Claude Code에서 /plan을 사용하여 계획이나 스펙을 먼저 정의하고 작업하는 것입니다. AWS의 IDE인 KIRO는 Spec-driven 개발을 통해 AI 코딩에 구조를 부여하고, 최상의 작업물을 도출할 수 있도록 도와줍니다.

많은 AI IDE와 마찬가지로 KIRO 역시 VS Code 기반으로 만들어졌기 때문에 디자인은 굉장히 친숙했습니다. 차이점은 Specs, Agent Hooks, Agent Steering, MCP Servers 등 Spec-driven 개발을 위한 사이드 탭 메뉴를 두어서 편의성을 높였다는 점입니다.

회사에서 AI 코딩 도구로 개발하기: AI-DLC

AI가 코드 생성 속도는 비약적으로 높여 줬지만, 실무 개발의 전체 사이클로 보면 10~15% 정도의 향상밖에 달성하지 못한다고 합니다. 개발자 개인의 생산성은 극대화되지만 설계, 분석, 테스트, 검증, 소통 등에는 AI 도구를 활용하지 못하고 있는 것이 주요 원인입니다. 이런 한계를 극복하기 위해 AI-DLC 개념이 등장했습니다.

기존의 SDLC에 AI를 사용하는 것이 아니라, AI를 중심으로 개발 프로세스를 새로 설계해야 합니다. 구현 단계에서만 AI를 사용하지 않고 계획, 구현, 테스트, 검증을 하나의 연속된 파이프라인으로 동작하게 해야 합니다. 그리고 AI가 개발을 보조하는 것이 아니라 개발을 하는 주체가 됩니다. 인간은 질문에 답변하고 리뷰 및 승인을 통해 판단, 결정, 책임만 담당하게 됩니다.

KIRO는 AI-DLC를 적용한 개발을 할 수 있도록 도와준다는 내용과 함께 시연을 보여 줬습니다. 이외에도 Kiro Web, AWS Security Agent, AWS DevOps Agent를 사용한 AI 네이티브 개발도 소개해 주었습니다. 그중에서 인상 깊었던 부분은 AWS Security Agent가 제공해 주는 선제적인 보안 기능들이었습니다. 침투 테스트도 제공해 주는데, 테스트 보고서도 상세하게 보여 주기 때문에 작은 회사에서 보안 쪽 인력이 부족하면 사용해 보는 것도 좋겠다고 생각했습니다.


Spring AI 개발, Harness로 10배 빠르게

이번 세션은 『하네스 엔지니어링 with 클로드 코드』의 저자 황민호님이 Claude Code를 활용한 Spring 하네스 구성에 대해 발표해 주셨습니다. 기존의 순차적 프롬프트 호출을 사용한 직렬화된 워크플로우 대신, Agent를 통해 조직화된 에이전트 팀 분업으로 생산성을 늘리는 것을 강조하며 기본적인 하네스 구성을 설명하는 시간이었습니다.

Claude Code Harness의 3대 핵심 구성 요소로는 다음 세 가지가 있습니다.

  • Agent: 역할과 전문 컨텍스트를 가진 AI 팀원
  • Skill: 재사용 가능한 작업 흐름
  • Orchestrator: 에이전트와 스킬을 연결, 조율하는 상위 컨트롤 타워

그리고 Spring과 하네스를 비교하는 멘탈 모델을 제시해 주었는데, 공감이 꽤 많이 되었습니다.

  • @Component = Agent
  • @Configuration + @Bean = Skill
  • @SpringBootApplication = Orchestrator
  • ApplicationEventPublisher = SendMessage (A2A 통신)

한 가지 아쉬웠던 부분은 조직 내에서 하네스 환경을 공유하고 유지보수하는 팁을 얻고 싶었는데, 해당 부분에 대한 답변은 들을 수 없었다는 점입니다. 민호님께서 현재 업무 프로세스에서는 협업이 필요 없기 때문에 아직 적용해 본 적 없다고 하셨습니다.


워크플로우 코드 왜 항상 복잡할까? - Temporal이 보여준 다른 방법

토스의 정승주님이 발표한 세션이었는데, 전달하고자 하는 바가 잘 와 닿았고 발표 준비를 열심히 하신 게 느껴졌습니다. 개인적으로 인상 깊었던 점은 Temporal이 단순히 함수를 재실행하는 것이 아니라, 비결정적인 행동을 분리하여 결과를 영속화하기 때문에 재시도를 하더라도 전체 워크플로우의 결과는 결정적으로 만들어 준다는 디테일이었습니다. 동일한 원리로 고비용 작업을 재사용할 수도 있습니다.

복잡한 워크플로우 코드

대부분의 워크플로우들은 비즈니스 로직에 관련된 문장만 본다면 단순하게 느껴집니다. 하지만 실제 운영 환경에서는 추가적인 요구 사항과 우발적인 문제 상황을 통제하기 위한 로직으로 흐름이 금방 복잡해집니다. 고객 보상 플로우를 예시로 들어보면 아래와 같습니다.

  • 비즈니스 로직
    • 고객 데이터를 수집하여 보상 금액을 평가하고 매니저 승인 후 크레딧 지급
  • 추가 요구 사항
    • 고객 데이터 수집
      • 병렬 호출
      • API별 재시도 정책
      • 5분 제한 시간
      • 고비용 로직 성공 시 결과 재사용
    • 승인 단계
      • 최대 7일 대기
      • 기간 만료 처리
      • 매니저 승인 신호 처리
    • 지급 단계
      • 장부 기록 & 고객 지급을 All or Nothing 처리
      • 실패 시 보상 트랜잭션

결국 비즈니스 로직 외에 재시도, timeout, 결과의 영속화, 타이머, 신호 처리, All or Nothing, 보상 같은 부가 기능이 계속 추가됩니다. 그래서 비즈니스 로직은 “수집 → 평가 → 승인 대기 → 지급”인데, 실제 코드에는 Task, Scheduler, Watcher, SignalAcceptor, TaskContextRepository, Saga, Compensation 같은 인프라성 코드가 추가됩니다.

Temporal이 워크플로우를 단순화시키는 방식

Temporal은 Temporal Server, Worker, Workflow, Activity라는 요소로 구성됩니다. 개발자는 Workflow에 “수집 → 평가 → 승인 대기 → 지급”이라는 흐름을 코드로 작성하고, 실제 API 호출이나 DB 조회처럼 비결정적인 작업은 Activity로 분리합니다. Activity의 결과, 타이머, 신호, 실행 상태를 Event History에 기록하고 필요할 때 워크플로우 코드를 다시 실행하면서 이전 결과를 재사용합니다. 그래서 Worker가 재시작되거나 함수 실행이 중단되어도 개발자 입장에서는 코드가 이어서 실행되는 것처럼 보입니다.

핵심 원리는 Durable Execution입니다. Temporal은 JVM 스택 자체를 저장하는 것이 아니라, 실행 중 발생한 이벤트를 Event History에 기록하고 워크플로우 코드를 다시 실행하면서 이전 결과를 Proxy를 통해 재사용합니다. 예를 들어 actA.foo()가 한 번 실행되어 결과가 기록되면, 워크플로우가 재실행될 때 실제 Activity를 다시 호출하지 않고 Event History에 저장된 결과를 반환합니다. 이 덕분에 함수가 종료되거나 Worker가 재시작되어도 개발자 입장에서는 멈췄던 지점에서 이어지는 것처럼 보입니다.


Is Java Alive and Kicking?

자바 챔피언 이희승님의 세션이었는데, 인사이트가 강하게 느껴지는 발표로 기억에 남습니다. 제가 생각하는 발표의 핵심 메시지는 “자바는 여전히 잘 살아 있지만 더 이상 당연한 선택지는 아니다.”라는 것이었습니다. 실제로 희승님도 요즘에는 Java로 개발을 자주 안 하시고 Go, Rust를 많이 사용한다고 하셔서 참가자들이 혼란스러워했던 기억도 납니다.

자바는 아직도 백엔드 프로젝트의 기본 선택지인가?

6개월 릴리즈 주기, Project Amber, Loom, Panama, Leyden, Valhalla 같은 현대화 프로젝트를 보면 오히려 꽤 활발하게 진화하고 있습니다. 언어 표현력은 좋아지고 있고, Virtual Thread를 통한 동시성 모델도 개선되었으며, Native Interop과 기동 성능을 다루려는 시도도 계속되고 있습니다. 그래서 자바는 아직도 죽지 않고 발전하고 있는 언어입니다. 다만 중요한 질문은 “아직도 모든 백엔드 프로젝트의 기본 선택지인가?”에 더 가깝습니다.

기술 지형

과거 Single-tenancy 환경에서 자바는 기술 지형에 잘 들어맞았습니다. 강력한 JVM의 런타임 최적화나 높은 처리량이라는 강점이 부각되고, 긴 기동 시간이나 JIT warm-up은 크게 문제가 되지 않았습니다. 하지만 지금은 컨테이너, Kubernetes, Serverless, Autoscaling, Multitenancy가 일반화되었습니다. 서비스는 자주 뜨고 내려가며 여러 워크로드가 같은 자원을 공유합니다. 이런 환경에서는 빠른 기동, 낮은 메모리 사용량, 예측 가능한 리소스 사용이 더 중요해졌습니다.

이 변화는 자바의 강점을 약점처럼 보이게 만듭니다. JVM은 풍부한 런타임 기능과 강력한 introspection을 제공하지만, 요즘은 OS 레벨 도구가 더 보편적인 관측 수단이 되고 있습니다. 또한 런타임에 처리하던 많은 작업이 빌드 타임으로 내려가는 흐름도 강해졌습니다. GraalVM이나 Leyden 같은 시도는 이 흐름에 대한 대응이지만, 빌드 비용, 트러블슈팅 난이도, 생태계 파편화, 여전히 무거운 런타임이라는 현실적 한계도 함께 존재합니다.

Tooling 측면에서도 자바는 도전받습니다. 전통적으로 개발 언어는 컴파일러와 표준 라이브러리에 집중하고, 나머지는 커뮤니티에 의존하는 미니멀 툴링 성향이 있었습니다. 하지만 현대의 개발 언어는 코딩 스타일, 정적 분석, 테스트, 의존성 관리, 빌드 시스템, 개발 환경 통합 등을 모두 제공하는 올인원 툴링 성향이 강합니다. 이런 측면에서 자바는 개발 환경의 파편화가 높은 편입니다.

이에 대한 대응 방향으로는 크게 두 가지가 있습니다. 코틀린, 스칼라처럼 자바를 두고 새로운 언어를 사용하는 것과 자바를 현대화하는 방향입니다. 그러나 어떤 방향이든 JVM 런타임의 짐은 그대로 존재하고 비용이 많이 들게 됩니다.

거버넌스

자바라는 언어로 이윤을 남기려다가 생긴 문제들이 존재합니다. JDK는 여러 개로 파편화되었고, 혼란스러운 라이선스 정책 등 부정적 신호들이 보입니다. 그리고 공식 웹사이트, 커뮤니티에 대한 관리가 미흡하다는 단점도 있습니다. 이런 문제들은 자바를 함께 돌볼 공유재가 아닌 통제하고 수익화할 자산으로 바라본 데에서 시작되었습니다.

마인드셰어

자바가 젊은 개발자들에게 배우고 싶은 언어인지 묻는다면 그렇다고 말하기 힘듭니다. 2024년 베를린 MERGE 컨퍼런스에서 자바로 신규 프로젝트를 진행하는 비율은 10% 이내였습니다. 그리고 JetBrains 2025 설문에 따르면 성장 잠재력 1~3위 언어는 TypeScript, Rust, Go로 자바는 속하지 못했습니다. 그리고 Haskell, Elixir처럼 열광적인 팬층도 적습니다. 당장은 괜찮지만 다음에 등장할 유니콘 기업에서 자바를 선택할지는 미지수입니다.

모든 문제에 자바를 먼저 대입하던 시대는 지나가고 있습니다. AI 시대에는 “내가 익숙한 기술인가?”보다 “현재 문제와 실행 환경에 가장 잘 맞는 기술인가?”를 기준으로 선택할 필요가 있습니다.


MSA 성능 튜닝 가이드

『마이크로서비스 아키텍처 구축 가이드』의 저자인 김용욱님의 세션으로, MSA 성능 튜닝에 대한 발표를 해주셨습니다. 주니어를 대상으로 준비하신 강의였지만 실무에서 만날 수 있는 여러 케이스를 예시로 설명해 주신 점이 좋았습니다.

MSA를 도입하면 서비스가 작게 나뉘고 각 서비스의 책임이 명확해진다는 장점이 있습니다. 하지만 서비스가 나뉘는 순간, 기존에는 메서드 호출이나 DB 조회로 끝나던 작업이 서비스 간 API 호출로 바뀌게 됩니다. 이때 호출 횟수와 호출 구조를 제대로 관리하지 않으면, MSA는 유연한 구조가 아니라 지연 시간과 장애 전파를 키우는 구조가 될 수 있습니다. 발표에서는 MSA의 성능 저하 원인을 크게 세 가지로 정리하고 있습니다.

비효율적인 서비스 구조

특정 서비스가 여러 서비스의 공통 조회 지점이 되면 호출이 집중되고, 그 서비스가 느려지거나 장애가 발생했을 때 전체 시스템에 영향이 전파될 수 있습니다. 기준정보나 마스터 정보처럼 여러 서비스에서 반복적으로 조회하는 데이터는 무조건 별도 서비스로 분리하는 것이 답이 아닐 수 있습니다. 경우에 따라 기능을 각 도메인 서비스로 재배치하거나, 읽기 전용 데이터를 이벤트나 배치를 통해 복제하는 방식이 더 적합할 수 있습니다.

비효율적인 코드

목록 조회에서 단건 조회 로직을 반복 재사용하는 방식은 API N+1 문제를 만들기 쉽습니다. 예를 들어 상품 목록을 조회한 뒤 각 상품마다 판매자 정보나 조직 정보를 개별 API로 조회하면, 상품 수만큼 원격 호출이 발생하게 됩니다. 코드 재사용 관점에서는 깔끔해 보일 수 있지만, 런타임 관점에서는 매우 비싼 구조입니다. 이런 경우에는 먼저 필요한 ID를 모으고 대상 서비스에 Bulk API로 한 번에 조회한 뒤 애플리케이션 메모리에서 조합하는 방식이 더 적절합니다.

같은 데이터의 반복 조회

모든 데이터가 매번 원천 서비스나 DB에서 조회되어야 하는 것은 아닙니다. 비밀키처럼 거의 변하지 않는 데이터, 공통코드처럼 실질적으로 자주 변경되지 않는 데이터, 날씨 정보처럼 조금 늦게 봐도 되는 데이터, 상품 정보처럼 특정 시점 이후 변경되지 않는 데이터는 캐싱이나 복제의 후보가 될 수 있습니다. 특히 로컬 캐시는 인스턴스별 정합성 이슈를 고려해야 하지만, 네트워크 호출 없이 메모리에서 바로 읽을 수 있기 때문에 매우 빠른 조회가 필요한 경우 강력한 선택지가 될 수 있습니다.

추가적으로 보통 캐시를 사용할 때 무조건 Redis 등 공유 캐시를 사용하려는 사람들에 대한 주의도 주셨습니다. 공유 캐시는 단일 장애 지점이 될 수 있기 때문에 필요할 때에만 문제가 발생하지 않는 방식으로 설계해서 사용하라고 당부했습니다.

결국 MSA 성능 튜닝의 핵심은 “서버를 얼마나 늘릴 것인가”보다 “불필요한 호출을 얼마나 줄일 수 있는가”에 가깝습니다. 서비스 간 호출이 많아질수록 latency는 누적되고, 부하는 특정 서비스에 집중되며, 장애는 더 쉽게 전파됩니다. 따라서 MSA에서는 서비스 분리 자체보다 분리된 서비스들이 서로를 어떻게 덜 호출하게 만들 것인지가 중요합니다. 구조적으로 호출이 많아지는 부분은 기능과 데이터를 재배치하고, 코드상 반복 호출은 Bulk 조회로 개선하며, 반복 조회되는 데이터는 캐싱 또는 복제로 처리해야 합니다. 좋은 MSA는 단순히 서비스를 잘게 나눈 구조가 아니라, 나뉜 서비스들이 불필요하게 서로를 호출하지 않아도 안정적으로 동작하는 구조라고 볼 수 있습니다.


3년 만에 참여한 Spring Camp였는데 확실히 세미나 주제들이 많이 변경된 것을 느꼈습니다. 이전에는 DDD, MSA 등 설계나 아키텍처 패턴이 주를 이루었고 대규모 트래픽 환경의 이슈 처리에 관련된 세션이 많았다면, 이번에는 AI에 관련된 주제가 가장 큰 비중을 차지했습니다. 이전에 갔던 그라파나 밋업에서도 SRE 분야에서 AI를 활용하는 방법이 주를 이루었는데, 이 흐름은 당분간 계속될 것 같습니다.

지난번 구글 슬리퍼에 이어서 이번에도 AWS Builder 자켓에 당첨됐습니다. 오랜만에 성장을 위한 좋은 자극도 받고 굿즈까지 챙겨올 수 있는 유익한 시간이었습니다. 다음 Spring Camp도 당첨돼서 참여할 수 있길..!!

댓글남기기