서재

박종건

2026
박종건
박종건Park jong geon
  • Email · patrol4@naver.com
  • Tel · 010-4393-7941
  • GitHub · github.com/PARKJGN
  • Blog · velog.io/@patrol4

백엔드와 프런트엔드를 오가며 AI 법률 지원 SaaS 플랫폼과 정산 시스템을 개발·운영해온 2년 차 개발자 박종건입니다.

처음에는 기능 구현에 집중했지만, 서비스를 운영하며 느린 조회, 무거운 이미지, 오래 걸리는 알림 발송 같은 병목을 직접 마주했습니다.

쿼리 최적화와 인덱싱으로 조회 속도를 4초에서 0.2초로, WebP 변환으로 이미지 용량을 70% 줄이고, 배치 발송 구조 개선으로 대량 알림 처리 시간을 크게 단축하며 문제를 하나씩 해결해 왔습니다. 디자인 시스템과 공통 컴포넌트 구축처럼 팀의 개발 효율을 높이는 작업에도 꾸준히 기여했습니다.

이 과정에서 '동작하는 코드'와 '좋은 시스템'의 차이를 배웠고, 문제를 만나면 원인을 끝까지 파고들어 그 차이를 좁혀가는 개발자가 되고자 합니다.

  • Spring

    AI 법률 SaaS 와 정산 시스템의 API 를 Spring Boot 로 설계하고 운영했습니다. JPA 로 도메인 모델을 다루고 트랜잭션 경계를 관리합니다.

  • React

    함수형 컴포넌트와 훅으로 상태와 렌더링을 관리하는 화면을 만듭니다. 사이드 프로젝트 oneBite 의 앱과 웹을 직접 만들었습니다.

  • Vue

    실무 화면 대부분을 Vue 로 만들며 공통 컴포넌트 약 30종을 표준화했습니다. Composition API 로 반응형 상태와 컴포넌트를 구성합니다.

  • PostgreSQL

    스키마를 정규화해 설계하고 인덱싱 전략을 세웁니다. 업체 목록 조회 쿼리를 리팩터링해 4초를 0.2초로 줄였습니다.

1 / 1

경력

2024–2026

알리자

주식회사 코어소프트 · 2024.04 – 2026.01

매장 예약과 상품 판매, 그 뒤의 정산까지 한 번에 도는 커머스 플랫폼입니다. 소비자 앱·매장용 앱·샵관리자·본사 어드민 네 개 화면을 오가며 개발했습니다. Spring 4.3 과 MyBatis 로 된 오래된 코드 위에서 2년 가까이 일했습니다.

느린 건 데이터가 아니라 쿼리의 모양이었다

관리자 업체 목록이 4초 걸렸습니다. 데이터가 많아서라고 생각하기 쉬운데, 쿼리를 뜯어 보니 회원 수·재방문율·결제 금액을 구하는 집계가 업체 한 줄마다 따로 돌고 있었습니다. 목록에 업체가 100개면 집계도 100번 돌았습니다. 대표 이미지 한 장을 고르는 부분도 min(sort) 서브쿼리로 매번 전체를 훑었습니다.

집계를 CTE 세 개로 미리 한 번에 만들어 조인으로 붙이고, 이미지는 정렬 후 하나만 가져오는 LATERAL 조인으로 바꿨습니다. 4초가 0.2초가 됐습니다. 제품 관리 목록도 같은 모양이었습니다 — 브랜드명·사진 경로·대분류·중분류를 각각 스칼라 서브쿼리로 꺼내고 있어서, 조인으로 펴고 인덱스를 얹어 10배 줄였습니다.

같은 데이터, 같은 인덱스인데 쿼리를 어떻게 쓰느냐로 스무 배가 갈렸습니다. 그 뒤로는 느리다는 말을 들으면 데이터 양보다 실행 계획의 모양을 먼저 봅니다.

발송 속도와 실패율은 다른 문제였다

알림을 HTTP 로 한 건씩 보내고 있어 대량 발송이 느렸습니다. Firebase Admin SDK 로 옮겨 토큰 500개씩 묶어 보내니 시간 문제는 풀렸습니다.

