인생 첫 컨퍼런스. 2025 우아콘 후기

Frog Lemon·2025년 10월 29일
8

우아한테크코스

목록 보기
4/4
post-thumbnail

2025년 10월 28일에 개최된 배달의 민족 기술 공유 행사인 '우아한테크컨퍼런스'에 다녀왔다.
개발자로 전향하고 한번쯤은 개발자 컨퍼런스를 경험해보고 싶었고, 타 컨퍼런스에 몇번 신청하긴 했지만 선정되진 않았었다.
이번에도 우테코 및 공식 홈페이지 추첨에서 떨어졌으나 3기 선배 '티케'의 배려로 참여할 수 있었다 (다시 한번 감사합니다😊) .

우아한테크코스의 커리큘럼에 녹아있는 교육 철학처럼 이번 경험을 통해 얻은 지식과 깨달음을 혼자 가져가는 것이 아닌 모두와 함께 공유하여 더불어 성장하고자 되도록 꼼꼼히 글을 작성했다.

우아콘은 백엔드, 프론트엔드, 모바일 앱, PM, 인프라, AI, 로봇, 데이터 등 시간대별로 다양한 세션들이 준비되어 있었고 원하는 시간에 맞춰 해당 세션에 참여하여 발표를 들었다.

이런 행사가 처음이라 들뜬 마음을 감추지 못한채 준비되어 있는 다양한 체험을 먼저 해버렸다. 원래 혼자 사진을 절대 절대 안찍는데 우아네컷의 상품이 너무나 궁금하여 저질러버렸다... (사진도 2장이 나와버려서 매우 곤란했다.)

나는 아래의 5개의 세션을 들었고, 발표 내용을 클로바 노트로 기록하였다. 기록한 내용들을 보기 쉽게 요약하여 보여주고, 추가적으로 나의 생각을 써보려고한다.

💡 들었던 세션 목록

1. AI 네이티브 회사를 향항 새로운 항해
2. 글로벌 타킷팅 서비스, 수억 명의 고객을 향한 도전
3. 더 나은 이상 탐지를 위한 여정: 서버부터 서비스, 그리고 문화 까지
4. ServerSentEvents로 실시간 알림 전송하기
5. BROS 레거시 스파게티 코드 개선
6. RAG, 들어는 봤는데... 내 서비스엔 어떻게 쓰지?


AI 네이티브 회사를 향항 새로운 항해

LLM, AI Agent, MCP...
요즘 개발자라면 대부분 어떤식으로든 AI를 활용한다고 생각한다.
이번 세션에서는 배달의 민족에서 AI를 도입했던 경험을 다룬다.

1️⃣ AI 생산성 기대와 초기 충격

AI 기술이 본격적으로 확산되면서, AI를 잘 활용하는 방법을 다룬 콘텐츠들도 쏟아졌고, 이를 보며 “곧 AI 시대가 온다”는 기대감과 동시에
“이 변화 속에서 뒤처지지 않으려면 어떻게 생산성을 높여야 할까” 하는 고민이 함께 생겼다.

이 주제는 단지 최근의 화두가 아니라, 오래전부터 사람들이 꾸준히 고민해온 생산성의 본질적 문제라고 생각한다.

2️⃣ 우아한형제들의 빠른 AI 도입과 변화

이런 상황 속에서 우아한형제들은 비교적 이른 시기에 AI 솔루션을 도입했다.
특히 GitHub Copilot을 빠르게 적용하면서, 개발자들이 “코딩이 더 편해졌다”, “생산성이 확실히 올라갔다”는 긍정적인 피드백을 많이 남겼다.

그럼에도 불구하고 코드리뷰, 자동화, 테스트등에서 불편한 점들이 존재했고, AI의 발전에도 해당 문제들은 해결되지 않았다.

3️⃣ 한계와 현실적 문제 인식

AI 도입 이후에도 활용 편차가 매우 컸다.
잘 쓰는 사람과 그렇지 않은 사람의 격차가 뚜렷했고,
일부는 “AI를 안 쓰면 뒤처진다”는 압박감 속에서 억지로 사용하는 모습도 보였다.

결국 내부적으로는 “해외에서는 AI가 생산성을 폭발적으로 높였다는데,
왜 우리는 그렇지 못한가?”라는 의문이 제기되었다.

4️⃣ 개선 방향: 검증과 반복의 루프

이런 문제를 단순히 “AI는 효과가 없다”로 결론내릴 수는 없었다.
그래서 AI 도입을 검증하고 개선하는 구조적 접근이 필요하다고 판단했다.

우리는 “리뷰 → PoC → 플랜”의 짧은 루프를 반복하는 전략을 세웠다.

  • 리뷰(Review): 현재 상황과 결과물을 점검하고, 산출물이 실제로 가치가 있는지 평가

  • PoC(Proof of Concept): 개념 검증을 통해 기술적 가능성과 효용성 확인

  • 플랜(Plan): 검증된 결과를 바탕으로 실행 계획을 구체화

이 과정을 통해 추측이 아닌 데이터 기반의 개선을 추진하기로 했다.

5️⃣ 현재 위치와 AI 발전 단계 인식

OpenAI가 제시한 AI 발전 5단계 모델을 기준으로 보면,
현재는 3단계 ‘에이전트(Agent) 시대’에 해당한다.

1단계: 단순한 대화 수행
2단계: 데이터 기반 조언과 추론 가능
3단계: 사용자를 대신해 독립적으로 작업 수행
4단계: 문제를 스스로 정의하고 혁신적 해결 시도
5단계: 완전한 자율적 지능

현재는 3단계, 즉 ‘에이전트가 실제 업무를 수행할 수 있는 단계’에 진입했다고 판단된다.
따라서 앞으로의 과제는 독립적으로 업무를 처리할 수 있는 AI 에이전트를 어떻게 만들 것인가에 집중되어야 한다.

발표자는 이 AI 모델을 2차 산업혁명의 엔진에 비유한다.
무한한 가능성을 지녔지만, 효율·내구성·비용의 균형이 핵심이다.
이 모델을 어떻게 설계하고 적용하느냐에 따라 AI의 실제 생산성 향상 효과가 결정될 것이다.

🧐 세션 후기

AI 트렌드인 Agent와 MCP에 관심이 많아 꾸준히 따라가려고 노력중이다. 그러나 학습을 거듭할수록 하나의 의문이 생겼다.
“과연 우리는 AI에게 전적으로 의존할 수 있을까?”

