PETIQUE
JSP, jQuery, Spring MVC, PostgreSQL/Supabase, Render 배포 환경을 함께 다룬 프로젝트입니다. 분양 상태 전이, CSRF 요청 공통 처리, 배포 설정 보완을 중심으로 설명할 수 있습니다.
동방건우 | Web Developer
React 기반 정적 서비스부터 Spring Boot, JSP, jQuery 기반 서버 프로젝트까지 작업했습니다. 기능 구현에서 멈추지 않고 배포 화면에서 오류를 확인하며, 데이터 가공·권한 처리·자동화 배포까지 함께 정리합니다.
대표 프로젝트
최근 정리일 · 2026.04.29
JSP, jQuery, Spring MVC, PostgreSQL/Supabase, Render 배포 환경을 함께 다룬 프로젝트입니다. 분양 상태 전이, CSRF 요청 공통 처리, 배포 설정 보완을 중심으로 설명할 수 있습니다.
영화·애니 리뷰 커뮤니티에 포인트 보상 흐름을 결합한 프로젝트입니다. 토큰 오류, 권한별 화면 노출, 포인트 상점 처리 흐름을 중심으로 보완했습니다.
공공데이터를 수집해 정적 JSON으로 만들고 React 화면에 반영한 개인 데이터 프로젝트입니다. API Key 노출 위험을 줄이고 데이터 검증 단계를 분리했습니다.
프로젝트
팜프라이스 노트, 상장노트, 리터세이브는 2026.03.02에 데이터형 미니 서비스 3종으로 묶어 기획했습니다.
Review Tag와 PETIQUE는 기존 기능을 유지하면서 화면 흐름, 오류 처리, 권한 검증, 배포 설정을 계속 보완하고 있습니다.
배포 자동화
데이터 처리
브라우저에서 모든 API를 직접 호출하지 않고, 수집 단계에서 데이터를 먼저 정리했습니다. 화면은 정리된 JSON을 읽도록 구성해 API Key 노출과 화면별 예외 처리 반복을 줄였습니다.
배포 확인 안내 서버 기반 배포 프로젝트는 첫 접속 시 화면이 열리기까지 시간이 걸릴 수 있습니다. 정적 배포 프로젝트는 GitHub Pages, Vercel, Cloudflare Pages 환경 기준으로 확인할 수 있게 정리했습니다.
기술 선택
공공데이터 API를 브라우저에서 바로 호출하지 않고, 수집 단계에서 정리한 뒤 JSON으로 저장했습니다. API Key 노출 위험과 화면별 예외 처리 반복을 줄이기 위한 선택입니다.
수동으로 데이터를 갱신하면 누락될 수 있어, 데이터 수집·검증·정적 파일 생성을 자동화했습니다. 배포 화면은 이미 정리된 데이터를 읽는 구조로 단순화했습니다.
PETIQUE는 기존 화면 구조를 무리하게 갈아엎지 않고 JSP와 jQuery 흐름을 유지했습니다. 대신 요청 공통 처리와 상태 검증을 보완해 운영 화면에서 생길 수 있는 오류를 줄이는 방향으로 잡았습니다.
Review Tag는 Oracle 기반 흐름을, PETIQUE는 PostgreSQL/Supabase와 Render 배포 흐름을 정리했습니다. 프로젝트마다 사용하는 DB와 배포 환경이 다른 이유를 설명할 수 있게 분리했습니다.
개발 기록
농산물 가격 데이터는 생활과 연결되어 있지만, 가격 흐름을 한눈에 비교하기 어렵다고 느꼈습니다. 품목별 가격 변화와 요약 정보를 빠르게 볼 수 있는 화면을 목표로 만들었습니다.
API 응답을 화면에서 바로 처리하면 실패 처리와 데이터 정리가 컴포넌트마다 반복됐습니다.
수집 단계에서 데이터 형태를 먼저 맞추고, React는 정적 JSON만 읽도록 분리했습니다.
정적 배포 환경에서도 API Key 노출을 줄이고, 화면 코드는 표시 역할에 집중시키기 위해서입니다.
데이터 누락을 배포 전에 확인할 수 있고, 화면에서는 검증된 값만 사용하게 됐습니다.
// 수집 단계에서 먼저 정리
const rows = normalizePriceRows(apiResponse);
if (!rows.length) {
throw new Error('가격 데이터가 비어 있습니다.');
}
await writeJson('public/data/prices.json', rows);
상장 일정과 공시 정보는 여러 페이지를 오가며 확인해야 해서 흐름을 놓치기 쉽습니다. 필요한 일정과 상태를 카드 형태로 정리해 빠르게 확인하는 서비스를 목표로 했습니다.
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);
주유소 가격은 자주 확인하지만 지역과 유종별로 비교하기 번거롭습니다. 사용자가 가격 차이를 빠르게 확인하고 선택할 수 있도록 정렬과 필터 중심의 서비스를 만들었습니다.
요청 조건에 따라 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);
기존 프로젝트 보완
2026.01.05 리디자인 시작 · 2026.03.24 토큰 오류 수정 · 2026.04.08 QA 항목 추가 · 리디자인/기능 보완 중 · 배포 중
영화·애니 콘텐츠를 기반으로 리뷰, 게시판, 퀴즈, 출석, 포인트, 룰렛, 상점, 인벤토리, 랭킹, 관리자 기능을 제공하는 커뮤니티형 서비스입니다.
포인트, 퀴즈, 룰렛, 상점, 인벤토리 흐름이 각각 흩어져 있어 사용자가 보상 구조를 한 번에 이해하기 어려웠습니다.
포인트 관련 메뉴와 화면 동선을 다시 정리하고, 로그인·권한·토큰 오류 상황을 배포 화면 기준으로 점검했습니다.
관리자 영화 검색 모달과 공통 스타일이 겹치면 다른 화면 수정 시 예기치 않게 깨질 수 있었습니다.
관리자 영화 검색 영역의 클래스명을 화면 역할이 드러나는 이름으로 분리했습니다.
리디자인 과정에서 색이나 배치만 바꾸지 않고, 화면별 스타일 소유권을 분명히 하기 위해서입니다.
관리자 화면과 공통 컴포넌트 스타일이 서로 덜 간섭하도록 정리했습니다.
// 포인트 구매는 중간 실패 시 데이터가 어긋나지 않게 묶어서 처리
@Transactional
public void purchaseItem(Long memberId, Long itemId) {
pointService.usePoint(memberId, itemPrice);
shopService.decreaseStock(itemId);
inventoryService.addItem(memberId, itemId);
}
기존 프로젝트 보완
2026.01.08 리디자인 시작 · 2026.03.21 분양 완료 로직 보완 · 2026.04.21 배포 검증 보강 · 리디자인/기능 보완 중 · 배포 중
반려동물 분양 게시글, 신청, 예약, 완료, 취소, 후기 연결, 커뮤니티 게시판, 댓글, 추천, 북마크, 신고, 쪽지, 마이페이지, 관리자 기능을 포함한 서비스입니다.
JSP form, jQuery Ajax, fetch 요청이 섞여 있어 CSRF 토큰 처리와 분양 상태 검증이 화면마다 달라질 수 있었습니다.
요청 공통부에서 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('완료 처리할 수 없는 상태입니다.');
}
기술 스택
연락처
프로젝트마다 기획, 구현, 배포, 수정 기록을 분리해 정리했습니다. 화면, 데이터, 권한, 배포 흐름에서 어떤 문제를 어떻게 해결했는지 설명할 수 있도록 정리했습니다.