합반 프로젝트 프로젝트 회고록 / 대규모 핀테크 사일런트 컨퍼런스

김지민·2025년 4월 7일
0

회고록

목록 보기
11/11

대규모 핀테크 사일런트 컨퍼런스

1️⃣ 개요

프로젝트 주제💡

: 대규모 핀테크 컨퍼런스에서 발생하는 비효율적인 운영 및 참가자의 불편을 해결하는 모바일 웹 기반 사일런트 컨퍼런스 솔루션


프로젝트 목표🚀

참가자가 온·오프라인에서 능동적으로 참여할 수 있도록 지원하며, 컨퍼런스 운영의 효율성과 만족도를 높이는 올인원 솔루션을 제공합니다.


프로젝트 내용📝

수행 방법

  • 1주차: 최종 기획안 작성 + 요구사항 파악 및 분석, 사용자 중심 웹 디자인과 개발 전략 수립
  • 2~5주차:
    • 시스템 아키텍처 설계, 데이터베이스 설계
    • 애자일 방법론 기반 반복적 개발 프로세스 수행
    • 성능 최적화 및 보안 검토
    • 기타 편의 기능 개발
  • 6주차: 최종 산출물 정리 및 발표, 프로젝트 성과 평가 및 개선안 제시
  • 주차별 세부 일정과 산출물 정리는 해당 팀의 PM이 진행

프로젝트 배경🖼️

혼잡한 강연장, 강연 선택의 어려움, 비효율적 질의응답, 세션 간 이동 어려움, 높은 운영 비용 등 기존 컨퍼런스의 문제점을 개선하고자 기존 스피커 시스템 대신 무선 헤드셋을 활용하여 한 공간에서 여러 개의 세션을 동시에 진행할 수 있는 혁신적이 포럼 방식의 사일런트 컨퍼런스를 선택하였습니다. 또한 시장의 성장 가능성을 고려하여 핀테크 컨퍼런스를 선정하였습니다.


2️⃣ 일정

프로젝트의 시작일과 종료일📆

시작일: 2025년 2월 26일
종료일: 2025년 4월 2일


작업 계획🗓️


3️⃣ 프로젝트 팀 구성

팀 구성원들의 역할과 책임👑


김지민(본인)

  • ERD 설계
  • 채팅 기능 설계 및 개발

4️⃣ 기술 스택 및 사용 도구

PD

  • Figma

FE

  • Core: React - js
  • UI: tailwindCss
  • State Managing: redux
  • Bundler: Vite

BE (My part)

  • SpringBoot
  • Spring Security
  • Docker
  • OAuth2
  • JPA
  • MySQL
  • Redis
  • Swagger
  • AWS
  • WebSocket
  • Redis Pub/Sub
  • Kurento

5️⃣ 아키텍처

시스템 아키텍처

플로우 차트


6️⃣ 기능 설명

  1. 모바일 웹 오디오 스트리밍 - 강연장 혼잡 시 온라인 스트리밍 대체 옵션 제공
  2. 실시간 혼잡도 제공 - 강연장 체크인 데이터를 활용한 실시간 좌석 및 인원 분석
  3. 실시간 Q&A 및 투표 - 모바일을 통한 질문 및 투표 기반 인기 질문 상위 노출
  4. 강연 미리담기 시스템 - 관심 강연을 사전 등록하여 일정 최적화
  5. 맞춤 강연 추천 - 참가자의 관심사를 분석하여 맞춤 강연 추천

7️⃣도전과제 및 해결책

  1. 채팅 화면에는 전송자 이름이 보여야하는데, 채팅은 쓰기랑 조회가 많아 mysql에 이름으로 계속 접근해도 괜찮을까 하는 우려사항 존재
    ➡️ Redis에는 userId만 저장하고, 조회할 때 userId → name을 매핑하는 방식으로 구현

  1. 전체 메시지가 아닌 각 세션의 채팅방 당 메시지 개수가 1000개만 유지되도록 구현해야하는데, 세션별로 처리하지 못했음