개인적으로 현재의 AI 열풍에는 일정 부분 ‘버블’이 존재한다고 생각한다.
빅테크 기업들이 가장 먼저 AI를 도입하며 생산성과 편의성을 높이고 있지만, 그만큼 새로운 위험도 함께 커지고 있다.
예를 들어, 잘못된 데이터를 학습시키는 휴먼 에러, 외부에서 의도적으로 조작된 악의적 학습, 그리고 그로 인한 결과 왜곡의 가능성은 여전히 남아 있다.

결국 AI는 스스로 학습하고 판단하는 시스템이기에, 언제나 오판의 위험을 내포한다.
따라서 우리는 “AI의 활용”뿐 아니라 “AI의 한계와 검증”에도 동일한 관심을 가져야 한다고 생각한다.


글로벌 타킷팅 서비스, 수억 명의 고객을 향한 도전

우아한 형제들에서 사용하는 타켓팅 서비스인 버즈가 글로벌 서비스로 확장하면서 선택한 기술들과 코드부터 인프라까지 어떤 변경 사항들이 있었는지에 대한 내용으로 진행되었던 세션이다.

1️⃣ 타겟팅 서비스란 무엇인가

버즈(Buzz)’는 배민의 유저 데이터를 기반으로 맞춤형 마케팅을 지원하는 타겟팅 시스템이다.
이 시스템의 핵심은 모든 유저에게 동일한 메시지를 보내는 대신, 필요한 사람에게 필요한 쿠폰과 정보를 제공하는 것이다.

타겟팅은 ‘세그먼트(Segment)’라는 개념으로 운영된다.
예를 들어, “20대 여성 중 최근 1주일 내 신한카드로 결제한 포항 거주자” 같은 조건이 세그먼트를 구성한다.
이 조건 기반의 고객 그룹을 빠르게 분석하기 위해, 오픈서치(OpenSearch) 가 핵심 데이터베이스로 활용된다.

💡오픈서치란?

오픈서치는 빠른 검색·집계, 스키마리스 JSON 저장, 쿼리 DSL 지원, 샤드 기반 확장성 등으로
수억 건의 고객 데이터를 1초 이내로 조회할 수 있게 한다.

2️⃣ 데이터 수집과 세그먼트 활용 구조

고객 속성 데이터는 매일 파이프라인을 통해 업데이트된다.
예를 들어, 마케터가 “생일 고객에게 쿠폰을 발행하고 싶다”고 요청하면,
데이터 엔지니어는 회원 DB에서 생일 정보를 추출해 데이터 웨어하우스로 복제하고,
버즈 시스템이 이를 집계해 오픈서치에 적재한다.

이 데이터는 푸시 액션(쿠폰, 알림)이나 퍼스널라이제이션(개인화된 배너 노출)에 활용된다.

💡 데이터 웨어하우스란?

데이터 웨어하우스는 다양한 소스에서 가져온 데이터를 통합하고 정리하여 저장하는 시스템으로, 비즈니스 인텔리전스, 보고, 분석을 통해 기업의 의사결정을 지원하는 데이터 저장소이다. 현재 운영 데이터와 분리된 독립적인 공간으로, 과거 데이터를 분석하고 추세를 파악하는 데 사용된다.

💡퍼스널라이제이션이란?

소비자 개인의 취향, 관심사, 구매이력, 나이등으로 특정 고객에게 정교한 맞춤형으로 제공하는 것

3️⃣ 글로벌 확장과 기술적 도전

버즈는 글로벌 버전인 세그멘텀(Segmentum) 으로 확장되며 70개국, 약 1.5억 명의 고객을 대상으로 서비스가 운영되고 있다.

확장 과정에서 직면한 주요 과제는 네 가지였다:

  • 낮은 API 레이턴시 (P95: 60ms, P99: 80ms 이하)
  • 수억 명 단위 데이터 스케일
  • 높은 TPS(초당 요청 처리)
  • 비용 효율성

4️⃣ 배포 전략 결정: 리전 단위 분산

초기에는 중앙집중형 배포(아시아 단일 리전) 방식을 고려했으나, 거리로 인한 레이턴시와 장애 전파 문제가 발생했다.

반면, 70개국 개별 배포는 비용과 운영 복잡도가 너무 높았다.

결론적으로, 4개 주요 리전(한국 포함) 에 리전 단위 배포를 진행하여 성능과 운영 효율의 균형을 맞췄다.

5️⃣ 데이터베이스 선택: DynamoDB 중심 아키텍처

1억 명 고객 × 1만 세그먼트 = 1천억 관계 데이터라는 규모에서
데이터 저장 효율성과 비용을 모두 고려해야 했다.
후보로는 Redis, DynamoDB, Cassandra를 검토했고, 확장성·일관성·운영 효율성을 이유로 DynamoDB를 선택했다.

<비용 최적화 전략>

  • 세그먼트 CDC를 통한 변경분만 업데이트

  • DynamoDB TTL로 만료된 데이터 자동 삭제 (비용 청구 없음)

  • 이 방식으로 일일 데이터 업데이트 비용을 대폭 절감했다.

6️⃣ 성능 최적화: 빠르고 안정적인 응답

아래는 버즈 서비스 팀에서 성능 최적화를 방법들이다.

1. 카페인 캐시(Caffeine Cache)

  • 메타데이터를 로컬 캐시로 관리해 DB I/O 최소화

2. 커넥션 풀 및 Keep-Alive 설정

  • 초기 핸드셰이크 비용 제거, 연결 재사용

3. Fail-Fast 전략

  • 지연이 발생하면 빠르게 실패 후 재시도 (테일 레이턴시 개선)

4. Request Hedging

  • 동일 요청을 두 번 보내 빠른 응답을 선택해 안정성 확보

결과적으로, 글로벌 환경에서 P95: 10ms / P99: 20ms 수준의 성능을 달성했다.

7️⃣ 글로벌 운영 후기와 교훈

글로벌 운영을 하면서 버즈 서비스 팀은 여러가지를 배웠다고 한다. 발표만 들었는데도 너무나 방대한 영역이었기에 얼마나 노력하셨는지 감도 오지 않았다.

어려움

  • 기술 부채를 일시적으로 상환해야 하는 고통 (3개월 이상 소요)

  • 버즈/세그멘텀 간 기술 스택 차이로 인한 복잡성

  • DH는 독일에 있기에 한국과는 시차가 7시간이 난다. 또한 언어·문화적 장벽이 존재하였다.

