jihwang.kim
Professional Project · 2026

Solution Square (Global)

2025 – Present

목적

제품 정보, 기술 자료, 선택 도구와 엔지니어링 지식을 여러 지역과 언어로 제공하는 LS ELECTRIC의 글로벌 고객 포털입니다.

역할 · 기술스택

Java/Spring 기반 백엔드 서비스와 프론트엔드 요청을 받는 API 서버(BFF), React·TypeScript 프런트엔드에서 제품·대시보드·검색·AI 서비스 개발에 참여했습니다.

Java · Spring Boot · React · TypeScript · Azure · Elasticsearch · Jenkins

JavaSpring BootReactTypeScriptAzureElasticsearchJenkins

성과 01

인증 로직 공통화

배경·원인
글로벌 포털과 자산 관리 서비스는 같은 뿌리에서 출발한 제품이라, 프론트엔드의 요청을 받아 인증과 백엔드 연계를 담당하는 API 서버(BFF)도 처음에는 하나였습니다. 담당 조직이 분리되면서 자산 관리 서비스 쪽에 같은 역할의 API 서버가 별도로 생겼고, 인증 로직이 하드카피로 중복된 채 각자 수정되기 시작했습니다. 한쪽의 수정이 다른 쪽에 반영되지 않아 인증 동작이 미묘하게 달라졌고, 문제가 생겨도 원인 파악이 어려웠습니다.
고민·선택 이유
별도 인증 서버로 분리하는 안을 먼저 검토했지만 배제했습니다. 운영 대상이 하나 늘고 모든 요청에 네트워크 홉이 붙는 비용을, 두 서비스 규모에서 감수할 이유가 없었습니다. 대신 이미 공통 모듈을 두는 저장소 관례가 있어 그 관례를 따르면 구조 변화 없이 변경 폭이 가장 작았습니다. 추출은 세션 → 인증 토큰·SAML 유틸 → JWT 순으로 나눴는데, 한 번에 옮기면 문제가 생겼을 때 원인 범위가 넓어지므로 단계마다 검증하고 넘어가기 위해서였습니다. 어댑터를 둔 것도 같은 이유로, 두 애플리케이션의 코드를 한 번에 바꾸지 않고 연결점만 교체하기 위해서입니다.
결과
인증 로직 변경이 한 곳의 수정으로 끝나게 되었고 두 애플리케이션의 인증 동작이 같아졌습니다. 이관하며 남은 dead code와 중복 의존성을 정리해 JWT 라이브러리도 단일 소유로 통일했습니다.
회고
레거시 개선은 한 번에 갈아엎는 것보다, 기존 관례를 따라 변경 폭을 줄이고 검증 가능한 단위로 나눠 옮기는 쪽이 안전하다는 기준을 얻었습니다.

성과 02

알림 템플릿·수신자 관리 시스템 구축

배경·원인
이메일 알림 템플릿이 언어별 HTML 파일 54개로 하드코딩돼 있었습니다. 템플릿마다 요청 클래스와 엔드포인트가 따로 있어 알림 종류가 늘수록 코드가 선형으로 늘었습니다. 문구나 수신자를 바꾸는 데도 배포가 필요해 단일 관리 지점이 없었습니다.
고민·선택 이유
템플릿을 코드가 아니라 데이터로 옮기기로 한 것은, 문구·수신자 변경을 배포에서 분리해야 관리자가 직접 다룰 수 있기 때문입니다. 템플릿의 식별을 채널·이벤트 타입·서비스 타입·언어 네 개 축의 조합으로 모델링한 것은, 새 알림이 코드 추가가 아니라 행 추가로 끝나게 하기 위해서입니다. 수신자를 템플릿에 묶지 않고 별도 레지스트리로 분리한 것은, 조직이나 담당자가 바뀔 때 수신자만 바꾸면 되게 하려는 것입니다. 개별 REST API 위에 관리 화면용 통합 API를 더한 것은 화면의 API 왕복을 줄이기 위해서입니다. 발송 구현체는 공통 템플릿 발송 하나로 수렴시켜 템플릿마다 발송 코드가 생기던 구조를 끊었습니다.
결과
관리자가 배포 없이 템플릿과 수신자를 동적으로 관리할 수 있게 됐고, 이후 신규 기능의 알림이 코드 추가 없이 기존 발송 로직을 재활용해 연결됐습니다. 수신자·발송 이력은 개인정보 암호화 대상으로 함께 정리했습니다.
회고
같은 모양의 코드가 반복 증식하는 것은 데이터 모델 부재의 신호이며, 식별 축을 데이터로 옮기면 새 요구가 코드 추가가 아니라 행 추가로 끝난다는 기준을 얻었습니다.

