~/brunosong

송호식 · 백엔드 13년차

만드는 것까지가 아니라
운영되는 상태까지 만듭니다.

에듀테크와 보험 도메인에서 서비스를 설계하고 레거시를 옮겼습니다. 그 시스템이 실제로 돌아가도록 관측과 배포 기반까지 함께 세웠습니다.

AI에게 물어보세요

준비 중

이력, 기술 선택의 이유, 홈랩 운영 방식까지, 제 자료를 학습한 봇이 대신 답합니다.

질문에 답하는 봇을 붙이는 중입니다. 준비되면 이 자리에서 바로 물어볼 수 있게 하겠습니다.

아키텍처 설계

도메인 경계를 긋고, 그 경계가 시간이 지나도 무너지지 않게 설계합니다.

원인까지 파고드는 방식

같은 패턴 6건

증상에 맞춰 대응하지 않고, 왜 그렇게 됐는지까지 보고 고칩니다.

프로젝트

5

구인구직 시스템

외주 프로젝트

2025.09 – 2026.07 · 백엔드 · 전체 아키텍처 설계

보험설계사 구인구직 플랫폼입니다. 바운디드 컨텍스트 15개를 헥사고날 레이어 모듈로 갈라, 의존 방향을 사람이 아니라 Maven 이 컴파일 타임에 막게 만들었습니다.

개발자 2명이 만들었고, 포털과 어드민 백엔드 설계를 전부 맡았습니다. 개발은 마무리했고 서비스는 운영 중입니다.

BC 15개 · Maven 모듈 102개 · Entity 125개
도메인 7개를 별도 레포로 떼어내 MSA 전환 검증
브론즈·실버·골드 3계층 레이크 위에 인재추천 에이전트
Spring Boot헥사고날모듈러 모놀리스MSAPostgreSQL

비바샘 시스템 안정화

실무 프로젝트

비상교육 · 2026.04 – 2026.10 · 백엔드 · 안정화 전반

교사용 수업지원 서비스의 안정화를 맡아 관측, 회귀 검증, 스키마 관리, 구조 재설계, 인증 개선 다섯 갈래로 나눠 진행하고 있습니다.

지금 주력은 어드민에 붙어 있던 문서변환을 별도 서비스로 떼어내는 일입니다.

Prometheus 수집 체계와 MySQL 장애 지표 정의
Playwright E2E 도메인 5개 · 클래스 44개, 운영 중
문서변환 문제 24건을 원인별로 묶어 재설계, 개발 중
Spring BootPrometheusPlaywrightFlywayMySQL

차세대 시스템 출력물 재설계

실무 프로젝트

삼성화재 · 2024.12 – 2026.02 · 백엔드 · 출력물 단독 설계 및 구현

대규모 차세대 프로젝트에서 일반보험 출력물 전체를 맡아, 1만 줄 규모의 레거시를 단독으로 재설계했습니다.

12개+ 상품군 출력물 전체를 단독 담당
메인 흐름 1,300줄 → 50줄로 정리
어노테이션 + 리플렉션 자동 라우팅으로 수동 설정 연결 제거
JavaSpring BootJPAMyBatisOracle

관측 체계 구축과 레거시 현대화

실무 프로젝트

웅진씽크빅 · 2022.10 – 2024.12 · 백엔드 · 현대화 및 관측 체계 주도

레거시 20개+ 를 Spring Boot 로 옮기고, 관측 체계를 작은 범위에서 먼저 검증해 공식 도입시켰습니다. 장애를 겪고 나서 아는 구조를 지표로 먼저 보는 구조로 바꿨습니다.

관측 도입 뒤 장애 월 0건 유지
레거시 20개+ 프로젝트를 단독으로 Spring Boot 전환
FTP 수동 배포 → Jenkins CI/CD, 태그 기준 롤백 확보
Spring BootKubernetesKafkaOpenTelemetryGrafana

온프레미스 배포·모니터링 현대화

