FULLSTACK DEVELOPER

DATE.2026.04.07

CONTACT

[email protected]

010.5543.4341

github.com/xowlsakffl

확장성과 유지보수성을 우선으로 설계하는 개발자
요구사항을 일관된 구조, 문서로 정리하고
변화에 유연한 시스템을 구축하며
지속 가능한 코드와 아키텍처를 만듭니다.

01 자기소개

INTRODUCE

EDUCATION

2018
스마트(UI/UX)웹디자인&모바일콘텐츠개발
2019
PHP&MYSQL
2020
Laravel 개발 과정
2024
Java, Spring / Redis 과정
2026
한국방송통신대 컴퓨터과학과 졸업

SKILLS

백엔드
프론트엔드
데이터베이스
도구 및 협업
클라우드/Devops
기획/설계

CAREER

2019
메이크24 근무(웹에이전시)웹사이트 템플릿 제작, PHP 유지보수
2020
메씨인터내셔날 근무(PCO 기업)웹 솔루션(이벤츠 픽), 자체 구축 쇼핑몰 개발
2023
케어랩스 근무(의료 플랫폼 기업)광고 자동화 및 관리 프로그램(제니슨) 개발
2024
세이브마케팅 근무(의료 마케팅 기업)광고 관리 프로그램 유지보수
2026
뷰랩스(의료, 뷰티 플랫폼 기업) 재직중의료/뷰티 앱 신규 개발(개발 중)

01 자기소개

INTRODUCE

진취적인 개발자!

문제를 발견하면 단순히 넘기지 않고 원인부터 구조적으로 파악합니다.

비효율적인 방식에는 침묵하지 않고 근거를 바탕으로 의견을 제시합니다.

더 나은 방향이 보이면 직접 개선까지 주장하고자 합니다.

모두가 단순히 "예" 라고 수긍 할 때 "아니오" 라고 외칠 수 있는 용기를 추구합니다.
구조적 사고
주도적 개선
책임감

01. 레거시를 보면 도망치지 않고 분석하는 스타일

입사 초기, 기존 시스템의 구조와 운영 방식을 빠르게 분석하고 문제점을 정리한 보고서를 작성했습니다.

단순한 코드 수준이 아닌 데이터 흐름과 아키텍처 관점에서 비효율과 구조적 한계를 도출했으며, 이를 기반으로 개선 및 구체적인 실행 방안을 제시했습니다.

개발은 주어진 기능을 구현하는 것을 넘어, 더 나은 구조를 만들기 위해 문제를 정의하고 개선을 주도하는 것이 주 핵심이라고 생각합니다.

02. 끝까지 책임지는 개발

개발은 기능 구현에서 끝나는 것이 아니라, 실제 운영 환경에서 안정적으로 동작하도록 끝까지 책임지는 하나의 과정입니다.

배포 이후에도 발생하는 이슈를 지속적으로 추적하고 개선하며, 단기적인 해결이 아닌 재발 방지와 구조적 안정성까지 고려합니다.

맡은 영역에 대해서는 시작부터 운영까지 끝까지 책임지는 것을 기본 원칙으로 삼고 있습니다.

01 자기소개

INTRODUCE

03. 광고 관리 시스템을 통해 습득한 “데이터 기반 문제 해결력”

케어랩스 재직 중 광고 운영 자동화 시스템을 개발했습니다. Google Ads, Kakao, Facebook 등 다양한 광고 플랫폼 API를 통합하여 캠페인 생성, 수정, 모니터링, 예산 추적을 하나의 시스템에서 자동 처리할 수 있도록 구현했습니다.

그 결과, 반복적인 수작업 업무를 약 40% 이상 줄였고, 데이터 집계 속도와 정확도를 개선하여 광고 성과 분석 및 의사결정 시간을 크게 단축했습니다. 특히, 실시간 데이터 대시보드와 조건별 자동 집행 로직을 개발하면서 "데이터가 곧 서비스의 품질을 결정한다"는 것을 체감했습니다.

API가 단순히 데이터를 주고받는 기술이 아니라, 서비스 전체의 흐름과 효율을 바꾸는 핵심 연결고리라는 점을 실무를 통해 경험하였습니다. 본 경험 이후 “데이터를 어떻게 구조화하고 자동화하면 비즈니스에 도움이 될까”를 중심으로 사고하고 있습니다.

04. 기획부터 개발 전반을 구조적으로 이해 가능한 역량

서버 인프라 구축부터 프론트엔드 UI 까지 직접 경험하며 개발 전 과정을 이해하고, 시스템 전반을 구조적으로 바라보는 역량을 키웠습니다.

업무 프로세스와 요구사항을 전체 흐름 관점에서 이해하고, 이를 기반으로 요구사항 정의서와 IA를 작성하며 기능 구조를 명확히 정리했습니다. 이후 데이터 구조와 API 설계로 연결하여 일관된 시스템 흐름을 구성했습니다.

서버 인프라는 클라우드(AWS)를 활용해 배포 및 로드밸런싱 환경을 구성했으며 데이터베이스는 직접 ERD 설계, MySQL, PostgreSQL, Redis 등을 활용해 서비스 특성에 맞는 구조로 설계했습니다.

프론트엔드에서는 React를 활용해 사용자 흐름을 고려한 UI를 구현했으며, 기능 단위가 아닌 서비스 전체 맥락에서 일관된 동작을 만드는 데 집중했습니다.

기획, 프론트엔드, 백엔드 역할이 명확히 나뉘어 있지만, 각 영역에 대한 이해를 바탕으로 전체 흐름을 파악할 때 업무 프로세스를 보다 효율적으로 풀어낼 수 있다고 생각합니다.

02 핵심역량

COMPETENCIES

업무능력

구조 분석 · 시스템 재설계

  • 레거시 시스템 분석, 구조 개선
  • 요구사항 재정의 및 리뉴얼 방향 수립
  • DDD 기반 도메인 구조 설계
  • 서비스 아키텍처 및 기능 흐름 재구성

API 설계 · 백엔드 개발

  • API 설계(API 명세서 포함) 및 비즈니스 로직 구현
  • 외부 API 연동
  • 크론 및 큐 기반 비동기 처리 설계(배치 작업)
  • 서비스 로직 중심 서버 개발

문제 해결 · 운영 자동화

  • 반복 작업 자동화 및 운영 효율 개선
  • 광고 데이터 수집 및 처리 자동화
  • 로그 기반 문제 분석 및 개선
  • 서비스 운영 프로세스 개선

End-to-End 개발 · 운영

  • 개발·배포·운영까지 수행
  • AWS 기반 인프라 구성
  • 서비스 배포 및 운영 환경 구축
  • 장애 대응 및 서비스 안정성 관리
  • 깃 규칙 정립

02 핵심역량

COMPETENCIES

기술스택
PHP90%
CodeIgniter70%
Laravel90%
Python40%
Django50%
JAVA50%
SpringBoot50%
JavaScript60%
React30%
next.js50%

뷰랩

성형·뷰티 중개 플랫폼의 백엔드와 프론트엔드를 함께 설계하고 관리자 운영 구조를 다시 세운 프로젝트

프로젝트 소개

뷰랩은 성형·시술 병원과 뷰티·라이프스타일 업체를 함께 다루는 플랫폼이지만, 운영 흐름은 단순하지 않았습니다. 일반 사용자, 병원 파트너, 뷰티 파트너, 내부 운영자가 같은 화면을 사용하고 있었고, 서비스가 커질수록 API 구조와 관리자 구조를 다시 잡아야 하는 상황이었습니다. 저는 이 프로젝트에서 단순 기능 추가보다 먼저 전체 흐름을 재정리하는 역할을 맡았고, 백엔드와 프론트엔드가 같은 기준으로 움직일 수 있도록 설계 기준을 세우는 일부터 시작했습니다.

특히 기존 앱은 여러 개발자를 거치며 레거시가 누적된 상태였습니다.

  • 스파게티 코드와 이른바 외계인 코드가 많아 구조를 읽는 것 자체에 비용이 큰 상태였습니다.
  • 권한 체계는 존재했지만 실제 권한 검증에 쓰이지 않고, 메뉴를 안 보이게만 처리하는 수준에 머물러 있었습니다.
  • Actor별 분리 없이 하나의 관리자 안에서 메뉴만 보였다 숨겼다 하는 방식이라 URL을 직접 아는 경우 화면 진입이 가능한 구조적 문제가 있었습니다.
  • 이미지와 동영상이 분리된 스토리지 전략 없이 같은 서버 안에서 뒤섞여 관리되고 있었습니다.
  • S3 같은 클라우드 스토리지를 사용하지 않아 저장 용량이 이미 한계에 가까웠습니다.
  • 메모리 사용량도 높아 일부 게시판은 목록조차 정상적으로 불러오지 못하는 상황이 있었습니다.

특히 합류 직후에는 바로 신규 기능을 붙이지 않았습니다. 기존 관리자 동선, 기존 API, 인증 흐름, 예외 처리, 세션과 권한 구조를 먼저 해체해서 보고, 문제 분석 보고서와 기존 API 문서화를 통해 현재 상태를 명확히 파악했습니다. 이후 신규 개발로 방향을 잡으면서 요구사항 정의, 문서 목록, ERD, 도메인과 상태 정의, API 기준을 먼저 정리한 뒤 구현을 진행했습니다.

백엔드

백엔드는 Laravel 기반으로 다시 정리했습니다. 뷰랩 플랫폼은 Staff, Hospital, Beauty, User가 각각 다른 진입점과 인증 정책을 가지므로, 라우트를 Actor 기준으로 분기하고 도메인 비즈니스 로직은 Domain 계층으로 분리하는 방향으로 구조를 잡았습니다. Controller는 요청과 응답 연결에 집중시키고, 실제 상태 변경 규칙은 Action, Query, Policy, Model 계층에 두는 방식으로 정리했습니다.

기존 구조에서 가장 먼저 손봐야 했던 부분도 바로 이 경계였습니다. 레거시 관리자에서는 권한이 실제 서버 검증보다 메뉴 표시 여부에 가까웠고, Actor별 API 경계도 분리되지 않아 내부 운영자, 병원 파트너, 뷰티 파트너가 같은 구조 안에서 섞여 있었습니다. 그래서 신규 백엔드에서는 `/api/v1/staff`, `/api/v1/hospital`, `/api/v1/beauty`, `/api/v1/user`로 진입점을 나누고, Sanctum ability와 permission을 함께 확인하는 방식으로 기준을 다시 세웠습니다.

문서를 먼저 세운 이유는 구현보다 기준이 더 중요했기 때문입니다. 기존 API를 전수 문서화한 뒤 신규 설계 단계에서 요구사항 정의서, Information Architecture, 와이어프레임, 플로우차트, 권한/가드 정의서, 카테고리 정의, ERD, 도메인 및 상태 정의, API 명세, 테스트 케이스, 운영 배포 체크리스트까지 문서 체계를 만들었습니다. 이 과정에서는 Codex AI를 적극 활용해 레거시 구조 분석, 문서 초안 정리, 반복적인 구조 비교, 코드 초안 작성과 리팩터링 정리 작업 속도를 끌어올렸고, 최종 설계 판단과 적용 기준은 직접 검증하면서 확정했습니다. 덕분에 기능이 늘어나도 개발 기준이 흔들리지 않았고, 병원/뷰티/콘텐츠/알림/채팅 같은 서로 다른 영역을 같은 규칙 아래에서 확장할 수 있었습니다.

운영 기준도 함께 묶었습니다. 공통 ApiResponse와 traceId, Redis Queue, Horizon, Reverb, 알림 구조, Scheduler, Logging, Error Handling 문서를 정리했고, 내부 운영자가 API와 운영도구를 분리된 정책으로 접근할 수 있도록 별도 내부도구 허브도 구성했습니다. 단순히 API를 만드는 데서 끝나는 것이 아니라, 개발 이후 운영까지 이어지는 백엔드 체계를 만드는 데 집중한 프로젝트였습니다.

