동방건우 | Web Developer

배포까지 고려해 문제를 해결하는 개발자

React 기반 정적 서비스부터 Spring Boot, JSP, jQuery 기반 서버 프로젝트까지 작업했습니다. 기능 구현에서 멈추지 않고 배포 화면에서 오류를 확인하며, 데이터 가공·권한 처리·자동화 배포까지 함께 정리합니다.

3개개인 데이터 프로젝트
2개기존 프로젝트 보완
API수집·가공 경험
CI/CD자동화 경험
React
Spring
JSP
Oracle
PostgreSQL
Actions
📌 개인 데이터 서비스 3개 기획·구현
🛠️ 기존 서비스 2개 리디자인/기능 보완
🧩 외부 API 수집·정적 JSON 가공
🚀 GitHub Pages · Vercel · Render 배포 경험

프로젝트

프로젝트 모음

개발기록 보기 →
개인 데이터 프로젝트

팜프라이스 노트, 상장노트, 리터세이브는 2026.03.02에 데이터형 미니 서비스 3종으로 묶어 기획했습니다.

기존 프로젝트 보완

Review Tag와 PETIQUE는 기존 기능을 유지하면서 화면 흐름, 오류 처리, 권한 검증, 배포 설정을 계속 보완하고 있습니다.

상장노트 미리보기
배포 중2026.03.02 기획 시작

상장노트

공모·상장 일정을 정리해 필요한 정보를 빠르게 확인할 수 있게 만든 서비스입니다.

ReactViteOpenDART API
ZIP 처리 · 인코딩 변환 · 일정 정리
리터세이브 미리보기
배포 중2026.03.02 기획 시작

리터세이브

주유소 가격을 지역·유종 기준으로 비교하고 절약 판단을 돕는 서비스입니다.

ReactViteOpinet API
Static JSON · 가격 정렬 · 예외 처리
Review Tag 미리보기
리디자인/기능 보완 중배포 중

Review Tag

영화·애니 리뷰 커뮤니티에 퀴즈와 포인트 보상 기능을 함께 넣은 서비스입니다.

ReactSpring BootOracle
기존 기능 보완 · 권한/토큰 · 포인트 흐름 정리
PETIQUE 미리보기
리디자인/기능 보완 중배포 중

PETIQUE

반려동물 분양, 후기, 커뮤니티를 한 흐름으로 연결한 웹 서비스입니다.

JSPjQueryPostgreSQL
Render · Supabase · 상태 전이 · CSRF 보완

배포 자동화

자동화 / 배포

GitHub Actions데이터 수집, 검증, 정적 파일 생성, 배포 흐름을 자동화했습니다.
GitHub PagesReact/Vite 기반 개인 데이터 프로젝트를 정적 사이트로 배포했습니다.
VercelReview Tag 프론트엔드 배포와 수정 화면 확인에 사용했습니다.
RenderPETIQUE 서버 배포, 환경 변수, 무료 티어 제약을 고려했습니다.
Cloudflare Pages포트폴리오 정적 배포를 위해 빌드 산출물 구조를 맞췄습니다.

데이터 처리

데이터 처리 흐름

외부 API 수집
데이터 수집
데이터 정리
검증
JSON 생성
화면 반영

브라우저에서 모든 API를 직접 호출하지 않고, 수집 단계에서 데이터를 먼저 정리했습니다. 화면은 정리된 JSON을 읽도록 구성해 API Key 노출과 화면별 예외 처리 반복을 줄였습니다.

배포 확인 안내 서버 기반 배포 프로젝트는 첫 접속 시 화면이 열리기까지 시간이 걸릴 수 있습니다. 정적 배포 프로젝트는 GitHub Pages, Vercel, Cloudflare Pages 환경 기준으로 확인할 수 있게 정리했습니다.

기술 선택

왜 이렇게 구현했는지

API 호출 위치 분리

공공데이터 API를 브라우저에서 바로 호출하지 않고, 수집 단계에서 정리한 뒤 JSON으로 저장했습니다. API Key 노출 위험과 화면별 예외 처리 반복을 줄이기 위한 선택입니다.