얻은 교훈

  • 확장 가능한 아키텍처 설계의 중요성

  • 기술 도입의 명확한 기준 필요성

  • 글로벌 협업에서의 신뢰와 원팀 문화의 가치

🧐 세션 후기

사용자 규모를 들었을 때 가장 먼저 떠오른 감정은 “1억 5천만 명이 사용하는 서비스에 대한 경외심”이었다.

모잇지 서비스를 개발하며 수백 명의 트래픽만으로도 성능과 안정성을 고민했던 입장에서, 이 수치는 단순한 숫자가 아니라 ‘설계 철학의 깊이 차이’로 느껴졌다.

다만 아직 주니어 개발자 준비생으로서 대규모 트래픽 환경을 직접 경험해보지 못했다는 점에서,
이런 감정은 어쩌면 당연한 것일지도 모른다.


더 나은 이상 탐지를 위한 여정: 서버부터 서비스, 그리고 문화 까지

이번 세션을 통해 처음으로 SRE(Site Reliability Engineering) 팀의 존재를 알게 되었다.
사실 ‘SRE’라는 용어조차 이번에 처음 들었다.
하지만 이번 세션을 들으면서 그들이 얼마나 중요한 역할을 하는지, 내가 과거에 경험했던 단순한 로그 수집이나 모니터링 작업이,SRE의 관점에서 체계적으로 확장되면 어떤 수준의 관리로 발전할 수 있는지 구체적으로 이해할 수 있었다.

1️⃣ SRE란 무엇인가

SRE(Site Reliability Engineering)는 시스템 신뢰성을 보장하기 위한 기술·문화적 접근 방식이다. 회사마다 약간씩 SRE에 대한 정의가 다르기에 우아한 형제들을 기준으로 설명하겠다.

우아한형제들에서는 SRE를 다음과 같은 네 가지 영역으로 정의하고 있다:

1. 관찰 가능성 확보

  • 로그·메트릭·트레이싱 등으로 서비스 상태를 실시간 파악

2. 이상 탐지 및 경보 체계 구축

  • 장애 전조를 조기에 인지

3. 장애 대응 정책 및 전파 프로세스 설계

4. 후속 조치 및 재발 방지 관리

이러한 체계를 통해 서비스 신뢰성을 높이고, 장애 발생 시 복구 시간을 최소화하는 것을 목표로 한다.

2️⃣ 왜 이상 탐지가 중요한가

배달의민족 서비스에서 장애는 곧 사용자 경험 저하와 매출 손실로 이어진다.
완벽한 장애 예방은 불가능하며, 빠른 감지와 대응 속도가 핵심 경쟁력이다.
따라서 SRE팀은 “장애를 없애는 것보다, 빠르게 복구하는 체계”에 집중하고 있다.

3️⃣ 초기 접근: 전사 경보 시스템

과거 배달의 민족에서는 각 팀이 독립적으로 모니터링을 운영했기 때문에 아래와 같은 문제점이 있었다.

  • 모니터링 사각지대 발생

  • 경보 기준 불일치

  • 담당자 부재 시 대응 지연

이를 해결하기 위해 중앙 통합 경보 시스템을 구축했다.

  • 핵심 지표(트래픽, 오류율, 응답 시간 등)를 표준화

  • 전사 공통의 알림 기준 수립

  • 운영자 개입 없이 자동화된 경보 발송

이 과정을 통해 운영 문화의 일원화그레이존 축소라는 효과를 얻었다.

4️⃣ 서비스 이상 탐지 시스템 기획

SRE팀은 단순한 인프라 수준의 모니터링을 넘어, 서비스가 정상적으로 동작하고 있는지를 판단할 수 있는 상위 레벨의 모니터링 시스템이 필요하다고 보았다.

여기서 말하는 ‘서비스 지표’는 CPU, 메모리, 네트워크와 같은 시스템 리소스 지표가 아니라
비즈니스 지표, 즉 서비스의 성능품질을 나타내는 지표를 의미한다.

예를 들어, 서비스가 정상적으로 작동한다면 특정 주문 건수나 결제 성공률 등이 일정한 패턴을 유지해야 한다.
하지만 서비스의 ‘정상 상태’에는 정답이 없다.
비즈니스 환경은 끊임없이 변화하며, 외부 요인(이벤트, 날씨, 트래픽 변화 등)에 따라 지표도 달라지기 때문이다.

5️⃣ 장애 탐지 및 대응 프로세스

우아한형제들 SRE팀은 서비스 장애 탐지를 위해 중앙값 기반의 예측값과 실시간 데이터를 비교하여 편차임계치에 도달하면 경보를 발생시키는 전략을 도입했다.

이를 통해 불필요한 오탐(False Positive)을 최소화하고,
이상 상황을 신속히 감지하여 장애 대응 속도를 대폭 단축할 수 있었다.

6️⃣ 서비스 조직과의 협업

이 시스템은 SRE팀 단독이 아닌, 서비스 조직과의 공동 설계를 통해 완성되었다.

기존 문제

  • 조직별 지표·경보 기준이 상이

  • 전사적 장애 현황 파악 불가

  • 경보 의미 불명확, 대응 절차 비일관적

해결 방향

  • 표준화된 서비스 지표 정의

  • 통일된 경보 포맷 및 대응 프로세스 적용

  • 조직별 맞춤 인터뷰 및 협업 설계
    → “획일화가 아닌, 비즈니스에 맞춘 표준화”

7️⃣ 성과와 배운 점

  1. 완벽보다 실행 우선 빠르게 시도하고 빠르게 실패해야 개선이 가능하다.

  2. 유저 중심의 지표 선정 CPU·메모리보다 사용자의 액션을 반영한 지표가 효과적이다.

  3. 공동의 목표 설정 SRE와 서비스 조직이 각자의 역할에 집중해야 시너지가 난다.

🧐 세션 후기

우선 발표자분의 한 말씀이 굉장히 인상적이었다.

장애를 근본적으로 방지하는 것은 불가능에 가깝다.사실 아무것도 안 하면 장애는 거의 발생하지 않는다.
근데 이제 회사는 계속 일을 해야 되고 더 나은 서비스를 만들어야 되기 때문에 변화가 계속 있고 이런 변화가 있는 한 장애는 피할 수가 없다.
그래서 이렇게 장애가 필연적이라면은 결국 서비스를 좀 빠르게 복구하는 데 집중을 해야 되겠죠.

