전체 글 181

Spring AI 학습 기록: Tool Calling으로 AI가 실제 데이터를 근거로 답하게 만들기

지금까지 만든 API는 리뷰를 꽤 잘 요약한다.그런데 사용자가 "이 상품 재고 있어?" 라고 물으면 제대로 답하지 못한다. 모른다고 말하면 그나마 다행이고, 그럴듯하게 지어내면 더 큰 문제가 된다.이번 글에서는 AI가 우리 시스템의 실제 데이터를 근거로 답하게 만드는 방법인 Tool Calling을 정리했다.개념 훑어보기1. Tool Calling = "상담원의 내부 시스템 조회 요청"AI가 "이 함수 좀 불러줘"라고 우리 앱에 요청하는 것이다.비유: 콜센터 상담원고객이 "제 주문 어떻게 됐어요?"라고 물으면, 상담원은 답을 지어내지 않고 내부 시스템 조회를 요청한다.조회 결과를 확인한 다음에 고객에게 답한다.여기서 중요한 건 상담원(AI)은 요청만 하고, 실제로 시스템을 조회하는 건 우리 앱이라는 점이..

Kafka 브로커 한 대를 중지하면? 리더 전환과 ISR 변화 관찰하기

Kafka는 데이터를 여러 브로커에 복제해 장애에 대비한다.그렇다면 실제로 브로커 한 대를 중지했을 때, 파티션과 복제본에는 어떤 변화가 발생하는지에 대해 실습을 해보기로 했다. 브로커 3대로 구성한 Kafka 환경에서 kafka-1을 중지하고, Kafka UI에 표시되는 order 토픽의 상태를 비교했다. 먼저 이번에 중지한 대상은 브로커 1이다.브로커는 파티션의 복제본을 저장하는 서버이며, 하나의 브로커에 여러 파티션의 복제본이 함께 존재한다.이번 환경에서도 브로커 1은 파티션 0·1·2의 복제본을 모두 가지고 있었다. 따라서 브로커 하나를 중지했지만 세 파티션 모두 영향을 받았다.1. 중지 전: 모든 복제본이 정상적으로 동기화된 상태order 토픽은 다음과 같이 구성되어 있었다.Number of P..

개발공부/Kafka 2026.09.25

Kafka가 필요한 이유와 핵심 개념 정리

기존 구조의 한계지금까지 배운 내용으로 기반으로 한 서버는 다음과 같은 구조였다.사용자 요청 → 서버 → DB/Redis 저장 / 조회이 구조는 평소에는 문제가 없지만, 트래픽이 갑자기 증가하면 세 가지 문제가 동시에 터진다.서버는 모든 요청을 "즉시" 처리해야 한다.요청량이 갑자기 증가해도 서버는 쉬지 않고 모든 요청을 즉시 처리해야 한다. 서버가 감당할 수 있는 범위를 넘어서면 장애로 이어진다.DB와 Redis는 동시에 많은 요청을 처리하지 못한다.트래픽 폭증은 다음과 같은 상황에서 자주 발생한다.대규모 세일 오픈인기 상품 재입고쇼핑몰 메인 배너 클릭 급증사용자 행동 데이터는 매우 빠르게 쌓인다.페이지 조회, 상품 클릭, 장바구니 추가, 구매, 스크롤 등 사용자 행동 로그는 실시간으로 쌓인다. 이 모..

개발공부/Kafka 2026.09.24

[Design]리프레시 토큰: 로테이션과 재사용 탐지를 선택한 이유

상황지금까지는 액세스 토큰 하나만으로 로그인을 구현했다.로그인에 성공하면 액세스 토큰을 발급하고, 이후 요청마다 그 토큰을 검증하는 단순한 구조였다.여기서 한 단계 업그레이드하고 싶어서 리프레시 토큰 도입을 알아보기 시작했다.그런데 찾아보다 보니, 리프레시 토큰을 붙이는 것 자체도 완전한 해법은 아니라는 이야기가 계속 나왔다. 리프레시 토큰이 탈취되면 액세스 토큰보다 훨씬 오래 살아있는 만큼 피해가 더 크고, 단순히 리프레시 토큰만 추가한다고 보안이 저절로 좋아지는 게 아니었다. 그래서 어떤 방식들이 있는지, 그리고 그 중 실무에서 실제로 쓰이는 조합이 뭔지 정리해보기로 했다.어떤 대안들이 있나?먼저 토큰 기반 인증에서 무엇을 절충해야 하는지 정리했다.JWT는 서버가 별도 저장소를 조회하지 않고도 서명과..

[Design]BCrypt 72바이트 제한: 비밀번호 검증이 바이트 단위여야 하는 이유

상황회원가입 로직은 비교적 간단하다고 생각이 들어서 후순위로 밀리기 쉬운 코드다.로그인, 비밀번호 찾기에 비하면 화려할 것도 없고, 이메일 형식과 비밀번호 길이 정도만 확인하면 끝이라고 생각하기 쉽다.그런데 비밀번호 필드 하나를 조금만 파고들면, 프레임워크 내부 동작과 실제 CVE까지 이어지는 이야기가 나온다는 사실을 알게 되었다.세 번째 줄, @Utf8ByteLength(max = 72)가 이 글의 주제이다.처음 봤을 땐 "회원가입 하나에 커스텀 어노테이션까지 굳이"라는 생각이 들기도 했지만... 파고들수록, 과한 설계가 아니라 정확히 필요한 만큼의 설계라는 생각이 들었다.72바이트라는 숫자의 정체는?72는 임의로 정한 값이 아니다.비밀번호 해싱에 흔히 쓰이는 BCrypt 알고리즘 자체가 입력을 72바..