GitHub Actions 자동화

수동으로 데이터를 갱신하면 누락될 수 있어, 데이터 수집·검증·정적 파일 생성을 자동화했습니다. 배포 화면은 이미 정리된 데이터를 읽는 구조로 단순화했습니다.

JSP / jQuery 유지 보완

PETIQUE는 기존 화면 구조를 무리하게 갈아엎지 않고 JSP와 jQuery 흐름을 유지했습니다. 대신 요청 공통 처리와 상태 검증을 보완해 운영 화면에서 생길 수 있는 오류를 줄이는 방향으로 잡았습니다.

DB와 배포 환경 분리

Review Tag는 Oracle 기반 흐름을, PETIQUE는 PostgreSQL/Supabase와 Render 배포 흐름을 정리했습니다. 프로젝트마다 사용하는 DB와 배포 환경이 다른 이유를 설명할 수 있게 분리했습니다.

개발 기록

개발 일정과 문제 해결 기록

개인 데이터 프로젝트

팜프라이스 노트

2026.03.02 기획 시작 · 2026.04.01 검증 로직 보강 · 배포 중

만든 이유

농산물 가격 데이터는 생활과 연결되어 있지만, 가격 흐름을 한눈에 비교하기 어렵다고 느꼈습니다. 품목별 가격 변화와 요약 정보를 빠르게 볼 수 있는 화면을 목표로 만들었습니다.

담당 작업

  • KAMIS 데이터 수집 흐름 정리
  • 품목 카드, 가격 비교, 요약 화면 구성
  • 정적 JSON 생성 후 React 화면에서 로딩
  • GitHub Actions 기반 수집·검증·배포 흐름 구성

개발 일정

  1. 2026.03.02농산물 가격을 다루는 데이터형 서비스로 방향을 정하고 화면 구성을 잡았습니다.
  2. 2026.03.05KAMIS 응답 구조를 확인하고 품목, 가격, 날짜 값을 화면에 맞게 정리했습니다.
  3. 2026.03.14가격 카드와 비교 영역을 만들고, 데이터가 없을 때 빈 화면이 나오지 않도록 기본 메시지를 넣었습니다.
  4. 2026.03.25브라우저 직접 호출 대신 수집 스크립트에서 데이터를 정리해 JSON으로 저장하는 흐름을 잡았습니다.
  5. 2026.04.01가격, 날짜, 품목 값이 누락되면 배포 전에 확인할 수 있도록 검증 단계를 보강했습니다.
  6. 2026.04.28배포 화면 기준으로 문구, 카드 간격, 데이터 표시 오류를 확인하고 수정했습니다.

문제 해결

문제

API 응답을 화면에서 바로 처리하면 실패 처리와 데이터 정리가 컴포넌트마다 반복됐습니다.

수정

수집 단계에서 데이터 형태를 먼저 맞추고, React는 정적 JSON만 읽도록 분리했습니다.

이유

정적 배포 환경에서도 API Key 노출을 줄이고, 화면 코드는 표시 역할에 집중시키기 위해서입니다.

결과

데이터 누락을 배포 전에 확인할 수 있고, 화면에서는 검증된 값만 사용하게 됐습니다.

핵심 로직 정리

// 수집 단계에서 먼저 정리
const rows = normalizePriceRows(apiResponse);

if (!rows.length) {
  throw new Error('가격 데이터가 비어 있습니다.');
}

await writeJson('public/data/prices.json', rows);

개인 데이터 프로젝트

상장노트

2026.03.02 기획 시작 · 2026.03.26 자동화 흐름 정리 · 배포 중

만든 이유

상장 일정과 공시 정보는 여러 페이지를 오가며 확인해야 해서 흐름을 놓치기 쉽습니다. 필요한 일정과 상태를 카드 형태로 정리해 빠르게 확인하는 서비스를 목표로 했습니다.