이 말이 이번 세션의 핵심을 가장 잘 설명한다고 느꼈다.
SRE의 본질은 장애 ‘예방’이 아니라 장애 ‘복구 능력’을 체계화하여 장애 복구 시간을 최소화 시키는것이라고 생각하고 우리가 지향해야할 부분이라고 생각한다.


ServerSentEvents로 실시간 알림 전송하기

이 세션은 기대를 했고, 열심히 따라가려고 노력했지만 아쉽게도 잘 이해가 되지 않았다... 내가 SSE를 경험해봤다면 도움이 되겠지만, 기본 지식이 없는 상태에서 듣다보니 머릿속에 남은 것이 적었다.😢

이번 세션은 추후 SSE를 사용하게 될 날을 기약하며 단순히 발표내용을 정리하는것으로 마무리 하려고한다.

💡이 세션은 기록된 내용을 가독성을 향상 시키는데 집중하였습니다. 잘못된 부분이 있다면 댓글에 기재해주면 감사하겠습니다.

들어가며

주문 접수 채널 팀에서는 수십만 파트너들이 주문을 쉽고 빠르게 처리할 수 있도록 PC 앱, 안드로이드 키오스크 등 다양한 프로그램을 개발하고 있다. 식당에서 들리는 주문 알림음, 그 시스템을 어떻게 개선했는지 이야기해보겠다.

1️⃣기존 MQTT 알림 시스템

기존 시스템은 MQTT 브로커를 통해 알림을 전송했다. 클라이언트가 MQTT에 연결하여 토픽을 구독하면, 도메인 서버에서 변경 사항 발생 시 메시지를 발행하고, 클라이언트는 이를 수신해 API로 상세 정보를 조회한 후 알림을 표시했다.

2️⃣기존 시스템의 문제점

제로 페이로드 문제
레거시 클라이언트에서 긴 페이로드가 잘리는 문제로 인해 변경 ID만 전송하고 클라이언트가 API로 상세 정보를 조회했다. 이로 인해 알림 로직이 클라이언트에 있어 문구나 시점 변경 시 앱 업데이트가 필수였다.

보안 문제
토픽 구독에 인증이 없어 다른 파트너의 토픽 구독이 가능했다. 다만 제로 페이로드였기에 유의미한 정보는 API 호출로만 얻을 수 있어 큰 문제는 없었다.

네트워크 문제
MQTT가 사용하는 1883, 8883 포트가 일부 환경에서 방화벽에 차단되어 폴링 로직이 추가로 필요했다.

웹뷰 연결 문제
웹뷰에서 여러 탭이 동시에 열리는 환경에서 MQTT 인증서 관리의 복잡도가 높았다.

3️⃣ AWS IoT 도입

AWS IoT를 도입하여 일부 문제를 해결했다.

보안 강화: x509 인증서 발급 시 자신의 토픽만 구독 가능하도록 권한을 부여했다.

페이로드 정형화: 보안이 강화되어 페이로드에 유의미한 정보(title, content, eventType, soundType 등)를 포함시켰다. 클라이언트는 수신 즉시 알림을 표시하게 되어 버전 종속성이 사라졌다.

하지만 MQTT를 사용하는 한 네트워크와 웹뷰 문제는 여전했다.

4️⃣ SSE 도입

왜 SSE인가?

실시간 통신 방식을 검토했다.

  • 폴링: 주기적 요청으로 비효율적
  • 웹소켓: 양방향 통신이지만 모든 API를 웹소켓으로 재정의해야 하는 오버 엔지니어링
  • SSE: 서버에서 클라이언트로 단방향 푸시, 기존 API 구조 유지 가능

알림만 필요한 발표자의 상황에 SSE가 적합했다.

5️⃣ 메시지 전달 방식 선택

세 가지 방식을 검토했다.

  1. 세션 연결 서버로 API 호출: 성능은 좋지만 세션 관리 복잡, 유실 가능성
  2. 브로커로 특정 서버에 전송: 순서 보장되지만 토픽 관리 복잡, 유실 가능성
  3. 모든 서버로 브로드캐스트 후 필터링: 간단하고 순서 보장, 쉬운 스케일 아웃

메시지 신뢰성이 가장 중요했기에 3번 방식을 선택했다.

6️⃣ 메시지 안정성 확보

Last-Event-ID 활용

SSE 표준인 Last-Event-ID 헤더를 활용했다. 클라이언트가 마지막 수신 ID를 헤더로 전송하면, 재연결 시 그 이후 메시지를 조회해 전송하여 순단 중 유실을 방지했다.

커밋 메시지

주문서 출력, 신규 알림 등 중요 메시지는 정확히 한 번만 전달되어야 했다. commitUrl을 포함한 메시지를 전송하고, 클라이언트가 수신 시 이를 호출하면 서버에서 마킹했다. 주기적으로 미커밋 이벤트를 조회해 재발행했다.

보안 강화

같은 세션의 동시 접속을 차단했다. 세션 매니저로 활성 세션을 관리하고, 메시지 전송 전 세션 유효성을 검증해 비정상 세션은 강제 종료했다.

폴링 제거

클라이언트의 다양한 폴링 로직을 서버로 이동시켰다. SSE 연결 시 서버가 각 도메인을 주기적으로 호출하고, 변경 시에만 클라이언트에 전송해 API 호출을 줄였다.

7️⃣ 전환 과정의 문제들

백프레셔 문제

코루틴 채널을 기본값(capacity=RENDEZVOUS, 즉 0)으로 생성해서 버퍼가 없었다. 메시지 처리가 지연되면 Kafka max.poll.interval이 초과되어 파티션 할당이 해제되었다. 적절한 capacity와 onBufferOverflow 설정으로 해결했다.

배포 시 CPU 스파이크

배포로 연결이 끊기면 모든 클라이언트가 동시에 재연결을 시도했다. 연결 유지 시간이 일정해 주기적으로 CPU가 급증했다. 연결 유지 시간과 재연결에 랜덤 지터를 부여해 해결했다.

불필요한 네트워크

앱, PC, 웹뷰 등 프로그램별, 버전별로 처리 가능한 메시지가 달랐지만 모든 메시지를 전송했다. 연결 시 처리 가능한 이벤트 타입을 받아 필터링하여 불필요한 네트워크 I/O를 제거했다.

8️⃣ 향후 개선 계획

메시지 브로커 변경: Kafka 대신 Redis Stream이나 NATS 같은 경량 프로토콜을 검토 중이다.

모바일 앱 SSE 도입: 포그라운드에서는 SSE, 백그라운드에서는 푸시로 전환하여 속도와 비용을 개선할 예정이다.