스토리지와 리소스 문제도 백엔드 관점에서 함께 정리해야 했습니다. 기존에는 이미지와 동영상이 같은 서버 자원 안에서 혼재되어 있었고, 서버 용량과 메모리 한계가 이미 운영 문제로 드러난 상태였습니다. 이 프로젝트에서는 단순 CRUD를 넘어서 미디어 관리, 업로드 정책, 비동기 처리, 운영 도구 접근 정책까지 같이 설계해 더 이상 한 서버 안에서 무질서하게 누적되지 않도록 구조를 바꾸는 데 집중했습니다.

기술 스택
PHP 8.3+ Laravel 12 Sanctum Reverb Horizon Redis MySQL / MariaDB SQLite Spatie Permission Activitylog Schedule Monitor FCM / APNs

인증, 권한, 실시간 이벤트, 비동기 처리, 운영 로그, 스케줄 모니터링까지 모두 하나의 백엔드 기준으로 정리한 점이 이 프로젝트의 핵심이었습니다.

권한과 인증 구조

API는 Actor별 guard와 ability를 분리해 인증했습니다. Staff, Hospital, Beauty, User 각각 `/api/v1/{actor}` 진입점이 다르고, 보호 라우트는 Sanctum 토큰과 actor ability를 함께 검사합니다. Staff/Hospital/Beauty는 Spatie Permission으로 role과 permission을 관리했고, 권한 문자열과 역할 문자열은 `AccessPermissions`, `AccessRoles`를 단일 소스로 유지해 시더를 통해 동기화되도록 구성했습니다.

DDD 설계

설계의 중심은 Actor와 Domain의 경계를 분리하는 것이었습니다. `Staff`, `Hospital`, `Beauty`, `User`는 API 사용 주체의 경계이고, `Hospital`, `Beauty`, `HospitalVideo`, `Talk`, `Chat`, `Notification`, `Notice`, `Faq`는 업무 책임의 경계입니다. HTTP 진입점은 `app/Modules/*`, 비즈니스 규칙은 `app/Domains/*`, 공통 응답과 예외/권한 상수는 `app/Common/*`에 두어 책임이 섞이지 않게 만들었습니다.

설계 원칙
  • Controller에는 비즈니스 규칙을 두지 않고 요청 해석과 응답 연결만 담당
  • 하나의 유스케이스는 Action 단위로 표현하고, 조회/저장 조건은 Query로 분리
  • 도메인 상태값은 Model 상수로 관리하고, 접근 제어는 Policy와 Permission으로 명시
  • 공통 기능은 `app/Common`, `app/Domains/Common`으로 이동하되 기술 종류보다 업무 소유권 기준으로 배치
  • 큐 Job도 공용 폴더에 몰지 않고 소유 도메인 하위에 배치해 변경 영향 범위를 최소화
주요 기능

Staff API 기준으로 모든 주요 도메인을 관리할 수 있도록 구성했고, Hospital/Beauty 파트너는 병원, 뷰티 파트너 회원들이 쓰는 도메인을 따로 분리했습니다. User API는 유저가 쓰는 기능에 더해 이후 앱 기능 확장의 기반이 되도록 설계했습니다.

프로젝트 구조
beaulab_backend/
├── app/
│   ├── Common/                    # 공통 응답, 예외, 권한 상수, 미들웨어
│   ├── Domains/                   # 도메인 모델, Action, Query, DTO, Policy
│   │   ├── AccountStaff/
│   │   ├── AccountHospital/
│   │   ├── AccountBeauty/
│   │   ├── AccountUser/
│   │   ├── Hospital/
│   │   ├── Beauty/
│   │   ├── HospitalDoctor/
│   │   ├── BeautyExpert/
│   │   ├── HospitalVideo/
│   │   ├── Talk/
│   │   ├── Chat/
│   │   ├── Notice/
│   │   ├── Faq/
│   │   └── Common/
│   ├── Modules/                   # Actor별 HTTP 진입점
│   │   ├── Staff/
│   │   ├── Hospital/
│   │   ├── Beauty/
│   │   └── User/
│   └── Providers/
├── bootstrap/app.php              # 라우팅, 미들웨어, 전역 예외 처리
├── config/
├── database/
├── develop-doc/
├── resources/views/tools/
├── routes/
│   ├── api.php
│   ├── web.php
│   ├── channels.php
│   └── console.php
└── artisan
에러와 예외 처리

예외 처리는 `bootstrap/app.php` 단일 지점에서 관리했습니다. Validation, Authentication, Authorization, ModelNotFound, MethodNotAllowed, Rate Limit, Token Error, QueryException, 기타 Throwable을 ErrorCode와 HTTP Status로 매핑하고, 모든 API 에러 응답은 `success`, `error.code`, `error.message`, `traceId` 구조로 통일했습니다. 운영 환경에서는 상세 SQL이나 내부 구현 정보를 응답에 노출하지 않고, 추적은 `traceId` 기준으로 하도록 설계했습니다.

{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "요청 값이 올바르지 않습니다."
  },
  "traceId": "request-trace-id"
}
로깅 전략

로그는 앱 로그, 감사 로그, 큐/Horizon 로그, 스케줄 모니터 로그, Telescope 관측 로그로 나눠 봤습니다. 앱 로그는 `storage/logs/laravel.log`, 감사 로그는 `activity_log`, 실패 큐는 `failed_jobs`, 배치 상태는 `job_batches`, 스케줄 상태는 Schedule Monitor 테이블, 개발/디버그 관측은 Telescope 테이블로 관리했습니다. `RequestId` 미들웨어가 `X-Request-Id`를 읽거나 UUID를 생성해 로그 컨텍스트와 응답 헤더, API 응답의 `traceId`에 공통으로 반영하도록 정리한 점도 운영 측면에서 중요했습니다.

큐와 스케줄러

비동기 런타임은 Redis + Horizon 기준으로 정리했습니다. 큐 레인은 `critical`, `mail`, `sms`, `chat`, `notifications`, `default`, `maintenance`로 분리했고, Horizon Supervisor도 레인별로 나눠 적체와 병목을 빠르게 파악할 수 있게 구성했습니다. Job은 기술 종류가 아니라 업무 소유 도메인 기준으로 배치해 어떤 도메인이 이 후처리를 책임지는지가 구조상 분명하게 드러나도록 했습니다.

스케줄러는 OS crontab이 매분 `php artisan schedule:run`을 실행하고, Laravel Scheduler가 `routes/console.php`의 작업을 수행하며, Spatie Schedule Monitor가 실행 결과를 DB에 기록하는 구조입니다. 실제 운영 작업으로는 `schedule-monitor:sync`, `notice:cleanup-temp-editor-images --hours=24`, `horizon:snapshot`, `queue:prune-batches`, `queue:prune-failed` 등을 관리했습니다.

백엔드 분석 및 설계 산출물

아래 이미지는 제가 합류 후 가장 먼저 정리했던 기존 API 분석 문서와, 신규 개발을 위해 직접 만든 요구사항 정의서, 문서 체계, ERD 일부입니다. 이 프로젝트에서는 개발을 빨리 시작하는 것보다 무엇을 어떤 기준으로 만들지 먼저 고정하는 일이 더 중요했습니다.

기존 API 문서화 화면
기존 API 구조와 예외 사항을 다시 문서화한 화면
STAFF 요구사항 정의서 화면
신규 관리자 개발을 위한 STAFF 요구사항 정의서
설계 문서 목록 화면
프로젝트 전체 문서 체계를 먼저 고정한 목록
뷰랩 ERD 다이어그램
신규 플랫폼 기준으로 다시 설계한 ERD와 도메인 관계

프론트엔드

프론트엔드는 Next.js App Router 기반 모노레포로 정리했습니다. 구조상으로는 `staff-web`은 직원 관리자, `user-web`은 유저 웹, `user-app`은 유저 앱, `beauty-web`과 `hospital-web`은 각 파트너용 웹으로 나누는 방향으로 설계했습니다. 다만 이 프로젝트 시점에는 전체 제품군이 완성된 상태는 아니었고, 구조를 먼저 정리한 뒤 단계적으로 확장하는 과정에 있었습니다. 공통 HTTP, 인증, 타입, 관리자 UI는 `packages/api-client`, `packages/auth`, `packages/types`, `packages/ui-admin` 패키지로 분리해 앱마다 같은 기반을 재사용할 수 있게 구성했습니다.

프론트도 레거시 문제를 그대로 안고 있었습니다. 권한 체계가 있어도 실제 화면 보호보다 메뉴 숨김 위주로만 쓰이고 있었고, Actor별 분리 없이 하나의 관리자에 기능이 섞여 있어 병원/뷰티/운영 흐름이 한 화면 구조 안에서 뒤엉켜 있었습니다. 결과적으로 메뉴만 가려졌을 뿐 URL을 직접 입력하면 접근 가능한 화면이 남아 있었고, 구조상 어떤 사용자가 어떤 도메인에 접근하는지 경계가 명확하지 않았습니다.

프론트 구조 역시 백엔드와 같은 철학으로 정리했습니다. Actor 경계와 도메인 경계를 분리하고, 우선 구현이 많이 진행된 `apps/staff-web` 안에서는 병원, 의료진, 동영상, 공지사항, 해시태그, 토크 같은 도메인 단위로 `components`, `hooks`, `lib`를 나눴습니다. 직원 관리자 shell, 사이드바, 권한 기반 메뉴 노출, route permission guard는 staff-web 공통 레이어가 소유하고, 뷰티/병원/staff에서 함께 쓰는 공통 컴포넌트와 UI는 `packages/ui-admin` 패키지로 올려 돌려쓰는 구조로 정리했습니다.

구현 관점에서는 운영자가 반복적으로 쓰는 화면 품질을 중요하게 봤습니다. 병의원/뷰티 도메인 토글, 목록/상세/등록/수정 흐름, 공지사항 에디터, 업로더, 모달, 전역 alert, spinner, permission 기반 메뉴 제어, `returnTo`와 `highlight` query를 활용한 목록 복귀 UX까지 일관된 패턴으로 맞췄습니다. 특히 관리자 웹은 보기 좋은 화면보다 계속 써도 피로하지 않은 구조가 더 중요하다고 판단해, 도메인 기준으로 정보 밀도를 조정하고 공통 패턴을 재사용하는 쪽으로 정리했습니다.

기술 스택
Next.js 16 React 19 TypeScript 5 Tailwind CSS 4 pnpm workspace Turborepo ESLint 9 Laravel Echo Pusher JS TipTap React Day Picker lucide-react
서비스 범위

프론트 서비스 범위는 `Staff Web`, `User Web`, `User App`, `Beauty Web`, `Hospital Web`, 그리고 이를 받치는 공통 프론트엔드 인프라를 기준으로 설계했습니다. 이 중 구현이 가장 많이 진행된 것은 직원 관리자용 `Staff Web`이고, 여기서는 로그인과 세션 복구, 병의원/뷰티 도메인 토글 기반 관리자 shell, 병원/의료진/동영상/토크/공지사항/FAQ/회원/카테고리/해시태그 관리, 뷰티 운영 화면과 공통 운영 화면을 담당했습니다.

`User Web`은 유저 웹 구조를 잡기 위한 영역이고, `User App`은 실제 앱 흐름을 염두에 둔 영역입니다. 당시에는 이 둘 모두 완성 단계가 아니라 유저 간 1:1 채팅, 알림, Reverb 이벤트 같은 공통 커뮤니케이션 흐름을 먼저 검증하는 용도로 설계와 일부 검증 화면 위주로 진행됐습니다. `Beauty Web`, `Hospital Web` 역시 파트너 전용 제품 경계를 분리하는 방향으로 구조를 잡았지만, 이 시점에는 아직 미완성 상태였습니다.