남은 건 실패율이었는데, 이건 속도와 다른 원인이었습니다. 배치 응답을 토큰 단위로 훑어 보니 실패의 상당수가 앱을 지운 기기의 죽은 토큰이었습니다. 계속 보내니 계속 실패하는 구조였습니다. UNREGISTERED 로 돌아온 토큰을 따로 모아 무효 처리하고 나서야 실패율이 떨어졌습니다.

묶어 보내는 것으로 끝냈다면 숫자는 좋아 보여도 실패는 그대로였을 겁니다. 응답을 한 건씩 확인하지 않았으면 몰랐을 일입니다.

용량을 줄이기 전에 저장하는 방식이 문제였다

이미지가 무겁다는 이야기가 나왔을 때, 처음 본 것은 변환이 아니라 저장 방식이었습니다. HTML 에디터에 이미지를 붙여넣으면 Base64 로 본문 안에 통째로 박혀 DB 에 들어가고 있었습니다. 글 한 줄을 불러오는데 이미지가 딸려 오는 셈이었습니다.

붙여넣는 순간 파일 서버에 저장하고 본문에는 URL 만 남기도록 먼저 바꿨습니다. 그다음 업로드 시점에 WebP 로 자동 변환하게 만들어 평균 용량을 약 70% 줄였고, 상품 상세에는 지연 로딩을 붙여 스크롤이 닿기 전에는 내려받지 않게 했습니다.

순서를 반대로 했다면 WebP 로 줄인 이미지를 여전히 Base64 로 본문에 박고 있었을 겁니다.

그 밖에

  • 전문가용·사업자용 모바일 웹을 V2 로 새로 만들며 화면 대부분을 맡았습니다.
  • 손으로 맞추던 매장·BC 정산을 신청·승인·조회 흐름으로 옮기고 집계 쿼리를 최적화했습니다.
  • 쇼핑몰 상품 목록·상세의 초기 API 호출을 걷어내 체감 속도를 끌어올렸습니다.
  • Cordova 앱 2종의 카메라 권한·iOS QR 스캐너·스토어 배포를 맡았습니다.
  • 공통 UI 컴포넌트 약 30종을 표준화하고 디자인 가이드를 만들었습니다.
  • Java 11 업그레이드에 대응하고 p6spy 로 SQL 로그를 정리했습니다.
  • 개발 언어 · Java 11, Spring 4.3, JSP, JavaScript, Vue 2
  • 사용 툴 · PostgreSQL, MyBatis, Firebase Admin SDK, Cordova

LawPilot

주식회사 코어소프트 · 2025.06 – 2026.01

생성형 AI 로 법률 업무를 돕는 SaaS 입니다. 저장소를 처음 만들어 백엔드·프런트·배포까지 서비스 전체를 맡았고, AI 모델은 Python 개발자가 맡았습니다.

몇 분 걸리는 일을 기다리게 만드는 법

사건 정보를 넣으면 인터뷰·서면·심리·판결 순으로 AI 가 재판을 따라갑니다. 한 단계에 몇 분씩 걸리는데, 그동안 화면이 아무 말도 하지 않으면 사용자는 멈춘 줄 압니다. 더 큰 문제는 그 사이에 새로고침하거나 창을 닫으면 진행하던 것이 사라진다는 것이었습니다.

진행 상태를 클라이언트가 아니라 서버가 들고 있게 했습니다. 어느 단계인지, 지금까지 나온 중간 결과가 무엇인지를 서버에 두고 WebSocket 으로 흘려보냈습니다. 다시 접속하면 서버에 남은 진행 중인 작업을 찾아 그 지점부터 이어 붙입니다.

오래 걸리는 작업은 빨리 만드는 것보다 중간에 끊겨도 괜찮게 만드는 편이 낫다고 봤습니다. AI 응답 시간은 우리가 줄일 수 있는 것이 아니었습니다.

돈이 걸린 자리에선 되돌릴 수 있어야 했다

기관이 쓰는 서비스라 계정만으로는 팔 수 없었습니다. 기관을 먼저 등록하고 그 아이디로 소속 사용자를 만드는 흐름을 세우고, 가입 때 국세청 사업자등록 상태 조회 API 로 실제 사업자인지 확인했습니다. 결제는 토스페이먼츠 빌링키로 정기결제를 붙였습니다.

