jihwang.kim
Professional Project

Tech Square

2022.07 - Present

개요

수요기업과 공급기업이 스마트공장 구축 파트너를 찾고 멘토링, 중고설비 거래, 운영 정보를 이용할 수 있는 B2B 제조 플랫폼입니다.

역할과 기술스택

Node.js, Express, TypeORM, MySQL, Vue 3, AWS, GitLab CI/CD

Node.jsExpressTypeORMMySQLVue 3AWSGitLab CI/CD

성과 01

Java 8 시스템을 Node.js 플랫폼으로 재구축하는 전환 참여

배경과 원인
Tech Square의 기존 시스템은 Java 8 기반으로 운영되고 있었고 품질과 유지보수에 한계가 있었습니다. Vue 3 기반의 사용자, 관리자 채널과 기술 구성을 맞춘 신규 플랫폼이 필요했습니다.
고민과 선택 이유
전환 결정에는 참여하지 않았고 결정 이후 합류해 Node.js, Express, TypeORM 기반 시스템의 공동 구축과 데이터 이관을 맡았습니다. 프론트엔드와 언어 생태계를 통일해 협업 경계를 줄였습니다. 기존 시스템과 신규 시스템을 병행 운영해 기능과 데이터를 검증한 뒤 운영을 인수했습니다.
결과
운영 중단 없이 신규 플랫폼으로 전환했습니다. 구축이 끝난 뒤에는 외주 인력 1명과 함께 API와 사용자, 관리자 채널을 운영하며 고도화했습니다.
회고
운영 시스템 전환은 새 기술보다 데이터 이관, 병행 운영, 인수 종료 기준을 함께 설계해야 안정적으로 끝낼 수 있습니다.

성과 02

공통 트랜잭션 계층으로 데이터 정합성 기준 통일

배경과 원인
추천 요청이 중복 접수되거나 추천 상태가 실제 진행 상황과 어긋나는 일이 있었습니다. 같은 업무에 속하는 변경을 하나의 트랜잭션으로 묶고 중복 요청과 상태 변경을 일관되게 처리할 기준이 필요했습니다.
고민과 선택 이유
ORM이 주는 기능만 쓰면 초반 속도는 빠르지만 업무가 늘수록 트랜잭션 경계가 컨트롤러마다 흩어집니다. 오래 운영할 서비스로 봤기 때문에 초기 비용을 감수하고 TypeORM 위에 SQL과 트랜잭션 공통 계층을 직접 만들었습니다. 업무적으로 하나의 명령인 변경은 하나의 트랜잭션으로 묶었습니다. 외부 API 호출이나 이메일 발송처럼 롤백으로 되돌릴 수 없는 작업은 트랜잭션 밖으로 뺐습니다. 중복 요청 대응에서는 트랜잭션 격리 수준을 올리는 방법을 먼저 검토했습니다. 다만 격리 수준을 올린다고 중복된 명령 자체가 사라지지는 않고 잠금 경합만 늘어납니다. 그래서 업무 키에 유니크 제약을 걸고 명령 식별자와 현재 상태 검증을 함께 뒀습니다.
결과
3계층 구조와 공통 트랜잭션 계층이 업무 서비스 61개에서 유지됩니다. 업무가 늘어난 뒤에도 트랜잭션 처리 방식이 갈라지지 않았습니다.
회고
트랜잭션 공통화의 목적은 코드 재사용보다 업무 단위의 성공과 실패 경계를 일관되게 만드는 데 있습니다.

성과 03

반복 조회 구조를 쿼리 재구성으로 개선

배경과 원인
회원, 기업, 멘토링 데이터가 늘면서 목록 한 건마다 연관 정보를 다시 조회하는 구조가 생겼고 검색 조건이 추가될수록 쿼리 조합도 복잡해졌습니다.
고민과 선택 이유
제한 시간을 늘리거나 인덱스를 무작정 추가하기보다 반복 조회를 조인과 일괄 조회로 전환했습니다. 동적 검색 조건은 파라미터 바인딩 기반 쿼리 빌더로 정리해 실행 구조와 입력 안전성을 함께 개선했습니다.
결과
반복 조회를 줄이고 검색 조건을 안전하게 조합할 수 있게 했으며, 목록과 엑셀 다운로드가 같은 조회 기준을 공유하도록 정리했습니다.
회고
느린 조회는 결과 집합과 반복 횟수를 먼저 확인하고 쿼리 구조를 바로잡은 뒤 필요한 인덱스를 선택해야 합니다.

성과 04

로컬 파일을 S3 기반 공통 파일 흐름으로 전환

