안녕하세요! 백엔드 개발자 김영길입니다.

🤝 자기소개

빠르게 실패하면서 배우는걸 좋아합니다.
프로젝트를 진행할 때, 완벽함을 추구하며 고민에 매몰되기보다는 적절한 고민 후 직접 구현해보며 실전 경험을 통해 문제를 해결해 나갑니다. 실패하는 것을 두려워하지 않으며, 이를 통해 프로젝트의 방향성과 완성도를 더욱 높일 수 있다고 믿습니다.

새로운 기술을 배우거나 기존의 기술을 깊게 파고드는 것을 좋아합니다.
개발자로서 새로운 기술을 배우거나 기존 기술을 깊이 탐구하는 과정이 가장 즐겁고 이를 통해 많은 지식을 얻을 수 있다고 믿습니다. 예를 들어, Express의 내부 로직을 직접 분석하고 구현해보거나 필요한 기능을 개선하는 시도를 통해 깊은 이해를 쌓아가고 있습니다. 현재 진행 중인 프로젝트와 상관없이, 개인적인 시간을 들여서라도 꾸준히 학습하고 정리하며 이를 공유하는 습관을 지속적으로 실천하고 있습니다.

지속적으로 팀원들과 협업하고 같이 성장하고 싶습니다.
개발자로서 코드 작성도 중요하지만, 동료들과의 대화를 코드로만 해결할 수는 없습니다. 저는 목표를 공유하고 함께 발전해나가는 소프트 스킬의 중요성을 깊이 인식하고 있습니다. 개인의 성장에 머무르지 않고, 동료들과 함께 성장하는 것을 지향하며 서로 도움을 주고받을 기회를 항상 적극적으로 활용하려고 노력합니다. 이러한 목표를 가지고 네이버 부스트 캠프에서 분야를 가리지않고 동료들과 활발히 소통하고 의견을 나누며 모두가 함께 성장하는 경험을 쌓을 수 있었습니다.

🚀 프로젝트

LiBoo (실시간 온라인 컨퍼런스 플랫폼)

2024.10 ~ 현재

resume-0.png

프로젝트 개요
  • 목표 : 간단한 학습 공유부터, 300명 정도의 인원이 실시간 컨퍼런스(영상 송출, 영상 시청, 실시간 채팅 및 질문)를 개최하고 참여할 수 있는 온라인 플랫폼
  • 기술 스택 : Nest.js, socket.io, Docker, Docker Swarm, Naver Cloud Platform, Redis Cluster
  • 사용 프로토콜 : RTMP, HLS
  • 서비스 페이지 : https://liboo.kr
  • GitHub : https://github.com/boostcampwm-2024/web22-LiBoo
  • 팀 개발 블로그 : https://blog.liboo.kr

주요 활동 및 성과

  • 스트리밍 프로토콜 학습
    • 사전 지식이 없던 스트리밍 지식을 학습하고 빠르게 실패해보면서 구현
  • 트랜스파일링 서버, 채팅 서버, API 서버 구조 설계
    • CPU 집중적인 트랜스파일링 서버와, 메모리 집중적인 실시간 채팅 서버를 분리하여 수평 확장에 용이하도록 설계
    • 확장성을 고려한 구조 설계부터 Docker Swarm 을 활용한 배포까지 주도적으로 프로젝트 수행
  • NCP(Naver Cloud Platform) 인프라 설계
    • 개발/테스트용 NCP 인스턴스를 분리하여 개발 편의성 향상
    • 접근 가능한 서버는 Public Subnet, 격리가 필요한 DB 는 Private Subnet 으로 분리
    • GitHub Action 으로 Prettier, Lint 확인 → Docker Swarm 으로 NCP 에 배포 하는 과정을 자동화하여 유지보수성 향상
    • 빠른 개발을 위해 NCP MySQL, NCP Redis 를 사용하여 데모 시연 후, 서버 인스턴스로 옮기면서 인프라 비용 절감
    • NCP Public, Private Subnet 으로 서브넷 분리
    • MySQL, Redis 는 Private Subnet 으로 배포하여 보안성 강화
  • 실시간성을 강조한 채팅 서버 구현
    • 메신저 어플 등과는 달리 영구적으로 유지되는 채팅방이 없고, 오프라인 유저에게 채팅을 보낼 필요가 없는 등의 특징을 활용한 Redis Pub/Sub 구조 설계
    • socket.io 를 활용하면서 발생한 버그를 수정하여 프로젝트에 사용하고, socket.io 의 이슈에 코멘트 🔗PR 🔗 작성
  • 꾸준한 문서화 및 팀 개발 블로그 자동화
    • 정적 호스팅을 통한 간단한 팀 개발 블로그 구현
    • 노션을 통한 꾸준한 문서 작성 및 공유로 협업 역량 강화
    • 노션의 문서를 개발 블로그로 배포하는 로직 자동화
    • 매일 아침에 데일리 스크럼🔗, 끝나면서 간단하게 회고🔗 진행하며 동료들과 꾸준한 의견 공유