공통 인프라는 pnpm workspace + Turborepo 모노레포를 기반으로, actor별 token/session storage, API client와 ApiResponse 타입, 메뉴 권한과 라우트 권한 매핑, 관리자 공통 UI 컴포넌트 재사용을 중심으로 정리했습니다.

프로젝트 구조
beaulab_frontend/
├── apps/
│   ├── staff-web/
│   │   ├── app/
│   │   │   ├── (admin)/
│   │   │   └── (auth)/
│   │   ├── components/
│   │   │   ├── common/
│   │   │   ├── hospital/
│   │   │   ├── doctor/
│   │   │   ├── video/
│   │   │   ├── notice/
│   │   │   ├── hashtag/
│   │   │   └── talk/
│   │   ├── hooks/
│   │   └── lib/
│   ├── user-web/
│   │   └── app/
│   ├── user-app/
│   ├── beauty-web/
│   └── hospital-web/
├── packages/
│   ├── api-client/
│   ├── auth/
│   ├── types/
│   └── ui-admin/
├── doc/
│   ├── architecture.md
│   └── staff-web-rules.md
├── package.json
├── pnpm-workspace.yaml
├── turbo.json
└── tsconfig.base.json
프론트 구조 설명

프론트도 백엔드와 마찬가지로 책임을 분리하는 쪽으로 설계했습니다. `packages/*`는 actor나 도메인을 모르는 범용 레이어로 두고, 각 앱은 자신이 담당하는 사용자군의 제품 로직을 소유하게 했습니다. 이 중 직원 관리자용 `apps/staff-web`이 가장 먼저 구체화되었고, 페이지 라우트는 App Router, 페이지 상태와 submit/fetch 흐름은 `*Client.tsx`, 도메인 전용 section/table/filter/modal은 `components/{domain}`, endpoint와 field name에 강하게 묶이는 로직은 `hooks/{domain}`, `lib/{domain}`으로 분리해 구조가 한쪽으로 무너지지 않게 유지했습니다.

공통 UI 전략도 분명하게 잡았습니다. 뷰티, 병원, staff 영역에서 함께 쓰는 공통 컴포넌트와 UI는 `packages/ui-admin`으로 올려 재사용하고, 각 앱은 그 위에 자신의 도메인 로직과 화면 조합만 얹는 구조로 설계했습니다. 즉 제품별로 화면을 따로 복제하기보다, 공통 패턴은 패키지에서 돌려쓰고 도메인 차이는 앱 레이어에서 풀어내는 방식입니다.

권한도 UX 제어 관점에서 정리했습니다. token은 `beaulab.token.{actor}`, session은 `beaulab.session.{actor}` key로 분리 저장하고, 메뉴 노출과 route guard는 같은 permission source를 참조하게 했습니다. 다만 프론트 권한은 최종 권한 검증을 대체하지 않도록 하고, 실제 보안 검증은 서버가 담당하는 구조를 유지했습니다.

운영 관리자 화면

아래 1번부터 8번까지는 실제 운영자가 사용하는 관리자 화면입니다. 병원/뷰티 운영, 검색과 필터, 상태값 관리, 등록 및 수정 흐름이 한 구조 안에서 이어지도록 설계했고, 백엔드에서 정의한 권한과 상태 체계를 프론트 화면에도 일관되게 반영했습니다.

뷰랩 관리자 화면 1
운영 관리자 화면 01
뷰랩 관리자 화면 2
운영 관리자 화면 02
뷰랩 관리자 화면 3
운영 관리자 화면 03
뷰랩 관리자 화면 4
운영 관리자 화면 04
뷰랩 관리자 화면 5
운영 관리자 화면 05
뷰랩 관리자 화면 6
운영 관리자 화면 06
뷰랩 관리자 화면 7
운영 관리자 화면 07
뷰랩 관리자 화면 8
운영 관리자 화면 08

개발툴 관리자

개발툴 관리자는 일반 관리자와 별개로 API Docs, Horizon, Telescope를 관리하기 위한 내부 운영 도구입니다. 백엔드 문서에서 정리한 것처럼 `tool_staff` 세션 인증, 허용 IP, Gate 기준을 함께 적용해 브라우저 기반 내부도구 접근 정책을 따로 분리했고, 로그인 후 하나의 허브 화면에서 필요한 도구로 이동할 수 있게 구성했습니다.

이 부분은 단순 편의 기능이 아니라 운영 안정성과도 연결됩니다. API 명세 확인, 큐 상태 모니터링, 요청/쿼리/예외 추적을 같은 관리 흐름 안에 두면 개발자와 운영자가 문제를 훨씬 빠르게 확인할 수 있기 때문입니다.

개발툴 관리자 로그인 화면
개발툴 관리자 로그인 화면
개발툴 관리자 허브 화면
API Docs, Horizon, Telescope를 묶은 내부도구 허브
API Docs 화면
Scramble 기반 API Docs 화면
Horizon 모니터링 화면
큐 상태와 워커를 보는 Horizon
Telescope 디버깅 화면
요청과 예외를 추적하는 Telescope

제니스

광고 운영, 자동화, 이벤트 관리, 내부 협업 업무를 하나의 백오피스에서 처리하기 위해 만든 CodeIgniter 4 기반 사내 운영 도구

프로젝트 소개

제니스는 광고 운영, 이벤트 관리, 사용자 관리, 내부 협업 업무를 하나의 관리자 시스템 안에서 처리할 수 있도록 만든 CodeIgniter 4 기반 사내 운영 도구입니다. 여러 광고 매체를 따로따로 운영하는 대신, 운영자가 실제로 사용하는 업무 흐름을 기준으로 광고 리포트 확인, 상태 변경, 자동화 실행 결과 조회, 이벤트 실무 처리, 내부 협업 연동이 한 서비스 안에서 이어지도록 설계했습니다.

이 프로젝트는 외부 공개용 제품이라기보다 실무자가 매일 쓰는 백오피스입니다. 광고 운영 현황을 보고 바로 상태를 조정하고, 자동화 조건을 관리하고, 이벤트 업무와 광고주/블랙리스트/변경 이력 같은 운영 데이터를 함께 다루는 쪽에 초점을 두었습니다.

현재 저장소는 공개 가능한 범위만 정리한 스냅샷입니다. 민감한 SQL, 외부 연동 키, 일부 설정 파일, 모델/라이브러리의 세부 구현은 제외되어 있지만, 포함된 컨트롤러와 뷰, 정적 자산 구조만으로도 전체 서비스가 어떤 업무를 다루는지와 운영 방향은 충분히 읽히도록 구성했습니다.

핵심 기능

  • Facebook, Google, Kakao, Naver 등 여러 광고 매체를 한 관리자 안에서 운영
  • 홈 화면에서 매체별 리포트 수집 및 운영 현황 확인
  • 조건 기반 자동화 실행, 상태 변경, 예산 조정, 실행 결과/로그 조회
  • 광고주 관리, 블랙리스트, 변경 이력, 엑셀 업로드, 매체 관리 등 이벤트/운영 실무 지원
  • Jira 이슈 상태 변화 연동과 Slack 사용자 알림 발송으로 내부 협업 연결
  • 로그인, 매직 링크, 비밀번호 변경 및 변경 주기 체크 등 계정/인증 관리
  • 회계, 인사, 회사 정보, 캘린더, 사용자, 통합 관리 같은 공통 관리자 기능 포함
  • `public/health.php`를 통한 JSON 헬스체크 응답 제공

구현 포인트

이 프로젝트에서는 광고 운영만 따로 떼어 놓은 도구를 만드는 대신, 사내 운영자가 실제로 같이 쓰는 업무 흐름을 한 백오피스 안에 묶는 방향으로 작업했습니다. 광고 매체 운영, 자동화 실행, 이벤트 실무, 사용자 인증, 외부 협업 도구 연동이 각각 따로 노는 구조가 아니라 하나의 관리자 안에서 이어지도록 정리한 것이 핵심입니다.

구조도 업무 기준으로 나눴습니다. `Accounting`, `Advertisement`, `AdvertisementManager`, `Api`, `Auth`, `Calendar`, `Company`, `EventManage`, `HumanResource`, `Integrate`, `User` 영역으로 나뉘어 있고, 로컬 스냅샷 기준으로 PHP 컨트롤러 36개, View 템플릿 87개 규모로 구성돼 있습니다.

세부적으로는 `HomeController`에서 로그인 사용자의 비밀번호 변경 시점을 확인하고, AJAX 요청에서만 리포트 응답을 내려주며, 예외 발생 시 API 에러 응답을 처리하도록 구성했습니다. `ExampleController`에서는 뷰 이름 화이트리스트 패턴 검증과 존재하지 않는 뷰 접근 차단을 넣었고, `PasswordChangeController`에서는 Shield 비밀번호 정책과 강제 재설정 해제를 다뤘습니다. 단순 화면 나열이 아니라 실무 운영에 필요한 제어 포인트가 컨트롤러 단에서 바로 드러나도록 정리한 프로젝트입니다.

기술 스택

PHP 8.0+ CodeIgniter 4 CodeIgniter Shield CodeIgniter Settings CodeIgniter Tasks MySQL Slack Jira Advertisement API Bootstrap 5 jQuery DataTables

백엔드는 PHP + CodeIgniter 4, 인증은 CodeIgniter Shield, 데이터와 외부 연동은 MySQL, Slack, Jira, 광고 매체 API를 기준으로 구성했습니다. 프론트 정적 에셋은 Bootstrap 5, Bootstrap Icons, jQuery, jQuery UI, DateRangePicker, DataTables, JSZip, pdfmake 기준으로 구성되어 있어, 사내 운영 도구 특유의 테이블 중심 화면과 폼 중심 화면을 빠르게 다룰 수 있도록 맞춰져 있습니다.

저장소 구조

php_ci4_zenith-my-commits/
├── README.md
└── zenith-project/
    ├── .github/
    │   ├── COMMIT_CONVENTION.md
    │   ├── pull_request_template.md
    │   └── workflows/php-lint.yml
    ├── app/
    │   ├── Controllers/
    │   └── Views/
    ├── public/
    │   ├── health.php
    │   └── static/
    ├── composer.json
    └── spark

이 저장소는 공개 가능한 범위만 정리한 버전입니다. 민감한 연동 설정, 일부 모델과 라이브러리, 환경 파일은 제외되어 있어 내부 운영 환경을 그대로 재현하는 용도보다는, 실제 서비스가 어떤 구조와 화면, 컨트롤러 설계, 운영 도메인으로 구성돼 있는지 보여주는 용도에 가깝습니다.

운영 화면

아래 이미지는 제니스 관리자 화면 일부입니다. 통합 광고관리, 운영 데이터 관리, 자동화 목록처럼 운영자가 실제로 자주 사용하는 화면 위주로 정리했고, 좌측 사이드바와 테이블 중심 레이아웃을 통해 사내 운영 도구의 성격이 바로 드러나도록 구성했습니다.

제니스 통합 광고 관리 화면
통합 광고 관리와 운영 데이터가 함께 보이는 메인 화면
제니스 운영 상세 화면
광고 운영과 이벤트 실무 데이터를 함께 다루는 관리 화면
제니스 자동화 목록 화면
조건 기반 자동화 실행 목록과 상태를 관리하는 화면
제니스 자동화 설정 모달 화면
자동화 실행 시간과 조건을 세부 설정하는 모달 화면

공개 범위와 운영 규칙

저장소에는 커밋 규칙, PR 템플릿, PHP 문법 검사를 위한 GitHub Actions 워크플로우가 함께 들어 있습니다. `.env`, `vendor`, 로그/세션/업로드 파일, `node_modules`, 외부 API 설정 파일, 광고 연동용 비공개 키/설정 파일은 버전 관리에서 제외되도록 정리돼 있어, 운영 환경을 그대로 공개하지 않으면서도 협업 규칙과 코드 구조는 확인할 수 있게 만들었습니다.

제니스 랜딩 운영 모듈