성과 03

개인정보 암호화와 검색의 충돌

배경·원인
개인정보 보호 기준을 높이기 위해 이름·연락처 같은 필드를 암호화해야 했는데, 암호화하면 그 값을 조건으로 하던 기존 동등 검색이 깨집니다. 보호와 검색 가능성이 정면으로 충돌하는 문제였습니다.
고민·선택 이유
암호화를 먼저 하고 검색을 나중에 푸는 순서도 가능했습니다. 다만 그 사이 평문 검색 경로가 남으면 영구히 유지될 위험이 있어, 봉투 암호화와 블라인드 인덱스를 처음부터 함께 설계했습니다. 봉투 방식을 고른 것은 암호문에 키 버전을 함께 저장해 나중에 키를 교체해도 재암호화 경로가 남게 하기 위해서입니다. 운영 중인 데이터가 있어 한 번의 배포 대신 쓰기 → 검색 → 백필 순으로 단계를 나눴습니다. 전환 기간에는 평문과 암호문을 모두 읽게 두었습니다 — 단계 중간에 문제가 생겨도 서비스가 멈추지 않아야 하기 때문입니다.
결과
암호화된 값으로도 동등 검색이 유지되는 상태로 운영 데이터에 단계적으로 적용했습니다. 백필은 중단 후 재실행해도 안전하도록 행 상태 기준으로 재개하게 만들었습니다.
회고
보안 요구는 기능을 깨지 않는 전환 경로까지 설계해야 운영 중인 시스템에 적용할 수 있습니다. 암호화 전환은 각 단계가 재진입 가능한 상태 전이여야 한다는 기준을 얻었습니다.

성과 04

배포 알림·연속 배포 자동화

배경·원인
여러 모듈을 배포하는 환경에서 누가 언제 배포했는지 팀에 공유되지 않았고, 커밋 단위 코드리뷰에서 놓치는 부분이 생길 수 있었습니다. 빌드 서버의 메모리 제약으로 모듈을 병렬 빌드할 수 없어 한 개씩 연속으로 빌드해야 했습니다. 앞 빌드가 끝나기를 사람이 기다렸다가 수동으로 다음 배포를 이어가고 있었습니다.
고민·선택 이유
알림 채널은 팀이 일상적으로 보는 팀즈를 기본으로 두고, 전송 실패 시 이메일로 폴백되게 이중화했습니다. 한 채널의 장애로 알림이 끊기는 순간 자동화 자체를 신뢰할 수 없게 되기 때문입니다. AI 코드리뷰를 MR 단위와 Push 단위로 분리한 것은, MR만 보면 커밋 단위에서 놓치는 부분이 생길 수 있어서입니다. 배포는 빌드 서버 메모리를 늘리는 대신, 파이프라인이 앞 빌드 완료를 감지해 다음 빌드·배포를 자동으로 잇게 했습니다. 제약은 그대로 두고 사람의 대기만 없애는 쪽이 비용 없이 같은 효과를 내기 때문입니다.
결과
배포 사실과 리뷰 결과가 자동으로 공유되고, 연속 배포에서 사람의 대기가 사라졌습니다.
회고
알림은 성공 경로만이 아니라 전송 실패의 폴백까지 설계해야 신뢰할 수 있고, 자동화의 대상은 작업 자체보다 작업 사이의 대기라는 기준을 얻었습니다.

성과 05

Java 11 → 21 → 25 런타임 현대화

배경·원인
모바일 클라이언트 인증과 고객사 사이트 단위 파일 관리를 담당할 신규 애플리케이션을 올려야 했습니다. 그런데 Java 11 기반의 기존 방식으로는 구현에 제약이 있었고, 오래된 런타임을 그대로 두는 것 자체도 장기 유지보수 위험이었습니다.
고민·선택 이유
현대화는 신규 애플리케이션 구축과 맞물려 시작했습니다. 21을 먼저 병합해 새 기능 개발과 런타임 전환을 같은 구간에서 진행했고, 이후 25로 올리며 Spring Boot 4 BOM으로 버전 관리를 통합했습니다. Jackson 3 마이그레이션과 JWT 라이브러리 단일 소유 정리, 모듈별 빌드 JDK 전환까지 함께 처리해 모듈마다 의존성이 갈리지 않게 했습니다.
결과
업그레이드가 깨뜨린 것들을 함께 복구했습니다. HTTPS 판정이 뒤집힌 SAML 헤더 처리와 entity-id 스킴, 비표준 포트 문제가 드러났습니다. 스테이징의 403 차단과 프록시 뒤 클라이언트 IP 유실도 진단 필터까지 넣어 되돌렸습니다. 같은 흐름에서 프론트엔드 빌드를 CRA에서 Vite로 옮기고 검색 클라이언트도 9.x로 올려, 백엔드와 프론트엔드의 낡은 의존성을 함께 걷어냈습니다. 이 전환 덕분에 이후 SAML 표준화도 프레임워크가 지원하는 방식 위에서 진행할 수 있었습니다.
회고
런타임 업그레이드에서 실제로 손이 가는 곳은 버전을 올리는 데가 아닙니다. 환경 차이 때문에 조용히 깨진 동작을 찾아 되돌리는 일이 본체입니다.