// 기존 방식
// 메시지 1000개 유지
		if (redisTemplate.opsForList().size(CHAT_LIST_KEY) > MAX_CHAT_SIZE) {

➡️ (CHAT_LIST_KEY + sessionId)로 처리하도록 변경 피드백 받음

private static final String CHAT_MESSAGE_KEY_PREFIX = "chat-messages:";  // 메시지 저장용
private static final int MAX_CHAT_SIZE = 1000;
String chatKey = CHAT_MESSAGE_KEY_PREFIX + message.getSessionId();

chatKey에 세션아이디를 포함시키고

redisTemplate.opsForList().trim(chatKey, -MAX_CHAT_SIZE, -1);

리스트 크기 1000개로 유지


  1. 페이징 처리 이슈
// 기존 방식
List<Object> rawMessages = chatRepository.getRecentMessages(String.valueOf(sessionId));

Redis에서 전체 메시지 조회 후 QUESTION 카테고리만 필터링 하여 좋아요 수 기준으로 정렬 후, Pageable 기준으로 자바에서 페이징하는 방식으로 구현
⬇️
그러나, 페이징 처리를 통해 일정 부분씩 끊어서 조회하여 데이터로딩에 대한 부하를 줄이는 장점이 있는데, 레디스에서 전체 조회 후 자바에서 페이징처리해도 부하를 줄일 수 있을지에 대한 의문 발생
⬇️
Redis List를 사용하고 있어서 전체 조회 후 페이징 처리를 하는 방법을 선택했었는데, 메시지 개수가 많아지면 부하를 줄이기 어려울 것 같다고 생각
⬇️
찾아본 결과 List는 전체를 가져와서 잘라야 하고,
ZSet은 정렬된 상태에서 원하는 범위만 잘라서 가져올 수 있다고 함.
레디스는 읽기 속도가 빨라서 1000개정도까진 무리없어서 전체조회 후 자바에서 페이징처리해도 괜찮을 것 같다는 의견도 있지만, 실시간 좋아요 수에 따른 실시간 질문 정렬이 가능하도록 하기 위해서 ZSet으로 리팩토링 하는 방향으로 결정하여 해결했음


  1. 유저 아이디 관련 이슈
    프론트 개발자에게서 들어온 이슈

    "우리가 유저 정보를 조회할 때 사용하는 두 API:
    /api/v1/users/account
    /api/v1/users/profile
    이 API들의 응답(Response)에는 userId가 안 들어있는데,
    그럼 우리가 ChatMessage를 생성할 때 필요한 userId는 어디서 가져와야 해?"

지금 프론트엔드는 서버에 메시지를 보낼 때 userId를 포함해야 하는 상황인데,
현재 제공된 API 중 어디에도 userId가 포함돼 있지 않은 상황
1. DTO에 userId를 추가
2. ChatMessage에서 userId 대신 email 사용

➡️ 두가지 방법을 논의했으나, Spring Security가 로그인한 유저의 정보를 담아주는 객체 Principal을 사용하는 것으로 결정

  • principal.getName() → 기본적으로 유저의 email이 들어 있음
  • 굳이 프론트에서 userId나 email을 따로 보내지 않아도 됨
  • 백엔드는 JWT 토큰 기반으로 유저 정보 확인하고, Principal을 채워줌

💡 프론트는 단순하게 요청만 보내면 되고, 백엔드는 Principal로 유저 식별 가능


  1. 네이밍 이슈

    레디스 키 네임을 중복으로 사용하여 충돌발생
    ➡️ 중복되지 않게 키 네임을 역할에 따라 각각 설정해줌

  1. 메시지 찾을 수 없음 에러 발생
    레디스 키 네임 수정 미반영으로 인한 에러를 확인하고 추가적으로
String messageKey = "chat-messages:" + message.getMessageId();

채팅 메시지 저장 시, 메시지 아이디를 키 값으로 저장하여 메시지를 제대로 불러올 수 있도록 하여 에러 해결


  1. timestamp 파싱 에러
    현재 상황
Text '2025-03-29T22:16:19.342572147' could not be parsed, unparsed text found at index 19

"2025-03-29T22:16:19.342572147"는 나노초 단위까지 포함된 ISO-8601 포맷,
근데 기본적으로 Jackson + JavaTimeModule 조합은 나노초까지는 처리 못 함. 최대 마이크로초 (6자리)까지만 지원

즉, Jackson이 timestamp를 LocalDateTime으로 파싱할 때 ".342572147"에서 뒷자리까지 파싱 못 해서 실패

// 💡 LocalDateTime 직렬화 시 나노초 제거 (기존 오류 해결용)
		objectMapper.configOverride(LocalDateTime.class)
			.setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd'T'HH:mm:ss"));

➡️ 나노초를 제거하여 에러 해결


8️⃣ 결과 및 성과

기능 구현 결과





9️⃣ 향후 계획

  1. 혼잡도 분석
  • IoT 센서 및 Beacon으로 출입 자동 체크
  • 푸시 알림 기능
    ➡️ 강연장 혼잡 완화, 참가자의 이동 효율성 증가
  1. 실시간 Q&A
  • NLP로 중복 질문 그룹화
  • AI가 주요 질문 요약
    ➡️ 참여 만족도 향상, 상호 간 명확한 의사소통
  1. 강연 미리담기
  • 외부 캘린더 연동
  • 맞춤 세션 일정 자동 추천
    ➡️ 개인 일정과 컨퍼런스 일정 통합 관리 가능
  1. AI 강연 추천
  • 머신 러닝 알고리즘 및 피드백 루프 추가(실제 유저 참여 데이터 반영)
    ➡️ 정교한 추천 경험 제공, 참여율 및 세션 집중도 향상

🔟 후기 및 배운 점

처음으로 PM, PD, 프론트엔드 개발자와 협업하며 프로젝트를 진행했습니다. 이전에는 백엔드 개발자끼리만 팀을 이뤄 작업했기 때문에 기술적인 부분에 대해 깊이 설명하지 않아도 소통이 원활했지만, 이번에는 다른 분야의 팀원들과 함께하다 보니 PM과 PD에게 기술적인 내용을 쉽게 풀어 설명하는 데 어려움을 느꼈고, 프론트엔드 개발자와의 협업 방식도 새롭게 배울 수 있는 계기가 되었습니다.

특히 프로젝트 막바지에는 소통이 원활히 이루어지지 않아 시간 부족으로 인해 완성도가 다소 아쉬웠던 점도 있었지만, 이러한 경험을 통해 개발 일정 공유와 커뮤니케이션의 중요성을 깊이 깨닫게 되었습니다. 또한, 그동안 백엔드 입장에서만 작성하던 API 명세서를 프론트엔드 개발자에게도 도움이 될 수 있도록 구성하는 법을 고민해보며 협업 역량을 키울 수 있었습니다.

이번 프로젝트에서는 처음으로 채팅 기능을 직접 설계하고 구현해보았는데, WebSocket, STOMP, Redis Pub/Sub 등 익숙하지 않던 기술들을 다뤄보며 부족한 점이 많았음을 느꼈습니다. 특히, 혼자 개발할 때는 잘 느끼지 못했던 로그의 중요성과 에러 추적의 필요성을 프론트와의 협업 과정에서 실감할 수 있었습니다. 이번 경험을 바탕으로, 다음에는 보다 구조적이고 안정적인 채팅 시스템을 구현할 수 있을 것이라는 자신감도 생겼습니다.


📌 마무리

이번 사일런트 컨퍼런스 프로젝트는 단순한 기능 구현을 넘어 실제 사용자 환경을 고려한 문제 해결 중심의 개발 경험이었습니다. 핀테크라는 주제를 통해 실시간 데이터 처리, 사용자 참여 유도, 시스템 아키텍처 구성 등 현업과 유사한 문제 상황을 경험해볼 수 있었고, 그 과정에서 기술적 역량뿐 아니라 팀원과의 원활한 커뮤니케이션 역량 역시 중요하다는 것을 몸소 느꼈습니다.

특히 실시간 채팅 기능을 처음부터 끝까지 직접 설계하고 구현하면서, Redis, WebSocket, STOMP, ZSet 등 새로운 기술 스택을 익히고 적용해볼 수 있었으며, 실시간성과 효율성, 확장성을 동시에 고려한 백엔드 개발이 얼마나 중요한지를 깨닫는 계기가 되었습니다.

이 프로젝트는 단발성으로 끝나는 서비스가 아닌, 실제 현장에 적용 가능하고 확장 가능한 플랫폼으로의 발전 가능성을 지니고 있습니다. 향후 IoT 기반 출입 체크, AI 기반 Q&A 정리 및 추천 시스템 등과 연계된다면, 단순한 행사 보조 시스템을 넘어 미래형 스마트 컨퍼런스 플랫폼으로 성장할 수 있을 것이라 기대됩니다.

이번 경험을 통해 얻은 지식과 교훈을 바탕으로, 다음 프로젝트에서는 더욱 완성도 높은 시스템을 설계하고 구현할 수 있도록 노력하겠습니다.


🔗 참고 자료 및 링크

BE-GitHub

profile
백엔드 개발자를 준비하는 삐약이 대학생에서 .. 취준생🐣

0개의 댓글