제니스 프로젝트에는 백오피스 외에 광고/이벤트 캠페인용 랜딩 페이지를 실제로 운영하는 별도 PHP 모듈도 함께 있었습니다. 이 모듈은 여러 도메인에서 방문자를 받아 랜딩 페이지를 출력하고, 신청 데이터를 수집한 뒤 중복 검증, 상태 분류, 외부 제휴 전송, 완료 페이지 이동까지 처리하는 실행 계층입니다.

역할을 나누면, 제니스 백오피스가 이벤트, 광고주, 매체, 전송 조건 같은 운영 데이터를 관리하고, 랜딩 운영 모듈은 그 설정을 바탕으로 실제 방문 요청을 받아 처리하는 구조였습니다. 즉 관리자에서 운영 기준을 만들고, 랜딩 모듈이 현장에서 그 기준을 실행하는 형태로 맞물려 있었습니다.

핵심 처리 흐름
  1. 방문자가 이벤트 URL 또는 해시 URL로 랜딩 페이지에 접근
  2. `zenith_core.php`가 이벤트 번호를 해석하고 DB에서 랜딩 정보 조회
  3. 이벤트별 랜딩 파일과 헤더/푸터 템플릿을 조합해 페이지 출력
  4. 폼 제출 시 `zenith_check_proc.php`가 필수값, 중복, 블랙리스트, 정책 조건 검사
  5. 정상 데이터는 DB 저장 후 상태 코드 분류
  6. 설정에 따라 Facebook Pixel 또는 제휴사 interlock 전송 수행
  7. 처리 결과에 따라 thanks 페이지나 결과 페이지로 이동
주요 기능
  • 이벤트 번호 또는 해시 기반 랜딩 페이지 라우팅
  • 이벤트별 HTML/PHP 템플릿 동적 로드
  • 신청 폼 데이터 수집 및 저장
  • 이름/전화번호/IP/쿠키 기준 중복 검증
  • 블랙리스트 및 운영 정책 기반 상태 분류
  • 외부 제휴사 interlock 전송 및 재전송
  • 완료 페이지 이동 및 Pixel 이벤트 전송
기술 스택
PHP MySQLi cURL OpenSSL Sodium PHP Session Cookie PHP Template Rendering Static HTML/CSS/JS

별도의 Composer/NPM 빌드 구조가 아니라, 이벤트별 PHP 템플릿과 정적 HTML/CSS/JS 파일을 직접 로드하는 방식으로 운영했습니다. 프레임워크 없이 전역 include와 파일 규칙으로 동작하므로, 실제 배포 구조와 디렉터리 배치가 코드 실행에 직접 영향을 주는 형태였습니다.

핵심 파일
zenith_core.php            # 랜딩 라우팅, 페이지 렌더링, 신청 처리, 완료 페이지 이동
zenith_check_proc.php      # 신청 데이터 검증, 상태 분류, 저장 후처리
zenith_interlock.php       # 외부 제휴 연동 결과 기록 및 재전송 처리
zenith_encryption.php      # 신청 데이터 암복호화
zenith_ip.php              # 방문자 IP 확인, 내부망/차단 처리
zenith_cookie.php          # 운영 쿠키 생성 및 조회
interlock_resend.php       # 특정 실패 건 재전송
interlock_resend_all.php   # 조건 기반 일괄 재전송
zenith_test.php            # 연동/요청 테스트 스크립트
zenith_test_form.php       # 폼 전송 테스트 화면
운영 관점에서 중요했던 부분

이 모듈은 단순 랜딩 출력기가 아니라, 실무 마케팅 운영에서 필요한 검증과 후처리를 직접 수행하는 코드였습니다. 이름/전화번호/IP/쿠키 기준 중복 검증, 블랙리스트 전화번호 차단, 나이 제한 검증, 상태 코드 분류, 메모 기록, 제휴사 interlock 전송 실패 건 재전송까지 포함돼 있어 실제 리드 운영 프로세스와 바로 연결되는 구조였습니다.

이벤츠팩

EventsPack 사용자 인증과 외부 사이트 빌더 연동을 담당한 Laravel API 서버

프로젝트 소개

EventsPack은 학술대회, 정부 행사, 기업 이벤트처럼 일정과 페이지 구성이 자주 바뀌는 행사 사이트를 빠르게 구축하기 위한 웹 솔루션입니다. 템플릿과 레이아웃 리소스를 기반으로 행사 사이트를 조립하고, 사용자 인증과 OAuth 연동을 통해 여러 외부 사이트에서도 동일한 계정 흐름을 사용할 수 있도록 설계했습니다.

제가 맡은 영역은 그중 사용자 인증과 API 연동 계층입니다. 단순 CRUD 서버가 아니라, 외부 서비스가 EventsPack 계정을 통해 인증을 위임받고 API 서버가 사용자 토큰과 리소스 접근 권한을 검증하는 구조를 구현한 것이 핵심이었습니다.

즉 프론트엔드나 외부 사이트 빌더는 이 API를 호출해 로그인 상태와 서비스 리소스 접근 가능 여부를 판단하고, API 서버는 회원/토큰/OAuth client/접근 권한을 책임지는 구조로 역할을 나눴습니다.

핵심 기능

  • 회원가입 및 로그인 API 제공
  • Laravel Passport 기반 access token 발급
  • OAuth client 생성/조회 프록시
  • 외부 앱 로그인 상태 확인과 bearer token 기반 강제 로그인 처리
  • 요청 컨트롤러/액션 기준 서비스 리소스 접근 권한 확인
  • 사이트/레이아웃/내비게이션 정보 API 제공
  • 허용 Origin 기반 CORS 처리

구현 포인트

이 프로젝트에서 중요했던 부분은 외부 서비스와 인증 서버 사이의 경계를 명확히 잡는 것이었습니다. EventsPack 계정을 기준으로 외부 사이트에서도 같은 사용자 인증 흐름을 사용할 수 있어야 했기 때문에, Passport 기반 OAuth와 토큰 검증 흐름, OAuth client 프록시, bearer token 기반 강제 로그인 처리까지 한 API 안에서 일관되게 정리했습니다.

접근 권한도 단순 로그인 여부에서 끝나지 않도록 구성했습니다. 요청이 들어온 컨트롤러와 액션 기준으로 서비스 리소스 접근 가능 여부를 판단하게 했고, 프론트나 외부 사이트 빌더는 이 결과를 기준으로 실제 화면 접근과 서비스 사용 가능 여부를 결정할 수 있게 만들었습니다.

인증을 외부 서비스에 위임할 수 있는 구조와 리소스 권한 검증 흐름까지 함께 구현한 점이 이 프로젝트의 핵심입니다.

기술 스택

PHP 7.3+ Laravel 6 Laravel Passport MySQL Guzzle HTTP Client Laravel Mix

프로젝트 구조

app/
├── Helper/                 # 메시지, 접근 권한 helper
├── Http/
│   ├── Controllers/Auth/   # 회원가입, 로그인, OAuth client API
│   └── Middleware/         # CORS, 강제 로그인, 권한 확인
├── Providers/
config/                     # Laravel 및 외부 서비스 설정
database/                   # migration, factory, seed
routes/
├── api.php                 # API endpoint
└── web.php                 # Passport/OAuth web route

보완한 부분

  • Laravel 실행에 필요한 `bootstrap/` 구조 복구
  • `.gitignore`가 `bootstrap` 전체를 제외하던 문제 수정
  • Composer/NPM 메타데이터를 프로젝트명 기준으로 정리
  • PHP 요구 버전을 lock 파일과 맞게 `7.3+`로 정리
  • CORS 허용 Origin을 `.env` 기반 설정으로 분리
  • 외부 EventsPack API URL 하드코딩 제거
  • `logoutRequest`의 잘못된 HTTP method 수정
  • 회원가입 validation 실패 후에도 생성 로직이 진행될 수 있던 흐름 수정
  • 라우트에서 호출되는 `register` 메서드 접근 제어자를 public으로 수정
  • bearer 검증 실패나 사용자 미존재 시 401로 명확히 차단

실행과 환경 설정

실행 흐름은 Laravel 표준에 Passport 초기화가 추가된 구조입니다. `composer install`, `npm install`, `.env` 복사, `php artisan key:generate`, `php artisan migrate`, `php artisan passport:install`, `php artisan serve` 순서로 구동할 수 있게 정리했고, 주요 환경변수로는 `APP_URL`, DB 계정 정보, `EVENTSPACK_API_BASE_URL`, `EVENTSPACK_ALLOWED_ORIGINS` 등을 사용했습니다.

화면 예시

아래 화면은 EventsPack 사용자 서비스 화면입니다. 행사 사이트를 빠르게 구성할 수 있도록 인증과 권한 검증을 담당한 API 서버를 구현했고, 사용자 경험 뒤에서 계정 흐름과 리소스 접근 제어를 처리했습니다.

EventsPack 사용자 화면
EventsPack 사용자 서비스 화면 예시

관련 저장소

관리자 저장소는 `php_laravel_EventPack_admin`, 사용자 API 저장소는 `php_laravel_EventsPack_dev1` 기준으로 운영했습니다. 사용자 API 계층에서는 OAuth와 서비스 리소스 권한 검증 흐름을 중심으로 구현했습니다.

이벤츠팩 관리자

EventsPack에는 사용자 인증/API 계층과 별도로 운영 데이터를 관리하는 Laravel 관리자 콘솔도 함께 있었습니다. 이 관리자 콘솔은 행사 단위 프로젝트, 사이트 기본 정보, 레이아웃 템플릿, 상단/내비게이션/중단/하단/기타 조각, 기능 팩을 관리하는 백오피스이며, 실제 행사 사이트를 구성하기 위한 기준 데이터를 만드는 역할을 맡았습니다.

역할을 나누면, 사용자 API가 회원/토큰/OAuth/접근 권한 검증을 담당하고, Admin은 사이트를 조립하기 위한 운영 데이터와 템플릿 리소스를 관리하는 구조였습니다. 즉 운영자는 여기서 프로젝트를 만들고 레이아웃과 기능 팩을 조합하며, 이후 사용자 API나 사이트 빌더가 이 데이터를 참조해 실제 행사 사이트를 구성할 수 있도록 준비하는 계층입니다.

핵심 운영 흐름
  1. 관리자가 Laravel 인증을 통해 관리자 콘솔에 로그인
  2. `super` 권한 미들웨어를 통과한 사용자만 `/admin/*` 화면 접근
  3. 행사 단위 프로젝트를 생성하고 사용자 계정과 연결
  4. 사이트 구성에 사용할 레이아웃 템플릿과 섹션 조각 등록
  5. 게시판/페이지 성격의 기능 팩과 기본 경로 관리
  6. 이후 사용자 API 또는 사이트 빌더가 이 구조를 바탕으로 행사 사이트 구성
주요 기능
  • 관리자 로그인 기반 운영 콘솔
  • 행사 단위 프로젝트(`works`) 관리
  • 프로젝트별 사이트 기본 정보(`sites`) 관리
  • 레이아웃 템플릿과 상단/내비게이션/중단/하단/기타 조각 관리
  • 사이트 기능 팩(`packs`) 관리
  • `super` 권한 기반 접근 제어
기술 스택
PHP 7.2.5+ / 8.0+ Laravel 6.20 MySQL Blade Laracasts Flash Composer Laravel Mix Axios Lodash Sass
프로젝트 구조
app/
├── Http/
│   ├── Controllers/Admin/
│   │   ├── Work/               # 프로젝트 관리
│   │   ├── Layout/             # 레이아웃 및 섹션 관리
│   │   └── Pack/               # 기능 팩 관리
│   ├── Controllers/Auth/       # 관리자 로그인/회원 인증
│   └── Middleware/             # 인증 및 super 권한 검사
├── Layout*.php                 # 레이아웃 관련 모델
├── Pack*.php                   # 팩 관련 모델
├── Site.php                    # 사이트 모델
├── User.php                    # 관리자/사용자 모델
└── Work.php                    # 프로젝트 모델
resources/views/
├── project/                    # 프로젝트 관리 화면
├── template/layout/            # 레이아웃 관리 화면
├── template/pack/              # 팩 관리 화면
└── users/                      # 사용자 관리 화면
database/migrations/
└── 2021_01_01_000001_create_eventspack_admin_tables.php
routes/
└── web.php                     # 관리자 콘솔 라우트
데이터 모델 관점