배경과 원인
업로드 파일이 서버 로컬 경로에 묶여 있어 환경이 바뀌면 탐색과 다운로드 처리가 달라졌고 PDF, Excel, 이미지마다 별도 예외가 쌓였습니다.
고민과 선택 이유
서버 인스턴스와 파일 생명주기를 분리하기 위해 S3로 전환하되 기존 파일을 한 번에 폐기하지 않고 두 경로를 함께 읽는 기간을 뒀습니다. 업로드, 조회, 삭제, 원본 파일명 복원을 공통 유틸리티로 모아 저장 방식 변경이 업무 코드로 퍼지지 않게 했습니다.
결과
공지, 보고서, 견적, 이미지 등 서로 다른 파일 흐름이 공통 저장 방식을 사용하게 됐고 환경에 종속된 파일 경로와 중복 처리를 줄였습니다.
회고
파일 저장소 전환은 객체 복사뿐 아니라 기존 키, 원본 이름과 조회 경로의 호환성을 함께 보존해야 하는 데이터 이관입니다.

성과 05

인증과 입력 경계를 단계적으로 보안 강화

배경과 원인
브라우저에서 접근 가능한 인증 토큰, 동적 SQL, HTML 입력과 다양한 업로드 경로가 각각 다른 보안 위험을 만들고 있었습니다.
고민과 선택 이유
JWT는 HttpOnly 쿠키로 옮겨 브라우저 스크립트의 직접 접근을 막고 동시 401 요청은 한 번의 토큰 갱신으로 모았습니다. SQL은 파라미터화하고 HTML과 파일은 허용 목록으로 검증해 인증, 데이터, 입력, 파일 경계마다 적합한 방어를 적용했습니다.
결과
사용자와 관리자 채널의 인증 흐름을 통일하고 스크립트 입력, SQL 삽입, 위험 파일 렌더링으로 이어질 수 있는 노출 경로를 줄였습니다.
회고
보안은 하나의 필터로 해결되지 않으며 인증, 입력, 데이터와 파일 경계를 각각 확인해 단계적으로 좁혀야 합니다.

성과 06

로그 단편을 요청 흐름으로 연결한 관측성 구축

배경과 원인
서비스별 `console` 로그만으로는 한 요청이 API와 데이터 처리 과정에서 어디까지 진행됐는지 연결해 보기 어려웠습니다.
고민과 선택 이유
로그를 더 추가하는 대신 전 소스를 구조화 로거로 통일하고 요청별 상관관계 ID를 부여했습니다. OpenTelemetry traceId까지 연결해 로그 형식을 유지하면서도 요청 흐름을 서비스 경계 너머로 추적할 수 있게 했습니다.
결과
개별 로그를 따로 검색하던 방식에서 벗어나 요청 단위로 문제 발생 지점을 좁힐 수 있는 운영 기반을 마련했습니다.
회고
관측성은 로그의 양보다 서로 다른 기록을 같은 요청 흐름으로 연결할 수 있는지가 중요합니다.

성과 07

시크릿과 로컬 개발환경을 재현 가능한 구성으로 전환

배경과 원인
환경별 설정과 시크릿 관리 방식이 분산되어 있었고, 로컬 데이터베이스 터널이 끊기면 애플리케이션 연결도 함께 불안정해졌습니다.
고민과 선택 이유
소규모 혼합 인력 팀의 운영 부담을 고려해 Vault보다 진입 장벽이 낮은 Infisical을 선택했습니다. Docker Compose로 실행 환경을 통일하고 DB 터널은 별도 프로세스로 분리해 끊김 감지, 지수 백오프 재연결, 중복 실행 방지를 적용했습니다.
결과
시크릿을 코드와 배포 파일에서 분리하고 개발자가 같은 실행 절차를 재현할 수 있게 했습니다. 터널 장애도 애플리케이션 전체 재시작에 의존하지 않고 복구할 수 있게 했습니다.
회고
개발환경 표준화는 도구를 맞추는 것보다 설정, 시크릿, 외부 연결의 실패와 복구 방식을 함께 정의하는 일입니다.

성과 08

반복 업무를 배치와 알림 파이프라인으로 자동화

배경과 원인
외부 데이터 적재, 상태 확인과 담당자 안내를 사람이 반복하면 누락과 처리 지연이 발생할 수 있었습니다.
고민과 선택 이유
대량 데이터는 건별 요청 대신 일괄 적재해 데이터베이스 요청 횟수를 줄이고 업무 조건별 cron 작업과 알림 흐름을 구성했습니다. 중복 실행, 빈 결과, 환경별 발송 여부를 분리해 자동화가 예외 상황에서 불필요한 작업을 만들지 않게 했습니다.
결과
기업 데이터 적재와 운영 알림이 정해진 조건과 일정에 따라 실행되어 담당자의 반복 확인 업무를 줄였습니다.
회고
배치 자동화는 주기적 실행보다 중복 처리, 빈 결과와 부분 실패를 안전하게 다루는 것이 핵심입니다.
목록으로
(c) 2026 Jihwang Kimv20261016.01
포트폴리오 PDF 다운로드