담당 작업

  • OpenDART 데이터 구조 확인
  • ZIP 파일 추출과 한글 인코딩 처리
  • 상장 일정 카드, 검색, 필터 UI 구성
  • 정리된 일정 데이터를 정적 JSON으로 제공

개발 일정

  1. 2026.03.02공모·상장 일정을 한 화면에서 볼 수 있는 서비스로 기획했습니다.
  2. 2026.03.06OpenDART 응답 구조와 필요한 항목을 확인하고 데이터 가공 방향을 정했습니다.
  3. 2026.03.11압축 파일 추출과 한글 인코딩 변환 흐름을 정리했습니다.
  4. 2026.03.19일정 카드, 상태 표시, 검색/필터 화면을 구성했습니다.
  5. 2026.03.26데이터 갱신과 정적 배포 흐름을 분리해 자동화 구조를 정리했습니다.
  6. 2026.04.28배포 화면에서 일정 표시와 검색 동작을 확인하고 문구를 다듬었습니다.

문제 해결

문제

OpenDART 데이터는 압축 파일과 인코딩 처리가 필요해 브라우저에서 바로 다루기 어렵습니다.

수정

Node.js 처리 단계에서 압축을 풀고 문자 인코딩을 변환한 뒤 JSON으로 저장했습니다.

이유

화면에서 파일 처리 로직을 없애고, 이미 정리된 일정 데이터만 읽게 만들기 위해서입니다.

결과

React 컴포넌트는 검색과 표시 역할에 집중하게 되었고, 한글 깨짐 문제를 줄였습니다.

핵심 로직 정리

// 데이터 처리 단계에서 압축과 인코딩을 먼저 처리
const zip = new AdmZip(buffer);
const entry = zip.getEntries().find((file) => file.entryName.endsWith('.xml'));

const text = iconv.decode(entry.getData(), 'euc-kr');
const schedules = parseListingSchedules(text);

await writeJson('public/data/ipos.json', schedules);

개인 데이터 프로젝트

리터세이브

2026.03.02 기획 시작 · 2026.04.02 JSON 분리 · 배포 중

만든 이유

주유소 가격은 자주 확인하지만 지역과 유종별로 비교하기 번거롭습니다. 사용자가 가격 차이를 빠르게 확인하고 선택할 수 있도록 정렬과 필터 중심의 서비스를 만들었습니다.

담당 작업

  • Opinet 데이터 수집과 응답 예외 처리
  • 지역, 유종, 가격 기준 정렬 로직 구성
  • 정적 JSON 분리로 화면 로딩 부담 완화
  • 가격 비교 카드와 안내 문구 개선

개발 일정

  1. 2026.03.02주유소 가격 비교를 주제로 데이터형 미니 서비스 방향을 정했습니다.
  2. 2026.03.08Opinet 응답을 확인하고 지역·유종 기준으로 데이터를 나누는 방식을 잡았습니다.
  3. 2026.03.15최저가 정렬, 가격 비교 카드, 빈 데이터 안내 화면을 구성했습니다.
  4. 2026.03.24화면에서 모든 데이터를 한 번에 처리하지 않도록 정적 JSON 저장 흐름을 만들었습니다.
  5. 2026.04.02가격 데이터와 누적 이력 데이터를 분리해 화면에서 필요한 파일만 읽도록 수정했습니다.
  6. 2026.04.28배포 화면 기준으로 지역 선택, 가격 정렬, 안내 문구를 점검했습니다.

문제 해결

문제

요청 조건에 따라 Opinet 응답이 비어 오거나, 가격 데이터와 이력 데이터가 섞여 화면 코드가 복잡해졌습니다.

수정

수집 단계에서 빈 응답을 확인하고, 현재 가격과 이력 데이터를 별도 JSON으로 분리했습니다.

이유

화면에서는 비교와 필터만 처리하고, 데이터 정리는 배포 전 단계에서 끝내기 위해서입니다.

결과

파일 구조가 단순해지고, 데이터가 없는 경우에도 안내 메시지를 안정적으로 보여줄 수 있게 됐습니다.

핵심 로직 정리