이 관리자 콘솔의 핵심은 화면보다 운영 데이터 모델입니다. `works`, `sites`, `layouts`, `layout_tops`, `layout_navigations`, `layout_middles`, `layout_bottoms`, `layout_etcs`, `packs`, `pack_board`, `pack_page`, `user_action_logs` 구조를 통해 행사 사이트를 조립하기 위한 템플릿과 기능, 운영 로그를 직접 관리하도록 구성했습니다. EventsPack 운영 데이터와 사이트 구성 리소스를 다루는 전용 백오피스입니다.

보완한 부분
  • 누락된 `artisan`, `bootstrap/`, `storage/`, `server.php`, `webpack.mix.js` 복구
  • `.env.example`, `.gitignore`, `.gitattributes` 추가
  • Composer/NPM 메타데이터를 프로젝트명 기준으로 정리
  • 기본 시간대와 locale를 국내 서비스 기준으로 정리
  • `CheckSuper` 미들웨어가 아무 것도 반환하지 않던 문제 수정
  • `/admin` 하위 라우트에 관리자 권한 미들웨어 적용
  • 없는 레코드 접근 시 null 오류 대신 `404` 처리
  • 레이아웃 하위 리소스의 잘못된 unique table 검증 수정
  • 수정 화면에서 자기 자신의 code 값 때문에 validation이 실패하던 문제 수정
  • `LayoutMiddleController`에 남아 있던 깨진 코드 조각 제거
  • 모델 관계 오류 수정
  • 모델 구조에 맞는 통합 migration 추가

백락온

일반 상품, 정기배송, 연계상품, 결제, 관리자 백오피스를 하나의 Laravel 애플리케이션 안에서 운영한 건강식품 쇼핑몰

프로젝트 소개

백락온은 건강식품 판매를 위한 Laravel 기반 쇼핑몰 프로젝트입니다. 일반 상품 판매, 정기배송 상품, 연계상품 주문, Toss Payments 결제, 회원/배송지/주문 관리, 관리자 백오피스를 하나의 서비스 흐름으로 구성한 커머스 애플리케이션입니다.

이 프로젝트는 단순 상품 진열 페이지가 아니라 회원가입과 소셜 로그인, 장바구니, 주문 생성, 결제 콜백, 주문 상태 관리, 상품 이미지 업로드, 관리자 CRUD, SMS 알림 기록까지 포함한 실서비스형 쇼핑몰이라는 점이 핵심입니다. 사용자 구매 흐름과 운영 백오피스, 외부 결제와 알림 연동을 하나의 Laravel 프로젝트 안에서 함께 처리하는 구조로 정리했습니다.

핵심 서비스 흐름

  1. 사용자가 일반 상품, 정기배송 상품, 연계상품 페이지를 탐색
  2. 로그인 사용자 기준으로 장바구니 또는 바로주문 흐름 진행
  3. 주문 생성 후 Toss Payments 결제 시도
  4. 결제 성공/가상계좌 콜백이 들어오면 주문 상태와 이력 갱신
  5. 필요 시 Aligo SMS로 운영 알림을 전송하고 이력 저장
  6. 사용자는 마이페이지에서 주문/배송지/회원정보 관리
  7. 운영자는 `/admin` 이하 백오피스에서 상품, 주문, 정기배송, 연계상품, 문의, 회원 관리

주요 기능

  • 회원가입, 로그인, 이메일 인증, Kakao/Naver 소셜 로그인
  • 상품 목록/상세, 장바구니, 일반 주문 생성과 저장
  • 정기배송 상품 목록/상세/주문과 일반 주문 모델 분리
  • 연계상품 별도 목록/상세/주문 흐름 운영
  • Toss Payments 결제 성공 콜백과 가상계좌 입금 상태 처리
  • Aligo SMS 운영 알림 전송과 기록 저장
  • 마이페이지에서 일반 주문/정기배송/연계상품 주문, 배송지, QnA 관리
  • 관리자 백오피스에서 회원/상품/카테고리/주문/문의 통합 관리

기술 스택

PHP 7.3+ Laravel 6 MySQL Blade Laravel Socialite Toss Payments Aligo SMS Composer Laravel Mix Axios Lodash Sass

프로젝트 구조

100rakon_com/
├── app/
│   ├── Http/Controllers/        # 쇼핑몰, 주문, 결제, 관리자 컨트롤러
│   ├── Http/Middleware/         # 관리자 권한, 배포 모드 검사
│   ├── Product.php              # 일반 상품 모델
│   ├── Subscrib*.php            # 정기배송 관련 모델
│   ├── Outstand*.php            # 연계상품 관련 모델
│   ├── Order*.php               # 일반 주문 관련 모델
│   ├── PayTossTransaction.php   # Toss 결제 이력
│   └── SmsSend.php              # SMS 발송 이력
├── config/
├── database/
│   ├── migrations/
│   ├── factories/
│   └── seeds/
├── public/
├── resources/
│   ├── views/                   # mall, auth, admin Blade 화면
│   ├── sass/
│   └── js/
├── routes/
│   ├── web.php
│   └── api.php
├── storage/
└── bootstrap/

데이터 모델 관점

이 프로젝트는 단일 주문 테이블만 있는 단순 쇼핑몰이 아니라, 일반 주문, 정기배송, 연계상품을 각각 다른 모델 묶음으로 분리해 관리하는 구조가 특징입니다. `User`, `UserAddress`, `Product`, `ProductCategory`, `Order`, `OrderItem`, `OrderBasket`, `OrderHistory`, `SubscribGood`, `SubscribOrder`, `SubscribOrderHistory`, `Outstand`, `OutstandOrder`, `OutstandHistory`, `PayTossTransaction`, `SmsSend`, `Qna` 등으로 나뉘어 있어 구매 유형별 흐름과 이력을 별도로 다룰 수 있게 정리했습니다.

외부 연동과 운영 포인트

결제와 운영 알림이 실제 운영 흐름에 직접 연결돼 있다는 점이 이 프로젝트의 중요한 포인트였습니다. Toss 결제 성공 및 가상계좌 콜백이 들어오면 주문 상태와 주문 이력을 함께 갱신하고, 필요 시 Aligo SMS 운영 알림 기록까지 남기도록 구성했습니다. 관리자 기능도 별도 프로젝트가 아니라 같은 앱 내부 `/admin` 네임스페이스 안에서 함께 운영되며, `check.admin` 미들웨어가 로그인 여부와 `super === 'Y'` 권한을 같이 검사하도록 정리했습니다.

보완한 부분

  • Laravel 실행에 필요한 `bootstrap/`과 `config/` 구조 복구
  • `.env.example`과 `.gitignore` 추가
  • 관리자 접근 미들웨어에서 비로그인 사용자 null 접근 오류 방지
  • 관리자 권한이 없는 사용자는 `403`으로 차단
  • 허용 IP 환경변수를 `APP_ALLOW_IPS`로 통일
  • 상품 상세 조회를 `findOrFail`로 변경해 없는 상품 접근 시 `404` 처리
  • 주문 페이지 진입 라우트에 인증 미들웨어 적용
  • Toss 가상계좌 콜백에 `secret` 검증 추가
  • 잘못된 resource parameter(`oscdx`, `sgcdx`, `sgdx`) 정리
  • 중복 등록되던 연계상품 주문 관리자 라우트 제거
  • SMS API Key, 운영자 전화번호, 입금 계좌 하드코딩 제거
  • README 인코딩 깨짐 수정 및 실행 방법 재작성

화면 예시

메인 화면, 장바구니, 주문조회 흐름을 함께 넣었습니다. 일반 주문, 정기배송, 연계상품, 결제, 백오피스를 하나의 Laravel 커머스 구조로 연결해 구현했습니다.

백락온 쇼핑몰 메인 화면
메인 화면
백락온 장바구니 화면
장바구니 화면
백락온 주문조회 화면
주문조회 화면

운영 환경과 주의 사항

이 저장소에는 운영 DB, 실제 결제 키, SMS 계정 정보가 포함되어 있지 않습니다. `public/`에 빌드 결과물이 들어 있어도 수정 개발은 `resources/`와 Laravel Mix 기준으로 진행하는 것이 맞고, Laravel 6 기반 프로젝트이기 때문에 최신 Laravel 관례와는 디렉터리/설정 방식이 일부 다릅니다. 결제와 SMS는 외부 서비스 연동 정보가 있어야 실제 동작합니다.

방치형 게임 템플릿

방치형 성장 루프와 기본 UI 구조를 빠르게 붙이기 위해 만들고 있는 템플릿 프로젝트로, 현재 기능을 채워가는 개발중 단계

현재 상태

방치형 게임 템플릿 구조를 먼저 정리하고 있으며, 핵심 루프와 화면 구성을 순차적으로 붙이고 있습니다.

의도한 방향

  • 방치형 성장 구조를 빠르게 붙일 수 있는 템플릿 형태로 정리
  • 반복 자원 획득, 업그레이드, 성장 수치 루프를 실험하기 위한 기반 준비
  • UI와 게임 로직을 분리해 이후 시스템 추가가 쉬운 구조로 확장 예정

진행 방향

전투, 성장, 재화, 업그레이드 루프를 붙일 수 있는 기반 구조를 먼저 잡고 있으며, 실제 시스템이 쌓이는 순서대로 템플릿을 확장할 예정입니다.

저장소

https://github.com/xowlsakffl/idle_game_template

빗썸 자동매수

빗썸 KRW 마켓을 대상으로 거래대금 상위 종목을 스캔하고 RSI와 이동평균 조건으로 매수 시도를 기록하는 Python 자동화 봇

프로젝트 소개

Bithumb RSI Auto Buyer는 빗썸 KRW 마켓을 대상으로 동작하는 자동 매수 봇입니다. 거래대금 상위 마켓을 조회하고, 이동평균과 RSI 조건을 만족하는 종목을 찾아 일일 예산 범위 안에서 매수 시도를 기록하도록 만들었습니다.

이 프로젝트의 핵심은 외부 거래소 API 연동, 주문 전 검증, 예산 제한, 상태 기록, 실거래 안전장치까지 포함한 자동화 구조를 구현한 점입니다. 기본값을 `PAPER=true`로 두고 실제 주문이 발생하지 않도록 설계했으며, 실거래 전 검증 가능한 구조로 정리했습니다.

주요 기능

  • `ccxt` 기반 빗썸 연동
  • 기본 페이퍼 트레이딩 모드
  • `PAPER=false`와 `LIVE_CONFIRM=true`를 동시에 요구하는 실거래 안전장치
  • RSI와 이동평균을 조합한 매수 필터
  • KRW 마켓 거래대금 상위 종목 스캔
  • 일일 KRW 예산 제한
  • 주문당 최대 매수 금액과 쿨다운 옵션
  • 중복 매수 방지를 위한 로컬 JSON 상태 관리
  • 일시적인 네트워크/거래소 오류에 대한 재시도 처리

전략 개요

봇은 거래대금 상위 KRW 마켓을 순회하면서 최근 종가가 이동평균선보다 높고, RSI가 설정한 매수 기준값보다 낮은 종목을 찾습니다. 조건을 만족하는 후보가 여러 개라면 RSI가 가장 낮은 종목을 우선 선택합니다.

전략 자체는 의도적으로 단순하게 유지했습니다. 이 프로젝트에서 중요했던 부분은 고급 매매 로직이 아니라, 실거래로 이어질 수 있는 자동화 코드에서 주문 전 검증과 예산 제한, 상태 저장, 실거래 차단 로직을 어떻게 넣을지였습니다.

기술 스택