까다로웠던 것은 사용량이었습니다. AI 를 부를 때마다 회사 토큰을 차감하는데, AI 호출은 실패할 수 있습니다. 차감만 하고 결과를 못 주면 돈을 받고 아무것도 안 준 것이 됩니다. 차감을 기록으로 남기고 호출이 실패하면 되돌리도록 맞췄습니다.

기능이 실패하는 것보다 실패한 흔적이 잘못 남는 것이 더 큰 문제인 자리가 있다는 걸 배웠습니다.

법조계는 아직 HWP 를 쓴다

기술 선택이 아니라 사용자가 쓰는 형식에 맞춰야 하는 일이었습니다. PDFBox 로 PDF 에서 글을 뽑고, docx4j 로 목차와 제목 서식을 갖춘 DOCX 를 만들고, hwplib 으로 HWP 를 읽었습니다.

처음에는 문서를 프런트에서 만들었는데, 화면마다 만드는 코드가 갈라져 같은 검토서인데 받는 곳에 따라 서식이 달랐습니다. 문서 생성을 전부 백엔드로 옮겨 어디서 받아도 같은 파일이 나오게 했습니다.

그 밖에

  • 법률 검토서를 정식판과 lite 판으로 나눠 만들고, 이후 대화형 채팅으로 확장했습니다.
  • 답변 스트리밍, 파일 첨부, 판례·법령 하이퍼링크, 문서 내려받기, 답변 피드백을 붙였습니다.
  • Python 벡터 검색 API 를 연동해 사건과 비슷한 판례·법령을 추천했습니다.
  • Docker Compose 로 개발·운영 구성을 나누고 nginx·HTTPS 를 붙였습니다.
  • 개발 언어 · Java 17, Spring Boot 3.5, JavaScript, Vue 3
  • 사용 툴 · PostgreSQL, JPA, WebSocket, Docker, nginx, 토스페이먼츠, PDFBox·docx4j·hwplib
1 / 1

oneBite

2026

무엇을 만들었나

관심 있는 카테고리를 조합해 구독해 두면, 매일 오전 8시에 AI 가 요약한 뉴스레터를 푸시로 받아보는 모바일·웹 서비스입니다. 백엔드부터 앱, 웹, 인프라까지 혼자 설계하고 만들었습니다.

어떻게 만들었나

  • 백엔드는 Kotlin 과 Spring Boot 로 헥사고날 아키텍처를 잡고 JPA·PostgreSQL·Flyway 를 올렸습니다. 푸시 팬아웃은 Kafka 로 비동기 처리합니다.
  • 인증은 JWT 액세스 토큰 30분 + 회전형 리프레시 토큰 30일의 무상태 구조로 만들고, 401 이 오면 클라이언트가 알아서 재발급받게 했습니다.
  • RSS 수집 → Claude 로 요약 → 에디션 생성 → APNs/FCM 발송을 n8n 배치가 15분 주기로 오케스트레이션합니다.
  • 앱은 React Native 에 Zustand·TanStack Query 를, 웹은 Next.js 를 썼습니다. Google·Kakao·Naver 소셜 로그인 3종을 붙였습니다.

무엇을 고민했나

같은 카테고리 조합을 구독한 사람이 여럿이면 요약도 여러 번 돌아야 할까. 그렇지 않게 하려고 에디션을 (카테고리 조합 · 언어 · 발행일) 단위로 만들어 공유하게 설계했습니다. 덕분에 LLM 호출이 사용자 수와 무관하게 조합당 하루 한 번으로 고정되고, 같은 내용을 두 번 만드는 일이 없습니다.

배포는 라즈베리파이 ARM64 3노드 쿠버네티스 클러스터에 올렸습니다. amd64/arm64 멀티아치 이미지를 GitHub Actions 로 굽고, 기동이 90초쯤 걸리는 문제는 startupProbe 로 받아냈습니다. App Store 와 Google Play 출시도 EAS 빌드부터 아이콘·정책 문서·심사 대응까지 직접 했습니다.