성과 06

SAML 표준화와 SSO 확장 기반

배경·원인
새 파트너 IdP와의 SSO 연동 요구가 들어왔는데, 레거시 SAML 구현은 프레임워크 특성상 유연하고 확장 가능한 구조를 만들기 어려웠습니다. 특히 Spring Boot 4에서는 기존 방식의 IdP 구현이 제한되는 상황이라, 당장의 연동을 넘어 향후 확장 개발을 위해 표준화를 사전에 해두는 것이 좋겠다고 판단했습니다.
고민·선택 이유
자체 방식을 고쳐 쓰는 대신 표준 방식으로 전환했습니다. 프레임워크가 지원을 보장하는 표준 위에 있어야 버전 업에서 살아남고, 확장도 프레임워크의 방식대로 풀리기 때문입니다. 제공자별 분기 코드 대신 SSO 제공자 레지스트리를 도입한 것은 새 파트너 연동이 코드 수정이 아니라 등록으로 끝나게 하기 위해서입니다. IdP 엔드포인트를 전용 보안 체인으로 분리해, IdP에만 필요한 보안 규칙이 나머지 서비스 경로에 영향을 주지 않게 했습니다. 범용 Mock SP 테스트 애플리케이션은 파트너마다 실제 연동 환경을 기다리지 않고 표준 준수를 먼저 검증하려고 만들었습니다.
결과
IdP-initiated 자동 로그인이 동작하는 표준 기반을 갖췄습니다. 연동 검증용 범용 SAML 2.0 Mock SP 테스트 애플리케이션도 마련해 새 제공자 연동을 반복 가능하게 만들었습니다.
회고
프레임워크가 다음 버전에서 제한하는 방식을 먼저 확인하고 표준을 따라두면, 당장의 요구를 넘어 다음 확장의 비용이 줄어든다는 기준을 얻었습니다.

성과 07

룰 기반 제품 구성기 (Drive Panel Selector)

배경·원인
고객이 사양에 맞는 드라이브·패널 구성을 찾으려면 매번 기술 문의를 거쳐야 했습니다. 영업에서는 시스템 안에서 상담과 동시에 견적 문의까지 이어지는 도구를 요구했고, 이를 다단계 구성기로 풀기로 했습니다.
고민·선택 이유
추천을 학습 모델이 아니라 명시적인 룰로 설계한 것은, 제품 구성이 옵션 간 제약이 뚜렷한 공학 문제이기 때문입니다. 잘못된 구성이 견적과 수주로 이어지는 도메인에서는 예측보다 누구나 검증하고 설명할 수 있는 규칙이 맞습니다. 기동방식 같은 선택지는 앞 단계에서 고른 드라이브 용량에 따라 동적으로 좁혀지게 해, 고객이 성립하지 않는 조합에 도달할 수 없게 했습니다. 마지막 단계의 모델 이미지 렌더링, 고객 직접 입력 항목, 관리자 문의 내역 연동과 중복 문의 방지도 함께 설계했습니다. 구성기를 화면에서 끝내지 않고 상담·견적 흐름까지 잇기 위해서입니다.
결과
고객이 기술 문의 없이 스스로 사양에 맞는 구성을 좁혀 결과 모델에 도달하고, 그 자리에서 문의·견적 요청으로 이어지는 흐름이 생겼습니다.
회고
추천처럼 보이는 요구도 옵션 간 의존성을 명시적인 룰로 정리하면 예측 가능하게 풀립니다. 결과 화면이 아니라 상담·견적까지 잇는 것이 도구의 완성이라는 기준을 얻었습니다.
← 목록으로
포트폴리오 PDF 다운로드