Python 3.11 ~ 3.13 ccxt pytest dotenv JSON State File

프로젝트 구조

파일 역할
main.py 스캔 루프, 예산 체크, 매수 흐름 제어
broker.py 빗썸/ccxt 연동, 재시도 처리, 주문 전 검증
strategy.py RSI와 이동평균 기반 매수 조건
state.py 로컬 JSON 상태 저장/조회
config.py 환경변수 기반 설정과 값 검증

실행과 안전장치

기본 실행 모드는 페이퍼 트레이딩입니다. `PAPER=true`와 `RUN_ONCE=true`로 한 번만 실행하는 방식으로 테스트할 수 있고, 실거래는 `PAPER=false`, `LIVE_CONFIRM=true`, API Key/Secret이 모두 설정된 경우에만 동작하게 해 실수로 실제 주문이 나가지 않도록 했습니다.

PAPER=false
LIVE_CONFIRM=true
BITHUMB_API_KEY=your-api-key
BITHUMB_API_SECRET=your-api-secret

상태는 `state.json`에 저장합니다. 오늘 사용한 KRW 금액, 오늘 이미 매수한 심볼, 마지막 매수 시각을 기록해 중복 매수와 예산 초과를 막고, 쿨다운 체크까지 가능하도록 했습니다.

테스트와 주의 사항

테스트는 `requirements-dev.txt`와 `pytest` 기준으로 구성했고, 실거래 전에는 반드시 `PAPER=true` 상태로 충분히 검증해야 한다는 점을 전제로 했습니다. 또한 빗썸 최소 주문 금액, API 권한, 수수료 정책을 먼저 확인해야 하며, API Key와 Secret은 절대 Git에 커밋하지 않도록 구조를 분리했습니다.

현재 코드는 매도 로직, 리밸런싱, 변동성 기반 포지션 사이징, 백테스트, 손실 제한 로직까지 포함한 완성형 트레이딩 시스템이 아니라, 실거래 안전장치와 상태 관리까지 포함한 매수 자동화 구조를 보여주는 프로젝트입니다.

저장소

https://github.com/xowlsakffl/auth-bithumb-buyer

게임허브

JWT 인증, 파티 권한 정책, 실시간 채팅과 음성 상태, React 프론트 통합 배포 구조까지 포함한 Spring Boot + React 멀티 모듈 웹 서비스

프로젝트 소개

GameHub는 디스코드형 게임 파티 운영을 위한 멀티 모듈 기반 웹 서비스입니다. 사용자 인증, 친구 기능, 파티 모집/참가, 실시간 채팅, 음성채널 상태, 권한/초대/뮤트 관리, 프론트엔드 번들 통합까지 포함한 Spring Boot + React 모노레포로 구성했습니다.

이 프로젝트의 핵심은 단일 백엔드가 아니라 `domain / core / user-api / admin-api / front-end`로 역할을 나눈 상태에서 JWT 인증, WebSocket(STOMP) 실시간 이벤트, 파티 멤버 권한 정책, 초대코드 기반 진입 흐름, 프론트 빌드 산출물의 백엔드 통합까지 실제 서비스 구조로 연결했다는 점입니다.

핵심 서비스 흐름

  1. 사용자가 `/api/auth/signup`, `/api/auth/login`으로 가입하거나 로그인
  2. JWT 기반 인증 상태로 친구, 파티, 채팅, 음성채널 API 호출
  3. 사용자는 파티를 생성하거나 초대코드/참가 요청을 통해 파티 입장
  4. 멤버 권한(`LEADER`, `MANAGER`, `MEMBER`)에 따라 수정, 승인, 강퇴, 위임, 뮤트 적용
  5. 채팅은 REST 조회와 STOMP 실시간 송수신을 함께 사용하고 읽음 상태를 별도로 관리
  6. 음성채널 이벤트는 파티 토픽과 사용자 전용 큐로 브로드캐스트
  7. 프론트엔드는 Vite로 빌드되고, 결과물은 `onion-user-api` 정적 리소스로 복사되어 함께 서빙

주요 기능

  • 회원가입, 로그인, 이메일/닉네임 중복 확인과 JWT 발급
  • 친구 요청, 수락, 거절, 친구 목록 관리
  • 파티 생성/수정/삭제/상태 변경과 목록/상세 조회
  • 자동참가/승인참가 방식의 파티 참여 흐름
  • 파티 멤버 강퇴, 방장 위임, 운영진 권한 관리, 뮤트/해제
  • 채팅 메시지 조회, 읽음 상태 관리, STOMP 기반 실시간 채팅 송수신
  • 음성채널 입장/퇴장/이동 상태 브로드캐스트
  • 사용자 전용 큐(`/user/queue/notifications`) 실시간 푸시 알림
  • 초대코드 조회/재발급/코드 입장 흐름

기술 스택

Java 21 Spring Boot 3.5.6 Spring Security Spring Data JPA WebSocket STOMP SockJS JWT ModelMapper MySQL H2 Gradle Multi Module React 19 React Router 7 Vite Tailwind CSS Axios

주요 화면

GameHub 회원가입 화면
회원가입 화면
GameHub 로그인 화면
로그인 화면
GameHub 메인 파티 허브 화면
메인 파티 허브 화면

프로젝트 구조

onion/
├── onion-domain/                  # Entity, Enum, Repository
├── onion-core/                    # DTO, Service, Security, Exception
├── onion-user-api/                # 사용자 REST API, WebSocket, 정적 리소스 서빙
├── onion-admin-api/               # 관리자 API 확장 모듈
├── front-end/                     # React + Vite 프론트엔드
├── postman/                       # Postman 컬렉션
├── build.gradle                   # 루트 Gradle 설정
└── settings.gradle                # 멀티 모듈 구성

모듈별 역할

`onion-domain`은 엔티티와 Enum, Repository를 담당하고, `onion-core`는 서비스 로직, DTO, JWT 보안 구성, 공통 예외 처리, ModelMapper 기반 매핑을 담당합니다. `onion-user-api`는 인증/친구/파티/채팅/음성 API와 WebSocket 설정, 프론트 정적 리소스 서빙까지 맡고, `onion-admin-api`는 운영 기능을 확장하기 위한 관리자 API 모듈입니다. `front-end`는 React 라우팅과 파티 카드, 친구 패널 UI, Axios 기반 API 호출을 담당합니다.

구현 포인트

이 프로젝트에서 중요했던 부분은 REST API만 구현하는 데서 끝나지 않고, JWT 기반 인증과 실시간 이벤트를 서비스 흐름에 자연스럽게 연결하는 것이었습니다. 파티 멤버 권한을 `LEADER`, `MANAGER`, `MEMBER`로 나누고, 수정/승인/강퇴/위임/뮤트 정책을 세분화해 운영 기준이 코드 구조에 직접 드러나게 정리했습니다.

WebSocket 쪽도 단순 채팅 푸시가 아니라, 실시간 채팅과 읽음 상태 저장/조회 API, 음성채널 접속 상태, 파티 브로드캐스트, 사용자 푸시 알림까지 연결했습니다. 특히 WebSocket JWT 인증 인터셉터와 인바운드 채널 보안을 추가해 실시간 계층도 REST와 같은 인증 기준으로 관리되도록 보완했습니다.

배포 구조 역시 포인트였습니다. `onion-user-api`가 Gradle `node` 플러그인을 통해 `front-end`의 `npm run build`를 수행하고, 결과물을 `src/main/resources/static`으로 복사하도록 구성해 프론트 별도 개발 서버와 백엔드 통합 배포 두 방식을 모두 지원하도록 정리했습니다.

보완한 부분

  • 프론트 산출물 복사 경로를 `build`에서 `dist`로 정정
  • 사용자 API 정적 리소스 산출물 추적 정책 정리
  • 파티 상태 변경 시 잘못된 status 입력 `500` 오류를 `400` 처리로 보완
  • 파티/친구/파티 쓰기 API 인증 정책 강화
  • 파티 생성/참가 요청 입력값 검증 추가
  • 참가 요청 중복 검사 로직을 존재 쿼리 기반으로 최적화
  • WebSocket JWT 인증 인터셉터 및 인바운드 채널 보안 추가
  • 실시간 채팅 + 읽음 상태 저장/조회 API 추가
  • 음성채널 접속 상태 + 파티 브로드캐스트 + 사용자 푸시 알림 추가
  • 권한 체계 확장(`LEADER` / `MANAGER` / `MEMBER`) 및 강퇴 정책 세분화
  • 파티 뮤트/해제 기능 및 뮤트 시 채팅/음성 차단 적용
  • 파티 초대코드 조회/재발급/입장 흐름 추가

운영과 실행 관점

현재 핵심 실행 모듈은 `onion-user-api`입니다. `onion-admin-api`는 관리자 API 확장 지점 성격이 강하고, 테스트 태스크는 각 모듈에서 `enabled = false`로 비활성화되어 있습니다. JPA 설정은 `ddl-auto: update`, `show-sql: true` 기준이며, 프론트엔드 `dist` 산출물은 이미 `onion-user-api/src/main/resources/static` 아래에도 반영되는 구조입니다.

이 프로젝트는 멀티 모듈 백엔드와 React 프론트가 결합된 게임 파티 허브형 웹 서비스 모노레포입니다.

저장소

https://github.com/xowlsakffl/gameHub-multi-module-

SNS Service

Spring Boot 백엔드와 React 프론트엔드를 함께 구성하고, Instagram 피드 패턴을 참고한 단일 컬럼 SNS UI까지 정리한 풀스택 프로젝트

프로젝트 소개

`SNS Service`는 게시글 기반 소셜 피드, 댓글, 좋아요, 알림, 신고 처리까지 포함한 풀스택 SNS 프로젝트입니다. 백엔드는 Spring Boot로 인증/도메인/API를 담당하고, 프론트엔드는 React로 피드 경험을 제공하도록 구성했습니다.

프론트 UI는 Instagram 웹/모바일 피드 구조를 참고한 클론형 인터페이스로 정리했습니다. 브랜드를 그대로 재사용한 것이 아니라, 피드 카드, 스토리, 하단 탭, 단일 컬럼 소비 흐름 같은 UI 패턴을 참고해 구현했고, 현재는 PC에서도 모바일과 같은 단일 컬럼 레이아웃으로 동작합니다.

인증, 실시간 이벤트, 콘텐츠 관리, 프론트 UI 흐름까지 한 번에 포함한 통합 레포지토리입니다.

핵심 서비스 흐름

  1. 사용자가 회원가입 또는 로그인 후 JWT를 발급받아 인증 상태를 유지
  2. 단일 컬럼 피드 UI에서 게시글 목록을 무한 스크롤로 소비하고, 상세/댓글/알림 화면까지 같은 흐름으로 이동
  3. 인증 사용자는 게시글 작성/수정/삭제, 댓글 작성, 좋아요 같은 쓰기 API를 호출
  4. 좋아요와 댓글 이벤트가 발생하면 SSE 구독 사용자에게 알림을 전송
  5. 사용자는 부적절한 게시글을 신고할 수 있고, 신고 누적 임계치에 따라 자동 블라인드 처리
  6. 관리자는 신고 목록을 검색하고 승인/반려 및 집계 API로 운영 현황을 확인

주요 기능

사용자 기능
  • JWT 기반 회원가입 및 로그인
  • 게시글 작성/수정/삭제/목록 조회/내 글 조회
  • 댓글 작성 및 조회
  • 좋아요 처리 및 좋아요 수 조회
  • SSE(Server-Sent Events) 기반 실시간 알림 구독
  • 무한 스크롤 기반 피드/알림/댓글 로딩
운영/관리 기능
  • 게시글 신고 등록
  • 신고 누적 임계치 기반 자동 블라인드
  • 관리자 신고 승인/반려
  • 관리자 신고 검색(`status`, `reasonType`, `postId`, `reporterUsername`)
  • 관리자 신고 대시보드 집계 API