1 / 1

우리의 가운데는 여기다

2024

무엇을 만들었나

이사를 자주 다니다 보니 친구들과 거리가 멀어졌고, 만날 때마다 제가 먼 길을 가는 일이 많았습니다. 그럼 아예 가운데를 구해 주자는 생각으로 만든 서비스입니다.

혼자서 여러 장소를 입력해 결과를 공유할 수도 있고, 방을 만들어 여러 명이 같은 방에서 각자의 장소를 넣을 수도 있습니다.

개발 기간은 2024년 3월 26일부터 4월 11일까지, 혼자 만들었습니다. Java 17 · Spring Boot · JPA · Thymeleaf · MySQL 로 만들었고 장소 검색은 Kakao API 를 썼습니다.

가운데를 어떻게 구했나

입력한 장소들을 이어 다각형을 그리고, 그 도형의 무게 중심을 구하는 방식입니다. 문제는 무게 중심 공식을 쓰려면 좌표가 도형을 그리는 순서대로 정렬돼 있어야 한다는 점이었습니다.

x 축의 최댓값과 최솟값 가운데에 세로선을 하나 긋고, 왼쪽은 y 가 작은 값에서 큰 값으로, 오른쪽은 y 가 큰 값에서 작은 값으로 이으면 선이 서로 겹치지 않는 다각형이 됩니다. 그 순서로 정렬한 다음 무게 중심을 구했습니다.

무엇을 배웠나