// 요청 실패 가능성을 고려해 수집 단계에서 먼저 정리
const stations = normalizeStations(apiResponse);

const currentPrices = stations
  .filter((station) => station.price)
  .sort((a, b) => a.price - b.price);

await writeJson('public/data/oil-prices.json', currentPrices);

기존 프로젝트 보완

Review Tag

2026.01.05 리디자인 시작 · 2026.03.24 토큰 오류 수정 · 2026.04.08 QA 항목 추가 · 리디자인/기능 보완 중 · 배포 중

기존 프로젝트 내용

영화·애니 콘텐츠를 기반으로 리뷰, 게시판, 퀴즈, 출석, 포인트, 룰렛, 상점, 인벤토리, 랭킹, 관리자 기능을 제공하는 커뮤니티형 서비스입니다.

보완한 범위

  • 배포 화면 기준으로 UI 흐름과 문구 재정리
  • 포인트 메뉴, 상점, 인벤토리, 관리자 화면 점검
  • 비로그인 접근, 토큰 갱신 오류, 권한별 화면 노출 보완
  • CSS 충돌 가능성이 있는 선택자와 화면 QA 항목 정리

수정 전후

기존 상태

포인트, 퀴즈, 룰렛, 상점, 인벤토리 흐름이 각각 흩어져 있어 사용자가 보상 구조를 한 번에 이해하기 어려웠습니다.

수정 후

포인트 관련 메뉴와 화면 동선을 다시 정리하고, 로그인·권한·토큰 오류 상황을 배포 화면 기준으로 점검했습니다.

개발 일정

  1. 2026.01.05기존 프로젝트를 배포 화면 기준으로 다시 확인하고 리디자인 범위를 나눴습니다.
  2. 2026.02.12포인트, 출석, 퀴즈, 룰렛, 상점, 인벤토리 흐름을 한 메뉴 구조로 다시 정리했습니다.
  3. 2026.03.14비로그인 사용자가 포인트 상점에 접근할 때 발생할 수 있는 흐름을 점검했습니다.
  4. 2026.03.24토큰 갱신 메서드 오류를 수정하고 로그인 유지 흐름을 다시 확인했습니다.
  5. 2026.04.08리디자인 화면에서 충돌 가능성이 있는 선택자와 깨지는 화면을 점검 항목으로 정리했습니다.
  6. 2026.04.28배포 화면 기준으로 카드, 관리자 화면, 포인트 메뉴의 표시 상태를 다시 확인했습니다.

문제 해결

문제

관리자 영화 검색 모달과 공통 스타일이 겹치면 다른 화면 수정 시 예기치 않게 깨질 수 있었습니다.

수정

관리자 영화 검색 영역의 클래스명을 화면 역할이 드러나는 이름으로 분리했습니다.

이유

리디자인 과정에서 색이나 배치만 바꾸지 않고, 화면별 스타일 소유권을 분명히 하기 위해서입니다.

결과

관리자 화면과 공통 컴포넌트 스타일이 서로 덜 간섭하도록 정리했습니다.

핵심 로직 정리

// 포인트 구매는 중간 실패 시 데이터가 어긋나지 않게 묶어서 처리
@Transactional
public void purchaseItem(Long memberId, Long itemId) {
    pointService.usePoint(memberId, itemPrice);
    shopService.decreaseStock(itemId);
    inventoryService.addItem(memberId, itemId);
}

기존 프로젝트 보완

PETIQUE

2026.01.08 리디자인 시작 · 2026.03.21 분양 완료 로직 보완 · 2026.04.21 배포 검증 보강 · 리디자인/기능 보완 중 · 배포 중

기존 프로젝트 내용

반려동물 분양 게시글, 신청, 예약, 완료, 취소, 후기 연결, 커뮤니티 게시판, 댓글, 추천, 북마크, 신고, 쪽지, 마이페이지, 관리자 기능을 포함한 서비스입니다.

보완한 범위

  • JSP와 jQuery 기반 화면 흐름 재정리
  • 분양 신청·승인·거절·완료 상태 전이 보완
  • PostgreSQL/Supabase, Render 배포 환경 정리
  • 이미지 업로드, 메일 인증, CSRF, 비밀번호 보안 항목 점검