프론트 UI 특징
  • Instagram 피드 패턴을 참고한 카드형 피드
  • 스토리 바와 하단 탭 네비게이션 구조
  • PC/모바일 동일 단일 컬럼 레이아웃
  • 페이지네이션 제거 후 무한 스크롤 적용

기술 스택

Java 17 Spring Boot 2.7 Spring Security JWT Spring Data JPA MariaDB Redis SSE React 17 CRA Gradle

프로젝트 구조

sns_service/
├── src/main/java/dev/be/snsservice/
│   ├── configuration/           # Security, Redis, JWT, Local seed
│   ├── controller/              # User/Post/Report API
│   │   ├── request/             # 요청 DTO
│   │   └── response/            # 응답 DTO
│   ├── exception/               # 예외/에러코드/전역 핸들러
│   ├── model/                   # 도메인 모델, enum
│   │   └── entity/              # JPA Entity
│   ├── repository/              # JPA/캐시/SSE Repository
│   ├── service/                 # 비즈니스 로직
│   └── util/                    # JWT/유틸
├── src/main/resources/
│   └── application.yml
├── front-end/                   # React 프론트엔드
│   ├── src/layouts/             # 피드/인증/알림/게시글 화면
│   ├── src/hooks/               # 무한 스크롤 훅
│   ├── src/utils/               # 프로필/이미지 메타, 병합 유틸
│   └── screenshots/mobile/      # README용 모바일 화면 캡처
├── database/                    # DB 도커 설정
├── redis/                       # Redis 도커 설정
└── docker-compose-local.yml

구현 포인트

이 프로젝트에서 중요한 부분은 백엔드 기능 구현만이 아니라, 그 기능이 실제 피드 UI 경험과 자연스럽게 연결되도록 만드는 것이었습니다. 피드 카드, 스토리, 하단 탭, 게시글 상세, 댓글, 알림 화면을 같은 톤으로 묶고, PC에서도 모바일과 같은 단일 컬럼 레이아웃으로 고정해 소비 흐름을 일관되게 만들었습니다.

백엔드 쪽은 JWT 인증을 전제로 쓰기 API를 보호하고, 좋아요와 댓글 이벤트를 SSE 알림으로 연결했습니다. 또한 게시글 수정/삭제 권한 체크를 엔티티 참조 비교가 아니라 ID 비교로 정리하고, JWT/SSE 구독 처리 안정성과 요청 검증 및 전역 예외 응답 구조를 보강했습니다.

신고 기능도 단순 등록에서 끝내지 않고, 누적 임계치 기반 자동 블라인드와 관리자 승인/반려, 검색과 집계 API까지 넣어 운영형 서비스 관점으로 확장했습니다. 즉 사용자 경험은 익숙한 피드 UI 패턴으로, 운영 기능은 실제 관리 흐름으로 연결한 점이 이 프로젝트의 핵심입니다.

보완한 부분

백엔드
  • 로컬 프로필에서 Redis 미연결 시 인메모리 캐시 fallback 적용
  • 로컬 데모 데이터 자동 시드 추가
  • MariaDB 호환성을 위해 JSON 컬럼을 `TEXT` 기반으로 보정
  • JWT/SSE 구독 처리 안정성 보강
  • 요청 검증과 전역 예외 응답 구조 정리
프론트엔드
  • 사용자명 매핑 오류 수정
  • PC/모바일 동일 단일 컬럼 레이아웃으로 재정리
  • Instagram 피드 패턴 기반 UI 개선
  • 페이지네이션 제거 후 무한 스크롤 적용
  • 로그인/회원가입 비동기 처리 경고 정리

실행과 데모 환경

실행 방법
.\gradlew.bat build
.\gradlew.bat bootRun

cd front-end
npm install
npm run start

docker compose -f docker-compose-local.yml up -d
로컬 실행 포인트

로컬 `local` 프로필에서는 데모 데이터가 자동으로 들어가도록 구성했습니다. 일반 사용자 `demo / password123!`, 관리자 사용자 `admin / admin1234!` 계정으로 바로 로그인할 수 있고, 사용자 6명, 게시글 12개, 댓글 8개, 좋아요 20개, 알림 6개, 신고 3개가 자동 생성됩니다.

이 덕분에 백엔드 API뿐 아니라 프론트 피드, 댓글, 알림, 신고 화면까지 별도 수동 입력 없이 바로 확인하고 캡처할 수 있도록 정리했습니다.

화면 예시

모든 이미지는 모바일 기준 캡처입니다. 로그인, 회원가입, 피드, 게시글 작성, 내 게시물, 게시글 상세, 알림 화면 순서로 정리했습니다.

SNS 서비스 로그인 화면
로그인
SNS 서비스 회원가입 화면
회원가입
SNS 서비스 피드 화면
피드
SNS 서비스 게시글 작성 화면
게시글 작성
SNS 서비스 내 게시물 화면
내 게시물
SNS 서비스 게시글 상세 화면
게시글 상세
SNS 서비스 알림 화면
알림

저장소

https://github.com/xowlsakffl/sns_service.git

주차장 찾기

주소 검색, 거리 계산, 추천 순위, 단축 URL, 길안내와 로드뷰 이동까지 하나의 검색 경험으로 연결한 Spring Boot 기반 주차장 추천 웹 솔루션

프로젝트 소개

주차장 추천은 사용자가 입력한 주소를 기준으로 주변 주차장을 탐색하고, 거리 기준 추천 결과를 지도와 카드 UI로 보여주는 Spring Boot 기반 웹 솔루션입니다.

핵심은 단순 목록 조회가 아니라, 주소 검색 API(Kakao Local), 거리 계산, 추천 순위, 단축 URL, 길안내와 로드뷰 이동을 하나의 검색 경험으로 연결한 점입니다. 검색 화면에서 반경과 추천 개수를 조절하고, 결과 화면에서는 지도와 추천 카드를 함께 보며 위치와 이동 동선을 바로 비교할 수 있도록 구성했습니다.

프로젝트 포인트

  • 주소 검색부터 추천 결과 확인까지 이어지는 웹 솔루션 흐름 구현
  • 지도 중심 결과 화면과 추천 카드 UI 구성
  • 반경/추천 개수 조절, 정렬 옵션, 추천 이유 배지 제공
  • Base62 기반 단축 URL(`/dir/{encodedId}`) 생성
  • 길안내 / 로드뷰 / 링크 복사 액션 제공
  • 잘못된 단축 URL 접근 시 메인 화면으로 안전하게 복귀

현재 구현 기능

검색 화면
  • 주소 검색 API 연동
  • 검색 반경(`1~20km`) 설정
  • 추천 개수(`1~10개`) 설정
  • 빠른 선택용 반경/개수 프리셋 제공
결과 화면
  • 지도 + 추천 카드 2단 구조
  • 카드 클릭 시 지도 마커와 경로선 동기화
  • `거리 가까운 순 / 거리 먼 순 / 이름순` 정렬
  • `추천 n위`, `가장 가까운 추천`, `도보 3분권` 등 추천 이유 표시
  • 길안내, 로드뷰, 링크 복사 버튼 제공
추천/링크 처리
  • 주소를 좌표로 변환한 뒤 반경 내 주차장 검색
  • 거리순 정렬 후 제한 개수만 추천
  • 추천 결과 저장 및 단축 URL 생성
  • 단축 URL 접근 시 실제 길안내 링크로 리다이렉트

기술 스택

Java 17 Spring Boot 2.6.7 Spring Data JPA Handlebars Kakao Local API MariaDB H2 Docker Docker Compose Spock MockWebServer

프로젝트 구조

src/
├── main/
│   ├── java/dev/be/parkingmap/
│   │   ├── api/                 # Kakao API 연동 서비스/DTO
│   │   ├── direction/           # 단축 URL, 방향/링크 처리
│   │   ├── parking/             # 주차장 조회/추천 서비스
│   │   └── config/              # Retry, RestTemplate 설정
│   └── resources/
│       ├── static/              # 공통 CSS, JS
│       ├── templates/           # main.hbs, output.hbs
│       └── application.yaml
└── test/
    ├── groovy/
    └── java/

database/
├── init/
└── config/

실행 방법

빠른 UI 확인용 실행(H2)

MariaDB 없이 화면과 흐름을 빠르게 확인할 때 사용하는 실행 방식입니다.

$env:SPRING_PROFILES_ACTIVE="local"
$env:SPRING_DATASOURCE_DRIVER_CLASS_NAME="org.h2.Driver"
$env:SPRING_DATASOURCE_URL="jdbc:h2:mem:parking-preview;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
$env:SPRING_DATASOURCE_USERNAME="sa"
$env:SPRING_DATASOURCE_PASSWORD=""
$env:SPRING_JPA_HIBERNATE_DDL_AUTO="create-drop"
$env:KAKAO_REST_API_KEY="your_kakao_rest_api_key"
$env:PARKING_RECOMMENDATION_BASE_URL="http://localhost:8080/dir/"
.\gradlew.bat bootRun
로컬 인프라 포함 실행(MariaDB)
docker compose -f docker-compose-local.yml up -d

$env:SPRING_DATASOURCE_USERNAME="root"
$env:SPRING_DATASOURCE_PASSWORD="your_password"
$env:KAKAO_REST_API_KEY="your_kakao_rest_api_key"
.\gradlew.bat bootRun

기본 타깃은 Java 17이며, 로컬에 JDK 17이 없어도 Gradle toolchain 기준으로 빌드와 테스트가 가능하도록 정리했습니다.

주요 환경변수

변수 설명
SPRING_PROFILES_ACTIVE 실행 프로필 (`local`, `prod`)
SPRING_DATASOURCE_DRIVER_CLASS_NAME DB 드라이버 클래스
SPRING_DATASOURCE_URL DB 연결 URL
SPRING_DATASOURCE_USERNAME DB 계정
SPRING_DATASOURCE_PASSWORD DB 비밀번호
KAKAO_REST_API_KEY Kakao Local API REST 키
PARKING_RECOMMENDATION_BASE_URL 단축 URL 생성 기준 URL

개선한 내용

  • 입력 DTO에 주소 trim / 옵션 sanitize 추가
  • 공백 주소 요청 차단 및 서비스 경계 방어 강화
  • 단축 URL 예외 처리 보강
  • 결과 화면을 테이블 중심에서 지도 + 카드 UI로 개편
  • 정렬 옵션과 추천 이유 배지 추가
  • H2 인메모리 DB 기반 프리뷰/테스트 환경 정리
  • JDK 21 환경에서도 빌드 가능하도록 toolchain / Lombok 정리

프로젝트 의미

이 프로젝트는 CRUD보다는 검색 경험 설계에 더 가깝습니다. 주소 입력, 거리 계산, 추천 순위, 지도 표현, 링크 이동까지 이어지는 흐름을 웹 UI로 완성했다는 점이 핵심입니다.

특히 결과 화면을 `지도 + 추천 카드 + 정렬 옵션 + 추천 이유` 구조로 정리하면서, 실제 서비스 화면에 가깝게 구성했습니다.

화면 예시

주차장 추천 검색 화면
검색 화면
주차장 추천 결과 화면
결과 화면

기어허브

React + Vite 프론트엔드와 Spring Boot API 서버를 분리 구성하고, 전자제품 전문 쇼핑몰 사용자 화면과 관리자 콘솔까지 연결한 이커머스 프로젝트

프로젝트 소개

기어허브는 컴퓨팅, 오디오, 게이밍, 모바일 액세서리를 중심으로 한 전자제품 전문 이커머스 서비스입니다. 프론트엔드는 React + Vite 기반으로 사용자 쇼핑몰 화면과 관리자 운영 콘솔을 구성했고, 백엔드는 Spring Boot 기반으로 인증, 상품, 장바구니, 배송지, 주문/결제, 관리자 API를 제공합니다.