문제 해결 및 결과

호스트 페이지의 숏 폴링과 트랜스파일링 서버의 변환 감지 로직의 중복

Pasted image 20250105175410.png

  • 문제 상황

    • 트랜스파일링 서버는 ffmpeg 프로세스가 RTMP 청크를 HLS 세그먼트로 트랜스파일링을 완료한 시점에 Object Storage 로 업로드 하는 로직이 필요합니다. 따라서 서버는 트랜스 파일링 완료 시점에 대한 별도의 감지 로직이 필요했습니다.
    • 호스트 페이지는 트랜스파일링 서버에 숏 폴링으로 HLS 세그먼트의 변환이 완료되면 세그먼트 파일을 받아오고 있습니다.
  • 해결 방안

    • 트랜스파일링이 완료되는 시점을 fs.watch 등으로 감지할 수도 있지만, 호스트 페이지에서 HLS 세그먼트를 위한 숏 폴링을 주기적으로 보내고 있었기 때문에 이를 활용한다면 트랜스파일링 서버 내부에는 감지 로직이 필요하지 않을 것이라고 생각했습니다.
    • 그렇게 호스트 페이지에서 숏 폴링으로 HLS 세그먼트를 받는 동시에 Object Storage 에 업로드하도록 로직을 수정해서 감지 로직을 위한 CPU 소모량을 줄였습니다.
    • 하지만 그 결과, Object Storage 에 업로드하는 로직이 호스트 페이지와 강한 의존성을 맺게 되었고 호스트 페이지에서 숏 폴링을 보내지 않는다면 Object Storage 에도 업로드 되지 않는 결과를 낳았습니다.
    • 이러한 강한 의존성을 끊어내고자 트랜스파일링 서버 내부에 감지 로직을 구현하고, 호스트 페이지에 SSE 로 HLS 세그먼트를 보내는 방식을 채택했습니다.
    • 그러나 서비스 특성 상, 트랜스파일링 서버를 확장했을 때 OBS 와 연결된 트랜스파일링 서버가 어떤 서버인지 알아야 호스트 페이지 또한 해당 트랜스파일링 서버에 SSE 연결을 할 수 있습니다.
    • 최종적으로 확장성까지 고려해서 트랜스파일링 서버의 내부 감지 로직을 통해 Object Storage 에 업로드 하고 호스트 페이지가 Object Storage 에 숏폴링으로 HLS 세그먼트를 받아오는 방식으로 구현
  • 결과
    - 호스트 페이지와 트랜스파일링 간에 생기는 강한 의존성을 제거
    - 호스트 페이지의 숏 폴링과 동시에 트랜스파일링 내부의 감지 로직을 위한 CPU 사용 → 트랜스파일링 서버의 내부 감지 로직만을 위한 CPU 사용
    - 호스트 페이지에서 Object Storage 에 업로드 되는 시간동안의 지연 시간이 발생했지만 이는 시청자 페이지와 다르지 않기 때문에 시청자 페이지와 같은 지연시간이 된 것이므로 문제없다고 판단