실무 프로젝트

비상교육 · 2020.07 – 2022.10 · 백엔드 · PL(4명)

윈도우 파일서버에 묶여 있던 구조를 리눅스 독립 구조로 옮기고 무중단 배포를 도입했습니다. PL 로 서비스 분리를 리딩했습니다.

Nginx 블루-그린 무중단 배포로 배포 다운타임 제거
프로시저 50개+ 를 애플리케이션으로 이관해 DB 락 해소
유료 APM 을 Scouter + ELK + Sentry 조합으로 대체
Spring BootNginxRedisSpring BatchELK

코드 스타일

데이터 이관 시스템 (창작 프로젝트)

DB 커밋과 메시지 전송은 한 트랜잭션으로 묶이지 않습니다. 보내고 커밋이 깨지면 없던 일을 알린 것이고, 커밋하고 보내다 죽으면 아무도 모릅니다. 그래서 보내지 않고 같은 트랜잭션에 적어 두고, 나중에 따로 집어 보냅니다. 상태를 닫는 시점을 어디로 잡느냐가 이 구조의 전부입니다.

전송 로그와 아웃박스 행을 한 트랜잭션에서 같이 적습니다. 여기서는 카프카를 부르지 않습니다. 이 메서드가 커밋되면 보낼 것이 남았다는 사실까지 함께 남습니다.

transfer-application-service/…/handler/TransferExecutionHandler.java
@Component
@RequiredArgsConstructor
public class TransferExecutionHandler {

    private final TransferPersistHelper transferPersistHelper;
    private final DataTransferOutboxHelper dataTransferOutboxHelper;
    private final TransferDataMapper transferDataMapper;


    @Transactional
    public Transfer sendData(Transfer transfer, SourceContentData sourceContentData) {

        List<TransferRequestEvent> transferRequestEvents = transferPersistHelper.persistTransferLog(transfer,sourceContentData);

        for (TransferRequestEvent transferRequestEvent : transferRequestEvents) {

            DataTransferEventPayload dataTransferEventPayload =
                    transferDataMapper.transferRequestEventToDataTransferEventPayload(transferRequestEvent);

            dataTransferOutboxHelper.saveDataTransferOutboxMessage(dataTransferEventPayload,
                    UUID.randomUUID());

        }

        updateTransferSendResult(transfer);

        return transfer;
    }


    public void updateTransferSendResult(Transfer transfer) {
        transferPersistHelper.updateTransferSendResult(transfer);
    }

}
직접 만든 창작 프로젝트의 실제 소스입니다. package 와 import, 그리고 다음 줄을 그대로 옮겨 적은 주석을 걷어냈습니다. 길이 때문에 뺀 자리는 코드 안에 표시했습니다. 판단이 담긴 주석은 원본 그대로입니다.

소개

백엔드 개발자 · 13년차

송호식

기능을 붙이는 일보다, 그 기능이 새벽에 멈췄을 때 무슨 일이 벌어지는지 보이게 만드는 일을 주로 해왔습니다. 관측 체계와 배포 파이프라인을 세우고, 레거시를 옮기고, 프로시저에 갇힌 로직을 애플리케이션으로 꺼내는 일들입니다.

기술은 근거가 설 때만 고릅니다. 데이터 이관 방식을 정할 때는 CDC와 서비스 자체 처리를 먼저 검토해 왜 맞지 않는지 확인한 뒤에 Kafka를 골랐고, 도입 승인이 나지 않았을 때는 작은 범위에서 효과를 먼저 증명하고 공식 도입을 받아냈습니다. 이 사이트에 올린 것들도 같은 방식으로 만들었습니다. 무엇을 골랐는지보다 무엇을 버렸는지를 남겨 두려고 합니다.

더 궁금한 것이 있다면 AI에게 물어보세요 →

Spring Boot레거시 현대화ObservabilityKubernetes
GitHub
github.com/brunosong
Email
playprogramer@gmail.com