핵심은 프론트에서 `shop / admin / components / store / api`, 백엔드에서 `controller / service / repository / model / payload / security`로 역할을 분리하고, JWT 인증 상태를 기준으로 사용자 쇼핑 흐름과 관리자 운영 흐름을 명확히 나눈 점입니다. 사용자단과 관리자단을 모두 갖춘 구조로 구성했습니다.

이 저장소들이 맡는 역할

프론트엔드
  • 쇼핑몰 홈, 상품 목록/상세, 장바구니, 체크아웃, 마이페이지
  • 관리자 대시보드, 상품 관리, 카테고리 관리, 주문 관리
  • Redux 기반 인증, 장바구니, 상품, 결제 수단 상태 관리
  • Axios 인스턴스와 JWT Authorization 헤더 자동 주입
  • Tailwind CSS, MUI, React Icons 기반 반응형 UI
백엔드
  • 인증 API: 회원가입, 로그인, 로그아웃, 사용자 정보 조회
  • 공개 조회 API: 상품 목록, 상품 상세, 카테고리 목록
  • 사용자 API: 장바구니, 배송지, 주문, 결제 준비
  • 관리자 API: 상품 관리, 카테고리 관리, 전체 주문 관리
  • 보안 계층: JWT 발급/검증, 권한별 접근 제어, CORS 설정

핵심 서비스 흐름

  1. 사용자는 홈 또는 스토어 화면에서 전자제품을 탐색하고 상세 페이지로 이동합니다.
  2. 장바구니에서 상품 수량과 결제 예정 금액을 확인한 뒤 체크아웃으로 이동합니다.
  3. 배송지를 선택하고 결제 수단을 고른 다음 주문 요약을 확인합니다.
  4. 데모 결제에서는 실제 결제 승인 없이 서버 장바구니를 동기화한 뒤 주문을 생성합니다.
  5. 주문 완료 후 마이페이지의 주문 내역에서 주문 상태와 상품 구성을 확인합니다.
  6. 백엔드는 `/api/auth/signin` 이후 JWT를 발급하고, 이후 요청은 `Authorization: Bearer` 헤더 기준으로 처리합니다.
  7. 관리자 계정은 `/admin`과 `/api/admin/**` 경로에서 상품, 카테고리, 주문 상태를 운영합니다.

주요 기능

사용자 쇼핑몰
  • 전자제품 전용 쇼핑몰 홈 화면
  • 상품 목록, 필터, 정렬, 상세 조회
  • 장바구니 담기, 수량 변경, 삭제
  • 회원가입 및 로그인
  • 배송지 등록/선택과 주문 진행
  • 데모 결제 기반 주문 생성
  • 사용자 마이페이지 및 주문 내역 조회
관리자 콘솔
  • 관리자 전용 대시보드
  • 상품/카테고리 등록, 수정, 삭제
  • 전체 주문 조회와 주문 상태 변경
  • 관리자 전용 라우트 및 API 보호
  • 사용자 화면과 관리자 화면의 라우트 모듈 분리

기술 스택

Frontend
React 19.1 Vite 6.3.5 React Router 7.6.2 Redux Toolkit 2.8.2 Axios 1.10 Tailwind CSS 3.4.17 MUI 7.1.2 React Hook Form 7.59 Swiper 11.2.8 Stripe React SDK
Backend / API
Java 21 Spring Boot 3.4.4 Spring Security Spring Data JPA JJWT 0.12.5 ModelMapper 3.0 Stripe Java 29.3 H2 MySQL Maven JWT Daum Postcode

프로젝트 구조

프론트엔드
src/
├── api/                         # Axios 인스턴스, JWT 헤더 주입
├── assets/                      # 정적 에셋
├── components/
│   ├── account/                 # 마이페이지, 주문 내역
│   ├── auth/                    # 로그인, 회원가입
│   ├── cart/                    # 장바구니
│   ├── checkout/                # 배송지, 결제 수단, 주문 요약
│   ├── home/                    # 홈 화면, 배너
│   ├── products/                # 상품 목록, 필터, 상세
│   └── shared/                  # 공통 UI
├── hooks/                       # 상품 필터 훅
├── modules/
│   ├── admin/                   # 관리자 라우트와 화면
│   └── shop/                    # 사용자 쇼핑몰 라우트
├── store/                       # Redux store, reducer, action
└── utils/                       # 가격 포맷, 텍스트 유틸
백엔드
src/main/java/com/ecommerce/project/
├── config/                      # 공통 설정, 데모 데이터, 정적 이미지 핸들러
├── controller/                  # REST API 컨트롤러
├── exceptions/                  # 공통 예외와 전역 예외 처리
├── model/                       # JPA Entity, Role Enum
├── payload/                     # DTO, API 응답 객체
├── repository/                  # Spring Data JPA Repository
├── security/                    # SecurityFilterChain, JWT 필터, 요청/응답 DTO
├── service/                     # 비즈니스 로직
└── util/                        # 인증 사용자 조회 유틸

src/main/resources/
└── application.properties       # 서버, DB, JWT, CORS, Stripe 설정

구현 포인트

프론트엔드

사용자 화면과 관리자 화면을 `src/modules/shop`, `src/modules/admin`으로 분리해 라우트 경계가 코드 구조에 그대로 드러나도록 정리했습니다. 홈, 상품, 상세, 장바구니, 체크아웃, 계정 페이지를 사용자 흐름에 맞춰 묶고, 관리자 영역은 별도 레이아웃과 전용 페이지 세트로 분리했습니다.

상태 관리는 Redux 기준으로 인증 사용자 정보, 장바구니 상품과 합계, 상품 목록, 카테고리, 결제 수단, 로딩 및 오류 상태를 나눠 관리했습니다. API 쪽은 `localStorage.auth.jwtToken`을 Authorization 헤더로 자동 주입하고, `withCredentials`도 함께 사용해 인증 흐름을 정리했습니다.

백엔드

백엔드는 JWT 인증과 Spring Security 권한 정책을 기준으로 공개 조회, 사용자 API, 관리자 API를 나눴습니다. 공개 회원가입은 `ROLE_USER`만 부여하고, `/api/admin/**` 경로는 `ROLE_ADMIN`으로 제한해 사용자 흐름과 운영 흐름이 섞이지 않도록 구성했습니다.

주문 생성 시 서버 장바구니 기준으로 주문 상품을 만들고 상품 재고를 차감하며, 관리자 영역에서는 전체 주문 조회와 상태 변경을 처리합니다. 즉 프론트의 사용자 경험과 백엔드의 비즈니스 로직이 한쪽으로 치우치지 않게 연결한 구조가 핵심입니다.

실행 준비

프론트엔드
npm install
npm run dev

npm run build
npm run preview
백엔드
.\mvnw.cmd spring-boot:run

.\mvnw.cmd -DskipTests package

java -jar target/sb-ecom-0.0.1-SNAPSHOT.jar

주요 환경 변수

영역 변수 설명
Frontend VITE_BACK_END_URL Spring Boot API 서버 주소
Frontend VITE_FRONTEND_URL 프론트엔드 실행 주소
Backend SERVER_PORT 서버 실행 포트
Backend SPRING_DATASOURCE_URL JDBC URL
Backend JWT_SECRET JWT 서명 키
Backend FRONTEND_URL CORS 허용 프론트 주소 목록
Backend IMAGE_BASE_URL 상품 이미지 기본 URL
Backend STRIPE_SECRET_KEY Stripe secret key

데모 계정과 데이터

프론트와 백엔드 모두 `demo / password123!`, `admin / admin1234!` 계정을 기준으로 정리했습니다. 백엔드의 `DemoDataInitializer`는 서버 시작 시 사용자 계정, 관리자 계정, 전자제품 카테고리, 데모 상품, 배송지, 장바구니를 보강해 로컬에서 바로 사용자 흐름과 관리자 흐름을 확인할 수 있게 구성했습니다.

보완한 부분

프론트엔드
  • 전자제품 전문 쇼핑몰 콘셉트로 UI와 문구 정리
  • 상품 카드 클릭 시 상세 페이지 이동
  • 장바구니 버튼을 아이콘 중심으로 정리
  • 상품 상세 페이지 및 관련 상품 영역 추가
  • 로그인/회원가입 화면 단일 카드형 레이아웃 정리
  • 관리자 전용 라우트와 운영 콘솔 추가
  • 주문 완료 직전 서버 장바구니 동기화 처리
  • 장바구니 동기화 반복 요청 제거
백엔드
  • 전자제품 전문 이커머스 콘셉트에 맞는 데모 데이터 구성
  • 상품 상세 API 추가
  • 상품 DTO에 브랜드, 요약 사양, 배송 정보, 카테고리 ID 확장
  • 관리자 상품/카테고리 등록/수정/삭제 API 정리
  • 관리자 전체 주문 조회 및 주문 상태 변경 API 추가
  • `/api/admin/**` 경로 `ROLE_ADMIN` 권한 제한
  • 공개 회원가입의 임의 관리자 권한 부여 차단
  • CORS preflight가 Spring Security 체인을 통과하도록 보완

화면 구성

사용자 화면
GearHub 메인 화면
메인 화면
GearHub 스토어 화면
스토어
GearHub 장바구니 화면
장바구니
GearHub 주문 완료 화면
주문 완료
GearHub 마이페이지 화면
마이페이지
GearHub 주문 내역 화면
주문 내역
관리자 화면
GearHub 관리자 대시보드
관리자 대시보드
GearHub 관리자 상품 관리
상품 관리
GearHub 관리자 카테고리 관리
카테고리 관리
GearHub 관리자 주문 관리
주문 관리

관련 저장소

https://github.com/xowlsakffl/Gearhub_react

https://github.com/xowlsakffl/Gearhub_springboot

04 지원동기

MOTIVATION

기획, 개발, 테스트, 배포, 운영 흐름을 표현한 아이콘

보다 체계적인 개발 프로세스와 명확한 기준 속에서 서비스의 전 과정을 깊이 있게 수행하고자 지원하게 되었습니다.

그동안 다양한 프로젝트를 경험하며 요구사항 정의부터 설계, 개발, 운영까지 전반적인 흐름을 직접 수행했습니다. 특히 레거시 시스템 분석을 기반으로 요구사항을 재정의하고, 데이터 구조와 API를 설계하며 서비스를 개선하는 과정에서 전체 흐름을 이해하는 것이 개발의 완성도를 좌우한다는 것을 체감했습니다.

다만 이러한 경험을 쌓는 과정에서 프로젝트마다 기준과 프로세스가 다르거나 명확히 정립되어 있지 않은 환경에서는 동일한 문제를 반복하거나 비효율이 발생하는 한계도 함께 느꼈습니다. 이로 인해 단순히 기능을 구현하는 것을 넘어 체계적인 프로세스와 일관된 기준 속에서 개발을 수행하는 것이 얼마나 중요한지에 대해 고민하게 되었습니다.

명확한 개발 프로세스와 협업 체계를 기반으로 서비스를 운영하고 있으며, 이러한 환경 속에서 요구사항 정의부터 설계, 개발, 운영까지의 전 과정을 보다 정교하게 수행하고 개선해 나갈 수 있다고 판단했습니다. 특히 단기적인 기능 구현이 아닌 구조와 흐름을 기반으로 서비스를 발전시키는 방향성과 제가 지향하는 개발 방식이 부합한다고 생각합니다.

입사 후에는 기존에 쌓아온 구조 분석 및 설계 경험을 바탕으로 서비스의 전체 흐름을 이해하고, 비용을 개선하며 안정성과 확장성을 고려한 구조를 만들어 가는 데 기여하고자 합니다. 또한 체계적인 프로세스 안에서 개발을 수행하며, 단순 구현을 넘어 실제 서비스에 지속적으로 가치를 더할 수 있는 개발자로 성장하고 싶습니다.

귀한 시간 내어 읽어주셔서 감사합니다.

구조를 이해하고 개선하는 개발자로서,
실질적인 가치를 만드는 데 기여하고 싶습니다.

안민성 캐릭터 프로필

CONTACT

[email protected]

010.5543.4341

github.com/xowlsakffl