9️⃣ 결론

SSE 도입으로 다음과 같은 성과를 얻었다.

  • 서버 비용 절감 및 일평균 4천만 건의 안정적 처리
  • 폴링 제거로 네트워크 트래픽 감소
  • 클라이언트 업데이트 없이 알림 제어 가능
  • 코틀린 코드로 작성되어 쉬운 수정 및 반영
  • 웹뷰 지원 및 보안 강화

BROS 레거시 스파게티 코드 개선

이 세션을 들은 이유는 우아한테크코스를 진행하며 프로젝트의 레거시 코드를 리팩토링하는 경험을 해보았기 때문이다.

내 기억상 리팩토링 과정은 힘들었었다. 리팩토링 이전에는 구현 능력이 중요하다고 생각했는데, 리팩토링을 시작하며 설계 능력의 중요성을 체감하였다.
아직 전체적인 아키텍쳐 설계 능력이 부족했던 나로서는 리팩토링 과정이 가장 고통스럽기도 하였다.😢

이러한 이유로 조언 혹은 배움을 얻을 수 있을까 싶어 해당 세션에 참여하였다.
BROS는 우아한 형제의 수백개의 프로젝트 중에서 10년 동안 유지보수 되어왔던 레거시 코드이며 10손가락 안에드는 코드라인수를 가졌다. 과연 BROS팀은 어떻게 리팩토링을 하였을까?

단계별로 발표내용을 분석해보겠다.

1️⃣ BROS의 시스템 구조와 문제점

멀티 모듈 프로젝트 구조

BROS는 여러 서버와 여러 공통 모듈이 존재하는 멀티 모듈 프로젝트로 구성되어 있다. 주요 서버들은 '딜리버리 서비스'라는 공통 모듈을 의존하고 있으며, 이 공통 모듈에 기능을 작성하면 여러 서버에서 사용할 수 있다. 그 결과 쉽게 기능이 추가되어 대부분의 비즈니스 로직을 포함한 매우 거대한 모듈이 되었다.

진짜 문제는 이 거대한 공통 모듈을 여러 팀이 커밋하고 있다는 점이다.

R&R 문제

💡R&R 이란?

R&R은 Role & Responsibilities의 약자로, 조직 내에서 각 구성원이 맡은 역할과 책임을 뜻한다.

여러 팀이 하나의 공통 모듈을 관리하면서 다음과 같은 문제가 발생했다.

  • 브랜치가 너무 다양하고 복잡
  • 원치 않은 레거시 코드와 코딩 스타일 마주침
  • R&R 논의, 개발 검토, 리뷰, 배포 이후 조치 등 팀과 팀을 넘어 과한 커뮤니케이션 발생

결과적으로 역할을 넘어선 과도한 비용이 발생했다.

스파게티 코드 문제

딜리버리 서비스 모듈 안에는 배달 관련 기능이 있고, 이 기능이 수행되면 애플리케이션 이벤트를 발행한다. 그러면 이벤트 리스너 또는 트랜잭셔널 이벤트 리스너로 구현된 후처리 리스너에서 나머지 동작을 수행하는 구조였다.

이벤트와 리스너의 복잡한 관계

  • 배달 이벤트: 약 39개
  • 후처리 리스너: 19개

서비스 A가 기능을 수행하면 애플리케이션 이벤트를 발행하고, 리스너 B, C, D에서 각각 이벤트를 소비한다.
문제는 리스너가 단순히 종료되지 않고, 다시 순환 호출되거나 다른 도메인을 호출하는 경우가 있다는 점이다.
그 서비스에서 또 다른 이벤트를 발행하면 대응되는 리스너들이 또 이를 소비하는 방식으로, 서비스와 리스너가 N:M 관계를 가지고 서로 복잡하게 호출하는 구조였다.

❗결과적으로

  • 개발 검토 중 길을 잃어버리기도 함
  • 높은 인지 부하로 위험 요소 증가
  • 영향 범위 파악에 매우 큰 비용 발생

2️⃣ 해결과정

이 과제의 핵심은 사실 RNR 정리 과정을 통해 공통 모듈이 엮여있는 역할과 책임을 분리하는 것이었고, 이를 위해 선행 업무로 코드 청소를 먼저 해야 되고 그다음에 또 성능 개선까지 같이 챙겨야 하는 미션을 받았다.

1. 🧹복잡한 코드 청소: 애플리케이션 이벤트 리스너 정리

코드 청소를 위해 다음 단계를 이어갔다.

  1. 일단 먼저 사용 여부와 대체제를 확인한 뒤에 삭제를 먼저 검토했다.
  2. 처리 리스너 내에 존재하는 비즈니스 로직들을 각 도메인에 맞게 리팩터링을 진행을 했다.
  3. 최종적으로 이제 애플리케이션 이벤트 리스트를 삭제하는 방향으로 가져갔고 이 리팩터링한 기능을 직접 메소드 콜 방식으로 개선했다.

결과

  • 리스너가 19개 → 5개로 감소 (14개 제거)
  • 리스너 로직 간소화 및 도메인 응집도와 가시성 향상
  • 불필요하게 긴 트랜잭션을 짧게 축소

2. 💫 R&R 정리

R&R 정리는 가장 메인이 되는 과제였다. 공통 모듈 사이의 역할과 책임을 끊어어 내고자 많은 노력을 했음이 보였다.

1. 라이더 서버

문제점

  • 라이더 서버는 라이더 팀 담당이지만 배달 수행에 직접 트랜잭션을 실행하는 역할이 과도함
  • 공통 모듈을 계속 수정해야 하는 부담
  • 액터(라이더 vs 관리자)에 의존하는 로직이 공통 모듈에 존재

해결
배달 서버를 중간에 투입했다. 네트워크 구간은 증가했지만 배달 수행의 직접 트랜잭션 실행 역할을 배달 서버에 부여하고, 라이더 서버는 배달 서버를 호출하는 방식으로 역할을 축소했다. 액터에 의존한 로직은 배달 서버와 어드민 서버 각각 앞쪽으로 이관하고, 공통 모듈에는 배달 도메인에 집중한 코드만 남겼다.

2. 라이더 메시지 도메인

문제점
관리자의 주소 변경, 고객/사장님의 주문 취소 시 라이더에게 동선 변경을 알리는 웹소켓 발행 코드가 공통 모듈에 존재했다. 배달팀 입장에서 담당 도메인도 아니고 코드 수정이 어려웠다.