socket.io 의 Default Room 을 나가면 Sender 를 포함해서 Broadcast 되는 현상

  • 문제 상황

    • socket.io 는 채팅을 하기 위해 room 에 join 하게 됩니다. 같은 room 에 있는 클라이언트는 같은 채팅방에 있는 시스템입니다.
    • socket.io 는 유저의 소켓 연결을 할 때, socket.id 와 동일한 이름의 room (Default Room) 에 자동으로 join 하게 됩니다. 이는 1:1 채팅이나 서버에서 개인에게 공지를 보내는 등의 용도로 사용하게 됩니다.
    • 그러나 저희 서비스는 위와 같은 1:1 채팅이 없는 실시간 라이브 방송의 채팅이므로 이러한 Default Room 은 사용되지 않은 채 서버의 메모리를 낭비할 여지가 있습니다.
    • 따라서 소켓 연결을 할 때 Default Room 에 join 하지 않도록 로직을 수정했는데 연관이 없다고 생각했던 broadcast 로직이 바뀌는 현상이 발생했습니다.
    • broadcast 는 기본적으로 sender 를 제외 하고 다른 사람들에게 이벤트를 보내는 로직인데, Default Room 에서 나간 채로 broadcast 를 하게 되면 Sender 를 포함해서 이벤트를 보내는 로직으로 바뀌는 문제가 발생했습니다. (관련 이슈 🔗)
  • 해결 방안
    문제를 해결하기 위해 3가지 정도의 방법을 생각해보았습니다.

    • socket.io 대신 WebSocket 을 사용하면서 room + broadcast 개념을 직접 구현
    • socket.io 의 room 개념을 그대로 유지한 채로 broadcast 로직을 새롭게 구현
    • socket.io 의 broadcast 로직을 직접 수정

    이 중에서 broadcast 로직을 직접 수정하는 것이 근본적인 문제를 해결할 수 있는 가장 좋은 방법이라 생각했습니다. 그래서 첫 번째로 프로젝트에서 Default Room 을 수정했을 때 Broadcast 로직이 수정되었으므로 room 에서 나가는 로직과 broadcast 간의 관계에 대해 학습했습니다. broadcast 의 로직을 직접 보기 전까지는 sender 를 제외시키는 과정이 sender 의 socket.id 를 제외하는 방식일거라 생각했는데 실제로 확인해본 결과 socket.id 와 같은 room (default room)을 제외시키는 방식이었습니다. default room 을 나가게 되면 해당 room 자체가 사라져버리므로 sender 를 제외시킬 수 없는 문제였습니다.

    따라서 만약 room 이 존재하지 않는다면 연결되어 있는 socket.id 에서 default room 과 같은 socket.id 가 존재하는지의 여부에 따라 제외할 수 있도록 로직을 추가했습니다.

  • 결과

    • 사용하지 않는 Default Room 을 메모리에서 제거 함으로써, 클라이언트 한 명이 연결될때마다 생기던 메모리 낭비를 해결
    • sender 를 포함하여 broadcast 되던 로직을 수정하면서 직접 sender 를 제외시켜야 하는 코드를 없애면서 코드 가독성 증가
    • socket.io 의 이슈에 코멘트 등록 및 컨트리뷰션 가이드라인에 맞게 PR 🔗을 작성했습니다.

채팅 서버의 확장 및 부하 분산

  • 문제 상황
    단일 채팅 서버로도 소수의 클라이언트들의 채팅은 충분히 처리할 수 있었지만, 초기에 기획했던 300명의 채팅 이벤트에 대해서는 불안정한 모습을 보였습니다.
    특히나 트랜스파일링 서버가 CPU 집약적 연산을 위주로 하기 때문에 많은 트랜스파일링과 맞물려 많은 채팅이 오는 경우, 채팅 서버의 확장이 반드시 필요했습니다.

  • 해결 방안
    단일 채팅 서버에서 다중 채팅 서버로 확장함에 따라 채팅 서버 간의 유저, room 등에 대한 정보가 공유되어야 했습니다. 따라서 socket.io 의 기본 Adapter 를 Redis Adapter 로 바꾸어 Redis pub/sub 을 활용해서 채팅 서버 간의 데이터를 공유했습니다. 채팅 서버와 트랜스파일링 서버는 컨테이너로 관리하면서 확장에 용이하도록 Docker Swarm 으로 클러스터링하여 배포했습니다. 초기 목표가 300명 규모였기 때문에 서버 인스턴스가 많이 필요하지 않았고, 복잡한 설정이 요구되지 않았습니다. 따라서 엔터프라이즈 환경에서 주로 사용하는 쿠버네티스 대신, 빠른 설정과 높은 호환성을 제공하는 Docker Swarm을 선택하게 되었습니다.

  • 결과
    400명의 채팅 부하 테스트 시나리오에서, 1대의 NCP(Naver Cloud Platform) 서버 인스턴스와 단일 채팅 서버로는 약 300명 정도의 사용자의 시나리오에서 CPU 사용률이 50퍼센트를 넘었지만, 2대의 NCP 서버 인스턴스3대의 채팅 서버로는 400명의 사용자 시나리오에서도 각각의 인스턴스가 CPU 를 20퍼센트와 30퍼센트 수준으로 부하를 분산하여 확장성과 안정성 향상