Spring AI 학습 기록: Spring AI Advisor 이해하기

개념 훑어보기AI를 우리 서비스에 그냥 연결해서 사용만 한다면 문제가 생긴다.AI 한 번 부를 때마다 돈이 나간다.(택시 미터기처럼)AI는 기억력이 없어서 방금 한 말도 다음 질문 때 까먹는다.누군가 위험한 내용이나 불건전한 질문을 할 수도 있다.오늘 글에서는 이 3가지 문제를 "공통으로 처리하는 장치"에 대해서 알아볼 것이다. 1. Advisor = "검문소"AI에게 질문을 보내기 전과, AI가 답을 보내온 후, 그 사이에 공통으로 껴서 뭔가를 처리하는 장치비유: 공항 출입국 심사대나갈 때(before): 가방 검사 (위험한 거 없는지, 짐 무게는 얼마인지)들어올 때(after): 세관 신고 (뭘 사왔는지 기록)왜 필요한가? 만약 이 검문소가 없으면, 개발자가 "이 비용 계산 코드"를 AI 부르는 곳마..

개발공부/SPRING 2026.09.18

Spring AI 학습 기록: AI의 답변을 자바 객체로 받아서 활용하기

AI에게 상품 리뷰를 요약해 달라고 하면 꽤 자연스러운 설명이 돌아온다. 그런데 쇼핑몰의 실제 화면을 생각해보면 조금 더 다채롭고 정확한 기능들이 필요하다.예를 들면 요약 문장은 상단에, 장점은 작은 태그로, 주의할 점 등등이 있다.하나의 긴 답변에서 이 내용을 매번 잘라내려면 오히려 추가 작업이 많아질 것 같았다.이번에는 이 문제를 1차적으로 해결하는 구조화 응답을 공부했다. 화면에 필요한 데이터부터 생각해 보기텀블러 리뷰를 분석한다고 가정해 보면“손잡이가 있어 들기 편하지만 가방에 넣고 다니기에는 다소 무겁다는 의견이 있습니다.”이 문장은 사람이 읽기에는 충분하다. 하지만 화면에 장점만 표시하려면 ‘들기 편하다’는 부분을 따로 찾아야 한다.표현이 ‘휴대하기 좋다’로 바뀌면 단순한 문자열 분리만으로 처..

개발공부/SPRING 2026.09.16

Docker란? 왜 필요한지부터 VM 차이, 이미지·컨테이너·볼륨

Spring Boot 프로젝트를 만들었다면 내 컴퓨터에서는 IntelliJ의 실행 버튼만 눌러도 서버가 동작한다.그런데 이 프로젝트를 팀원의 컴퓨터나 배포 서버로 옮기면Java를 설치하고, 버전을 확인하고, MySQL을 준비하고, 실행에 필요한 설정도 맞춰야 한다.소스 코드는 Git으로 공유했지만, 그 코드를 실행할 환경까지 전달한 것은 아니기 때문이다.Docker를 이해하는 출발점은 여기에 있다. “코드뿐 아니라, 코드를 실행하는 환경도 함께 준비해서 전달할 수 없을까?”Git으로 같은 코드를 받았는데 왜 실행 결과가 다를까?쇼핑몰 프로젝트를 함께 개발한다고 가정해 보자. 모두 같은 코드를 내려받았지만, 각자의 컴퓨터 상태는 다를 수 있다.구분개발자 A개발자 BJava프로젝트에 맞는 버전다른 프로젝트에..

개발공부/Docker 2026.09.15

Spring AI 학습 기록: Spring AI 리뷰 요약 API 구현 흐름

Spring AI를 이용하면 여러 상품 리뷰를 전달하고, 고객이 읽기 쉬운 하나의 문단으로 요약하는 기능을 구현할 수 있다.이번 학습의 목적은 단순히 OpenAI API를 한 번 호출해 보는 것이 아니다. 애플리케이션 내부에서 AI 호출을 어떤 계층에 배치하고, 공통 지시사항과 요청별 데이터를 어떻게 분리해야 하는지 이해하는 데 있다.1. 의존성 추가하기ext['springAiVersion'] = '2.0.1'dependencyManagement { imports { mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}" }}dependencies { implementation 'org.springframework...

개발공부/SPRING 2026.09.14

STOMP 채팅에 Redis Pub/Sub은 왜 필요할까? 단일 서버부터 다중 서버까지 이해하기

채팅 서버를 스케일 아웃했을 때 발생하는 메세지 전달 문제를 해결하는 방법 중 필요한 개념이 Redis Pub/Sub라는 것을 알게 되었다. Publisher가 Channel에 메시지를 발행하면 해당 Channel을 구독한 모든 Subscriber가 메시지를 받는다.하지만 STOMP에서도 이미 SUBSCRIBE와 메시지 전송을 사용하고 있기 때문에 다음과 같은 의문이 생긴다.STOMP도 구독이고 Redis도 구독이라면 둘은 무엇이 다른가?결론부터 말하면 두 기술은 서로 다른 구간을 담당한다.STOMP는 사용자와 Spring 서버 사이에서 메시지를 주고받기 위한 규칙이다.Redis Pub/Sub은 여러 Spring 서버가 메시지를 공유하기 위한 통신 방식이다.Redis Pub/Sub은 STOMP를 사용하기..

개발공부/WEB 2026.09.11