해결
배달 이벤트를 라이더에게 보낼지, 어떻게 보낼지 결정하는 도메인은 라이더에 더 가깝게 위치해야 한다고 합의했다. 메신저 서버를 활용하여 기존 웹소켓 발행 기능을 모두 이관시켰다. 기존 애플리케이션 이벤트 리스너는 Kafka를 사용해서 서버 분리를 진행했다. 메신저 서버에서 Kafka를 통해 이벤트를 소비하고 여기에서만 웹소켓이 발행되도록 R&R을 정리했다.

3. R&R 정리: 문의 내역 도메인

라이더와 상담사를 연결하는 도메인이 공통 모듈에 위치했다. 새로운 공통 모듈을 만들고 리팩토링하면서 코드를 이관했다. 소프트한 경계 격리를 의도했다.

3. ⭕성능 개선: API 3대장 개선

라이더 서버의 가장 많이 호출되는 API인 '배달 진행 목록' API를 대상으로 성능 개선을 진행했다.

문제점

  • 반복적으로 DB 조회 수행
  • REST Call이 있음에도 트랜잭션을 길게 사용
  • 방어 로직을 수행하는 Insert 기능을 위해 Writer DB를 오랫동안 점유

해결

  • 배달 서버를 중간에 두고 DB 사용을 모두 위임
  • 불필요한 단계 제거
  • 중복된 DB 사용을 줄이고 리더 DB 사용
  • REST Call 시점에 트랜잭션이 포함되지 않도록 처리
  • 방어 로직 수행 시 잠깐만 Writer DB를 사용하도록 트랜잭션 범위 최소화
  • Response 크기 경량화

3️⃣ 성과

1. ⭕ 코드 품질 개선

스파게티 코드 제거

  • 이벤트 리스너: 19개 → 5개 (14개 제거)
  • 기존 마이너 버그와 취약점 개선
  • 미사용 비즈니스 로직, 테이블 적재, 리소스 제거

복잡도 감소

  • 프로젝트 전체 코드: 3천 라인 증가 (4개월간 다른 팀 개발 병행)
  • 순환 복잡도와 인지 복잡도 감소 (코드량 증가에도 불구하고)
  • 특히 공통 모듈: 1만 라인 이상 제거, 복잡도 크게 감소

테스트 커버리지 향상

  • 30% 초반 → 36% 상승
  • 리팩토링한 코드들의 커버리지 대부분 70~80% 이상

2. ⭕ R&R 정리

  • 라이더 서버: 역할과 책임 축소
  • 메신저 서버: 배차 추천/거절 시점만 사용 → 배달 전반적인 부분으로 확대
  • 배달 서버: 배달 내역 서빙 역할 → 라이더의 배달 수행 처리로 재정의

3. ⭕ 성능 개선

서버 관점

  • 주요 API 레이턴시: 약간 감소 (중간 서버 추가로 네트워크 구간 증가했으나 성능 유지)
  • 리스폰스 사이즈: 최대 44% 감소

DB 관점

  • 저녁 타임 피크 기준 라이터 DB CPU: 최대 7% 감소 (비싼 머신 사용 중이라 큰 변화 기대 어려웠으나 성과 달성)
  • 데일리 기준 라이터 DB CPU: 5% 이상 감소
  • 리더 DB CPU: 각각 1%, 2.7% 증가 (트랜잭션 분리하여 라이터 DB 사용 줄이고 리더 DB로 전환한 의도대로 작동)

4. 무장애 달성

4개월간 개선 업무로 장애 발생 없음 - 참여자들이 가장 만족하는 성과

🧐 세션 후기

대규모 프로젝트의 리팩토링 과정을 들으며, 만약 내가 시작한다면 어디서부터 손대야 할지 상상해보았다.

결론적으로, "네! 10분 동안 멍만 때렸습니다."

리팩토링 능력을 키우려면 어떻게 해야 할까? 애초에 모든 것을 고려한 설계란 가능한 것일까?
책을 더 읽고, 다른 사람들의 코드를 관찰하며 학습할 필요가 있겠다.


RAG, 들어는 봤는데... 내 서비스엔 어떻게 쓰지?

이번 세션은 개인적으로 가장 기대했던 부분이다.
‘모잇지’ 프로젝트에서는 핵심 로직에 AI를 직접 활용해보았고, 앞으로는 단순히 학습 데이터에 기반한 응답이 아닌, 실제 데이터 기반의 신뢰성 높은 응답으로 서비스를 발전시키고자 했다.

그 과정에서 주목한 개념이 바로 RAG(Retrieval-Augmented Generation) 이다.
RAG는 최근 AI 분야에서 가장 주목받는 트렌드 중 하나로, 관련 학습 자료도 다양하게 존재했다.
그러나 여러 자료를 살펴보아도, 우아한테크코스 백엔드 코치 검프 의 설명만큼 명확하게 이해되는 것은 없었다.

1️⃣ RAG가 필요한 이유

LLM을 사용할 때 쿼리를 던지면 때로는 정상 응답이 오고, 때로는 응답이 불가하거나 환각(Hallucination) 현상이 발생한다. LLM이 바보라서일까? 아니다.
이런 일이 발생하는 이유는 LLM이 인터넷에 있는 정보와 학습 모델이 가진 자체 데이터로만 학습했기 때문이다. 환각이 발생하는 이유는 학습 데이터에 없는 것을 요청했기 때문이다.

▪️예시

질문: "이번 주 미팅 일정은?"
결과: 환각 발생 (LLM의 학습 데이터에 없는 정보)

당연한 결과이다. 사람의 경우에도 누군가가 대뜸 이런 질문을 하더라도 그 사람의 일정에 대해 모른다면 대답을 할리 만무하다.

해결 방법은 쿼리 + 컨텍스트을 같이 제공한다. 캘린더 파일과 함께 "이번 주 미팅 일정은?"이라고 보내면 LLM이 쿼리와 컨텍스트를 이해하고 정상적인 응답을 할 수 있다.

▪️쿼리-컨텍스트 결합도 증가

이때 새로운 문제가 발생한다. 준비해야 할 쿼리-컨텍스트가 많아지면 어떻게 될까?

"이번 주 미팅 일정은?"
"기획서 내용 요약해줘"
"데이터가 존재하는지 확인해줘"

쿼리-컨텍스트 결합도가 증가하면 또 다른 문제가 발생한다. 쿼리로는 "이번 주 미팅 일정은?"이라고 보냈는데 컨텍스트로 파일 시스템 정보를 주면 LLM이 이해하지 못하고 잘못된 응답을 받게 된다.