수정 전후

기존 상태

JSP form, jQuery Ajax, fetch 요청이 섞여 있어 CSRF 토큰 처리와 분양 상태 검증이 화면마다 달라질 수 있었습니다.

수정 후

요청 공통부에서 CSRF 토큰을 붙이고, 분양 상태 전이는 서버에서 권한과 현재 상태를 먼저 확인하도록 정리했습니다.

개발 일정

  1. 2026.01.08기존 분양 서비스 구조를 다시 확인하고 리디자인과 배포 보완 범위를 정했습니다.
  2. 2026.02.14분양 신청, 승인, 거절, 완료 상태가 어떤 순서로 바뀌어야 하는지 다시 정리했습니다.
  3. 2026.03.18회원탈퇴 오류를 확인하고 관련 흐름을 수정했습니다.
  4. 2026.03.20닉네임 중복검사 로직을 보완해 가입·수정 화면의 검증 흐름을 정리했습니다.
  5. 2026.03.21분양 완료 로직을 보완해 신청 상태와 후기 연결 흐름이 어긋나지 않도록 수정했습니다.
  6. 2026.04.21Render 배포 환경에서 의존성, 보안 설정, CSRF 요청 흐름을 다시 확인했습니다.

문제 해결

문제

JSP 화면에서 form, jQuery Ajax, fetch 요청이 섞이면 CSRF 토큰 누락으로 요청이 실패할 수 있었습니다.

수정

form 제출, jQuery Ajax, fetch 요청에 CSRF 토큰이 빠지지 않도록 공통 스크립트에서 요청 방식을 묶었습니다.

이유

화면마다 토큰 코드를 따로 작성하면 누락이 생기기 쉬워서, 요청 공통부에서 처리하는 편이 안정적이라고 판단했습니다.

결과

JSP와 jQuery 기반 화면에서도 인증 요청 흐름을 일정하게 유지하고, 누락으로 인한 실패 가능성을 줄였습니다.

핵심 로직 정리

// jQuery Ajax 요청에 CSRF 토큰을 공통으로 추가
$.ajaxSetup({
  beforeSend: function (xhr) {
    xhr.setRequestHeader(csrfHeaderName, csrfToken);
  }
});

// 분양 완료는 권한과 상태를 먼저 확인
if (!canCompleteAdoption(adoption, loginMember)) {
  throw new IllegalStateException('완료 처리할 수 없는 상태입니다.');
}

기술 스택

사용해 본 기술

Frontend

ReactViteJavaScriptjQueryHTML5CSS3AxiosJotaiBootstrap

Backend & View

Java 21Spring BootSpring MVCSpring SecurityJWTJSPJSTLJdbcTemplateMyBatis

Database

OraclePostgreSQLSupabaseSQLCRUDTransaction

Data & API

KAMIS APIOpenDART APIOpinet APITMDB APIEmailJSimgBBJSONXML

Deploy & CI/CD

GitHub ActionsGitHub PagesVercelRenderCloudflare PagesGitHub Secrets

기술을 사용한 위치

React / Vite팜프라이스 노트, 상장노트, 리터세이브, Review Tag
JSP / jQueryPETIQUE 화면 흐름과 요청 처리
Spring Boot / MVCReview Tag API, PETIQUE 서버 구조
OracleReview Tag 데이터베이스
PostgreSQL / SupabasePETIQUE 배포 데이터베이스
GitHub Actions팜프라이스 노트, 상장노트, 리터세이브 데이터 자동화
VercelReview Tag 프론트엔드 배포
RenderPETIQUE 서버 배포

연락처

배포된 화면을 기준으로 계속 보완하고 있습니다.

프로젝트마다 기획, 구현, 배포, 수정 기록을 분리해 정리했습니다. 화면, 데이터, 권한, 배포 흐름에서 어떤 문제를 어떻게 해결했는지 설명할 수 있도록 정리했습니다.