없는 주소를 입력하면 예상과 달리 NoHandlerFoundException 이 아니라 NoResourceFoundException 이 떴습니다. 매핑되는 핸들러가 없으면 SimpleUrlHandlerMapping 의 /** 규칙이 ResourceHttpRequestHandler 를 돌려주기 때문이었습니다. 정적 경로 패턴을 /static/** 로 옮겨 /** 를 비워 두니 의도한 예외가 제대로 났습니다.

또 하나는 예외 응답 형식이었습니다. JSON 을 돌려주는 메서드를 RestController 와 Controller 에서 가리지 않고 쓴 탓에, 페이지에서 나야 할 오류가 JSON 으로 튀어나왔습니다. 페이지용 오류 처리를 따로 만들어 나눴습니다. 공부만 하던 JPA 와 ExceptionHandler 를 몸으로 익힌 프로젝트였습니다.

1 / 1

하루를 담다

2024

무엇을 만들었나

사용자의 취향 데이터를 분석하고 크롤링한 장소 정보를 정제해, 하루 일정을 추천해 주는 맞춤형 서비스입니다. 한국ICT인재개발원 과정에서 다섯 명이 함께 만들었고, 개발 기간은 2024년 1월 5일부터 31일까지였습니다.

드래그 앤 드롭으로 일정을 짜고, SSE 로 실시간 알림을 받고, 자카드 유사도로 취향이 비슷한 사용자를 찾아 장소를 추천하는 것이 핵심 기능이었습니다. Spring Boot · JavaScript · jQuery · Python · MySQL · MongoDB 를 썼습니다.

무엇을 맡았나

  • DB 설계 — 정규화로 데이터 무결성을 지키고 엔터티 간 관계를 매핑했습니다.
  • 웹 서버 배포 — AWS EC2 와 RDS 로 배포를 맡았습니다.
  • 스케줄 메이킹 — jQueryUI 로 드래그·드롭·리사이즈를 구현하고, TMAP API 로 이동 시간을 보여 줬습니다.
  • 장소 추천 — Python 에서 자카드 유사도로 사용자 간 유사도를 재고, 그 결과를 스프링과 웹소켓으로 주고받았습니다.
  • 형상 관리 — merge 충돌을 점검하고 팀원과 이야기하며 코드를 정리했습니다.

무엇을 배웠나

TMAP API 를 부를 때 async/await 과 then 을 섞어 쓰다 비동기 처리에서 헤맸습니다. Promise 를 제대로 정리하는 계기가 됐고, 스타일은 한쪽으로 통일하는 게 낫다는 걸 배웠습니다.

드래그·리사이즈·클릭 이벤트가 서로 충돌해 마우스 관련 오류가 계속 났습니다. 이벤트를 하나씩 짚어 가며 잡는 과정에서 이벤트 핸들러의 동작을 훨씬 잘 이해하게 됐습니다.

서울 장소 2만여 건을 크롤링할 때는 같은 사이트라도 동적 페이지 구조가 제각각이라 예외 처리와 자동화가 까다로웠습니다. 한 페이지만 보고 규칙을 정하면 안 된다는 걸 알게 됐습니다.

아쉬운 점도 남았습니다. 예외 처리를 충분히 하지 못해 WAS 기본 오류 페이지가 그대로 노출됐고, 드래그·리사이즈에 시간을 너무 써서 뒤가 촉박했습니다. 써 보고 싶던 JPA·React·JWT 는 팀에 아는 사람이 없어 결국 다음으로 미뤘습니다.

1 / 1

꽃사수

2023

무엇을 만들었나

꽃은 좋아하지만 길러 본 적은 없는 사람들을 위한 꽃 화분 판매 사이트입니다. 한국ICT인재개발원 과정에서 다섯 명이 2023년 11월 6일부터 17일까지 만든, 제 첫 개발 프로젝트입니다.

꽃 이름이나 종목을 몰라도 찾아볼 수 있는 쉬운 카테고리, 키우는 환경을 조건으로 거는 검색 필터, 의미 있는 꽃을 고르고 싶은 사람을 위한 꽃말 검색을 넣었습니다. Spring · JavaScript · jQuery · JSP · MySQL 로 만들었습니다.

무엇을 맡았나

  • DB 설계 — 정규화로 데이터 무결성을 지키고 엔터티 간 관계를 매핑했습니다.
  • 결제 연동 — 아임포트 API 로 카카오페이 결제를 붙였습니다.
  • 내부 로직 — 장바구니, 주문 상세, 마이페이지를 구현했습니다.
  • 형상 관리 — merge 충돌을 점검하고 팀원과 이야기하며 코드를 정리했습니다.

무엇을 배웠나

JSP 폼에서 여러 개의 모델을 컨트롤러로 넘기는 방법을 몰라 한참 막혔습니다. 리스트를 멤버 변수로 가지는 모델 하나를 만들어 바인딩하는 방식으로 풀면서 @ModelAttribute 가 무엇을 하는지, 데이터가 어떻게 바인딩되는지 알게 됐습니다.

메인 페이지에 태그를 겹치지 않게 랜덤한 위치로 뿌리는 것도 만만치 않았습니다. 엘리먼트 크기와 뷰포트를 공부하게 된 계기였습니다.

돌아보면 아쉬운 것이 둘 있습니다. 하나는 소통입니다. 기간이 짧고 다들 처음이라 각자 할 일에 파묻혀 서로의 코드를 보지 못했습니다. 짧게라도 리뷰하고 데일리 스크럼을 했다면 훨씬 나았을 겁니다. 다른 하나는 주문 번호입니다. 시간을 조합해 PK 를 만들었는데, 같은 시각에 주문이 둘 들어오면 반드시 깨지는 설계였습니다. 고유 식별을 어떻게 보장할지 그때부터 계속 생각하게 됐습니다.

1 / 1

방명록

2026

다녀가셨다는 흔적을 남겨 주세요. 이름과 하고 싶은 말이면 충분합니다. 이메일도 비밀번호도 받지 않습니다 — 적게 받을수록 지킬 것이 적습니다.

남기신 글은 바로 이 아래에 쌓입니다. 다만 광고나 욕설로 판단되면 보이지 않고, 제가 확인한 뒤에 올라옵니다. 멀쩡한 글이 잘못 걸리는 일도 있으니, 한참 지나도 보이지 않으면 patrol4@naver.com 으로 알려 주세요.

지운 글은 되돌릴 수 없습니다. 남긴 글을 지우고 싶으시면 같은 주소로 말씀해 주세요.

남기신 글은 스팸·욕설 판정을 위해 외부 서비스로 전송됩니다. 그 밖의 용도로는 쓰지 않습니다.


불러오는 중…

1 / 1