2️⃣ RAG란?

RAG는 이러한 문제를 해결한다. 사용자가 쿼리를 보내면 그 쿼리에 맞는 정보를 지식 베이스에서 검색해 온 다음, 검색해 온 내용을 바탕으로 쿼리와 함께 LLM에게 정보를 보내어 정상적인 응답을 받게 하는 것이다.

💡 한마디로 RAG란

LLM이 새로운 정보를 검색하고 통합할 수 있도록 하는 기술

3️⃣RAG의 3가지 핵심 컴포넌트

1. 색인(Indexing) 파이프라인
문서를 검색 가능한 형태로 준비하고 저장하는 단계. 예를 들어 캘린더 파일을 검색해서 가져오기 위해 미리 준비하는 것이다.

2. 생성(Generation) 파이프라인
질문에 맞는 정보를 검색하고 답변을 생성하는 과정. 색인 파이프라인에서 준비된 파일을 가져와 LLM에게 던지고 정상적인 응답을 받게 하는 과정이다.

3. 평가(Evaluation)
사용자와 직접 인터랙션하지는 않지만 시스템의 품질을 측정하고 개선하기에 필수적인 요소다.

4️⃣ RAG 구현 6단계

(실은 이전에 검프가 교육 운영 RAG를 만들기 위해 MCP 를 도입하는 과정이 있었지만 내용이 길어 이번에는 적지 않았다.)

💡RAG 구현 6단계 요약

1. 사용 사례 식별 및 RAG 필요성 평가: RAG의 필요성 확인
2. 요구 사항 수집 및 분석: RAG 시스템에 필요한 요구 사항 분석
3. RAG 프레임워크 결정: Spring AI 선택
4. 색인 파이프라인 구현: 로딩, 청킹, 임베딩, 저장소
5. 생성 파이프라인 구현: 검색, 증강, 생성
6. 평가 구현: 컨텍스트 관련성, 답변 충실성, 답변 관련성

RAG를 구현하기 위해서는 위의 여섯 단계가 필요했다. 이 여섯 단계가 완료되어야 운영 배포가 완료되었다고 말할 수 있다.

이제부터 단계별로 요약하여 설명하겠다.

1. 사용 사례 식별 및 RAG 필요성 평가

RAG가 듣고보니 정말 좋은데 모든 AI 관련 프로젝트에서 도입하면 좋지 않을까?
그렇지 않다. RAG를 무조건 써야 한다고 생각하면 배보다 배꼽이 커지는 경우가 발생한다.
한다.
RAG는 쿼리-컨텍스트 결합도가 많이 증가할 때가 RAG 도입 시점이다.

RAG가 필요한 경우

  • 실시간으로 정보가 업데이트되는 경우
  • 도메인 내 특화 지식이 필요한 경우

RAG가 불필요한 경우

  • 간단한 질의응답
  • 업데이트되지 않는 정적 데이터
  • 일반적인 대화

2. 요구 사항 수집 및 분석

3. RAG 프레임워크 결정

어떤 프레임워크를 사용할지 결정하는 단계다. 검프는 RAG 구현시 스프링 AI를 선택했고 이유는 아래와 같다.

Spring AI vs LangChain 비교

항목Spring AILangChain
요구 사항 변경 시 유연한 대응익숙한 자바 환경, 스프링 생태계 - 가능파이썬 환경, 추가 학습 필요 - 어려움
팀원들이 단기간에 습득 가능팀 내 기술 스택과 동일 - 가능추가 학습 필요 - 어려움
배포 가능기존 배포 플랫폼 지원 - 가능추가 연동 필요 - 어려움
로깅 추적 가능가능불가능

유의사항

  • 프레임워크의 장점보다 팀이 익숙한 언어 환경이 생산성에 더 큰 영향을 미침

  • 혼자 개발하거나 배울 수는 있지만 팀 내 코드 리뷰나 코멘트를 받으려면 팀원들이 익숙한 언어가 훨씬 생산성이 좋음

  • 모든 항목에서 가능한 것은 없음 - 우리 상황에서 중요한 것의 우선순위 결정 필요

  • "완벽함보다 빠른 검증" 슬로건으로 빠른 빌드, 배포, 검증이 가능한 Spring AI 선택

4. 색인 파이프라인 구현

문서를 검색 가능한 형태로 준비하고 저장하는 단계다. 핵심 요소는 로딩, 청킹, 임베딩, 저장소 네 가지다.

4-1. 로딩 (Loading)

데이터 소스를 연결하고 수집하는 요소다. 캘린더 API를 통해 캘린더 파일을 가져온다고 생각하면 된다.

고려 사항

  • 어떤 데이터 연결: DB, 구글 드라이브, 캘린더

  • 어떤 포맷 파싱: JSON, 텍스트, XML

  • 데이터 정제: 개인정보 마스킹, 중복 제거

유의사항

  • 텍스트 데이터를 먼저 고려한다. (이미지, 음성, 비디오는 이후 모든 프로세스 변경 필요)

  • 외부 API 호출 제한에 유념한다.

  • 한 번에 모든 데이터를 가져올지, 조금씩 가져올지 확인한다.

4-2. 청킹 (Chunking)

데이터를 검색 가능한 단위로 분할하는 요소다. 캘린더에서 가져온 파일을 검색 가능한 단위로 잘게 쪼갠다고 생각하면 된다.

고려 사항

  • 분할 전략: 고정 크기 청킹, 부모-자식 구조

    • 고정 크기 청킹: 청크 크기를 미리 결정
    • 부모-자식 구조: 부모 청크에는 전반적인 요약, 자식 청크에는 세부 사항과 부모 청크 정보 또는 시퀀스 번호
  • 크기와 중복: 5천 자 (Spring AI 기본값), 중복 없음 (부모-자식 구조)

  • 메타데이터: 출처, 시간, 구조 정보 저장

유의사항

  • 청크 크기 최적화가 필요하다.

    • 작으면: 빠르고 성능 좋지만 문맥적 검색 신뢰도가 떨어진다.
    • 크면: 성능 떨어진다.
    • 도메인 특성에 따라 설정하는 것을 추천한다.
  • 청킹 전략에 따라 분할로 인한 의미 손실 발생 - 도메인 고려하여 손실 허용 범위 설정

  • 메타데이터는 필수다. 청크된 데이터의 의미를 정리해 주는 데이터가 있으면 검색 시 더 나은 성능

4-3. 임베딩 (Embedding)