그 외


Emotionary (아동 맞춤 정서 검사 서비스)

2022.06 ~ 2023.01

emotionary.png

누원초.jpg

프로젝트 개요
  • 스타트업 기업(노리스페이스, 칠드러닝)과 연계하여 아동에게 적합한 정서 검사 서비스 설계
    • 주기적으로 검사해야하는 아동 정서 검사의 비용 문제 해결
    • 검사 진행과 검사 결과를 바로 볼 수 있도록 어플리케이션으로 설계
    • 아동에 맞춘 시청각 자료를 활용한 스토리텔링 검사
  • 기술 스택 : Kotlin, AWS, Docker
주요 활동 및 성과
  • xml 기반의 안드로이드 화면 구현
    • 앱 시작 시, 칠드러닝 기업의 로고를 띄우는 시간 동안 coroutine 을 활용하여 검사 이미지를 미리 로딩하여 사용자 경험 개선
  • 실제 사용자 테스트 및 피드백을 반영하며 사용자 중심의 어플리케이션 설계
    • 누원초등학교 학생들을 대상으로 검사 진행 및 피드백 반영
    • 초등학생은 집중력을 길게 유지하기 힘드므로 검사 문항자체를 짧게 수정
    • 집에서 검사를 진행할 경우 학부모의 개입이 있을 수 있어서 학교에서 진행하는 것을 선호
    • 학교 소유의 태블릿을 주로 활용하므로 넓은 가로의 반응형 디자인
    • 초등학생들이 힘들어하는 부분을 직접 옆에서 도와주면서 피드백 반영 (아이콘, 화면전환 등)
  • 지속적인 리팩토링
    • 공식 프로젝트 기간이 끝난 후 리팩토링 및 현업 개발자 피드백을 위해서 대표님께 직접 찾아가 인턴으로 합류
    • 코드 수정 시, GitHub Action 으로 EC2 에 자동 배포함으로써 개발 편의성 증가


🎓 활동 및 교육

당근(인터널 프로덕트팀, 인턴)

2025.02 ~ 2025.05

  • 당근의 전사 구성원들의 업무 효율성을 높이기 위한 플랫폼 개발
  • 사내 계정 관리 시스템 개발 및 관리
  • 사내의 다양한 지식 공유 세션 참여

네이버 부스트 캠프 9기

베이직, 챌린지, 멤버십
2024.07 ~ 2024.12

  • CS 와 기본기를 강조한 학습
  • 코드 리뷰, 페어 프로그래밍, 데일리 스크럼을 통한 협업 과정 경험
  • 팀 블로그, 깃허브 위키, 노션 등을 활용한 체계적인 문서화

Norispace (개발팀, 인턴)

2023.01 ~ 2023.03

  • 아동 맞춤 정서 검사 서비스 유지보수
  • 네이버 OCR AI 모델을 활용한 동물병원 영수증 분류 프로젝트를 진행
  • 이후 사내 OCR 모델로 변경 후, 사내 데모 서비스로 활용
  • 간단한 프론트엔드부터 FastAPI 로 서버 설계

코딩교육봉사

2022.08 ~ 2022.11

  • 초등학생 5~6학년을 대상으로 코딩교육봉사를 진행
  • 변수, 함수, 조건문의 개념을 최대한 쉽게 풀어 설명
  • 엔트리를 활용해서 흥미를 유발하는 실습을 진행

ViralPro (개발팀)

2019.10.01 ~ 2020.03.01

  • 인플루언서와 소규모 광고주 연결 이라는 주제로 창업한 학교 동기와 개발
  • Youtube API 를 활용해서 인플루언서들을 구독자 순, 동영상 순 등의 기준으로 정렬한 페이지를 php 로 작성하거나 ec2 Lambda 로 인플루언서 정보 갱신을 위한 cronjob 함수 설계

건국대학교

소프트웨어학과
2018.03 ~ 2025.02 졸업

  • 다양한 프로그래밍 언어와 기술 지식 학습
  • 기업(노리스페이스) 연계 프로젝트 수업으로 팀원과의 협업 역량 강화
  • 프로젝트를 지속적으로 유지보수 및 개발하고 싶어서 노리스페이스의 인턴 경험

영동일고등학교

2013.03 ~ 2016.02 졸업


병역 사항

육군 3사단 정보통신대대

2020.06.01 ~ 2021.12.01
병장 만기전역