분할된 내용을 컴퓨터가 이해하는 n차원 형태로 변환하는 것이다. 배열의 각 요소가 차원이고, 각 차원의 숫자들이 분할한 데이터를 표현한다.

유의사항

  • 파운데이션 모델로 항상 먼저 검증

  • 도메인 속성에 따라 파인 튜닝할 수 있지만 처음 전체 플로우를 해볼 때까지는 파운데이션 모델 사용

  • 차원 수는 높을수록 성능 좋지만 비용 증가 - 적절한 수 선택

4-4. 저장소 (Storage)

임베딩된 데이터를 저장하고 검색할 서비스다. 컴퓨터가 이해할 수 있는 벡터 형태로 변환된 파일을 나중에 검색하기 위해 저장한다.

5. 생성 파이프라인 구현

질문에 맞는 정보를 검색하고 답변을 생성하는 과정이다. 핵심 요소는 검색, 증강, 생성 세 가지다.

5-1. 검색 (Retrieval)

사용자 질문에 가장 관련성 높은 청크를 추출하는 것이다. 색인 단계에서 저장된 청크들을 검색기에서 가져온다.

고려 사항

  • 검색 전략: 저장소 기본 설정인 문맥적 임베딩 사용
    • 문맥적 임베딩: 문맥 기반 검색 (예: "애플"이 과일인지 회사인지 구분한다)
  • 사용자 질문 최적화: LLM을 이용하여 최적화한다. (불필요한 것은 버리고 필요한 것만 남긴다)

유의사항

  • 메타데이터 필터링으로 검색 효율성 향상: 데이터 세부 내용보다 필터링된 내용 검색이 효율적이다.

  • 청크 개수 설정 필요: 많이 가져올수록 컨텍스트 윈도우가 빠르게 소비 된다.

  • 유사도 점수 기준 필요: 우리 도메인에서 어느 정도 유사도까지를 맞다고 판단할지 설정해야한다.

  • 검색된 데이터의 정밀도는 평가 단계에서 면밀히 검토한다.

5-2. 증강 (Augmentation)

검색된 청크를 사용자 질문과 결합하여 LLM에게 전달하는 요소다. 사용자 질문과 검색된 데이터를 프롬프트와 함께 던지는 과정이다.

고려 사항

  • 페르소나를 정의:
    예시) AI가 수행할 역할이나 성격을 "교육 운영 데이터를 검색해 주는 서비스"

  • 컨텍스트 제약: 검색된 내용으로만 답변

  • 프롬프팅 기법: 추론 과정을 응답하도록 요구, 답변 형식을 특정 형식으로 지정

유의사항

  • 검색된 청크 원본 유지하여 검증: 프롬프트를 수정하다 청크가 너무 커져도 청크 수정보다는 프롬프팅 수정이나 청크 개수를 조정한다.

  • 프롬프트 명확히 제시: "검색된 내용으로만 답변해", "이런 응답 형식으로 답변해" 등 명확한 제약

  • 프롬프트도 컨텍스트 윈도우 사이즈에 포함 - 간결화가 필요하다.

5-3. 생성 (Generation)

증강된 프롬프트를 받아 최종 응답을 생성하는 요소다. 쿼리, 컨텍스트, 프롬프트를 LLM이 받아서 사용자에게 응답하는 과정이다.

유의사항

  • 파운데이션 모델로 먼저 검증: 오픈소스 모델, 파인 튜닝 모델도 있지만 처음에는 범용 모델로 모든 프로세스를 검증하는 것을 추천한다.

  • 프롬프트의 점 하나로 결과값이 크게 달라진다.(진짜로)

  • 모델 자체가 바뀌면 기존에 잘 나오던 것도 안 나올 수 있다.

  • 모델 크기는 도메인의 가치에 따라 설정한다 : 방대한 데이터 검색이나 의료 정보는 큰 모델, 단순 캘린더 일정은 작은 모델을 선택한다.

  • 성능과 속도 사이의 트레이드 오프 필요가 필요하다: 늦더라도 정확한 답변 vs 빠르지만 부족한 답변 사이의 트레이드 오프가 필요하다.

  • 증강된 데이터의 품질은 평가 단계에서 고려한다.

6. 평가 구현

시스템의 품질을 측정하고 개선하는 과정이다. 세 가지 큰 지표를 측정한다.

6-1. 컨텍스트 관련성 (Context Relevance)

검색된 정보가 사용자 질문과 얼마나 관련성이 높은지를 평가하는 지표다.

6-2. 답변 충실성 (Answer Faithfulness)

생성된 답변이 검색된 정보에 얼마나 사실적으로 근거하는지 평가하는 지표다.

6-3. 답변 관련성 (Answer Relevance)

생성된 답변이 사용자 질문과 얼마나 관련성이 높은지 평가하는 지표다.


2025 우아콘을 마치며🎉

처음의 마음가짐

사실 처음 마음가짐은 "컨퍼런스 현장의 분위기를 느끼자"였다.

아마도 마음 한편에 발표를 하시는 개발자 분의 내용을 내가 감히 이해할 수 없을 거라는 주눅이 들었었나 보다.

예상과 달랐던 경험

하지만 막상 발표를 들어보니 발표 내용이 이해가 되었고, 너무나도 배울 점이 많았다.

우테코에 들어오기 전이라면 하나도 알아듣지 못했을 내용들이 전부는 아니더라도 귀에 들어오고, 발표 내용에 대해서 고민까지 할 수 있게 되었다.

실제로 슬리도를 통해 발표자 분께 이것저것 질문을 하고 답변을 받는 경험을 할 수 있었기에, 우아한형제들의 현업 개발자 분들과 커뮤니케이션을 하고 있다는 사실에 더욱 뿌듯했던 것 같다.

성장의 원동력

아마도 이 모든 것은 우테코 내의 커리큘럼에 녹아있던 교육철학을 자연스레 배운 덕분이라 생각한다.

다시 한번 이런 소중한 경험을 주신 코치님들과 다양한 이야기를 나누었던 크루들에게 감사함을 전하고 싶다.

앞으로의 다짐

앞으로도 이러한 컨퍼런스에 자주 참여할 것 같다.

동기부여도 되고 다양한 개발자들의 모습을 볼 수 있다는 것은 많은 것을 배우게 해준다.


2025 우아콘은 내 인생 첫 컨퍼런스였고, 최고의 경험이었다! 🎉

profile
도전하며 굴러가는 돌멩이, 인생 마라톤 중 😎

0개의 댓글