황준혁 포트폴리오 — AX Engineer

HWANG JUNHYEOK · PORTFOLIO 2026

PORTFOLIO

AI 작업의 범위와 완료 조건을 먼저 정하고, 결과는 코드 버전과 reviewer 승인에 묶어 확인한 뒤 완료로 봅니다.

CONTACT

justn.hyeok@gmail.com

WEB

justn.me

GITHUB

justn-hyeok

LINKEDIN

justn-hyeok

황준혁 사진

안녕하세요

황준혁입니다.

HWANG JUNHYEOK · JUSTN

AX Engineer

학력

2024.03 - 2027.01

부산소프트웨어마이스터고 소프트웨어개발과 졸업 예정

자격

2025.07 정보처리산업기사

2026.03 SQL 개발자 (SQLD)

2026.04 리눅스마스터 2급

다루는 영역

AI-native 제품 개발

사용자 문제를 화면·API·AI 기능으로 구현하고, 실패와 검증 조건까지 제품에 연결합니다. 개발 과정에서도 agent가 반환한 코드와 실행 결과를 다시 확인합니다.

기반 역량 · Frontend

TypeScript·React·Next.js로 사용자 흐름을 구현합니다. 입력과 제출, 편집 상태와 복원이 일치하도록 조건을 정합니다.

2/21

목차

입력과 복구에서 AI 실행·검증까지 확장합니다.

01

AI 기능의 실행과 결과 검증

자갈치플랫폼의 실행 실패 처리와 코드 버전 재검증

02

개인 제품

라피 · stackot의 중복 방지와 재전송

03

조직 운영

제품 팀과 공개 프로젝트 조직의 서로 다른 책임

04

제품 구현의 기반

Maru의 입력 · 제출과 자갈치의 저장 · 복원

3/21

구조화·검증

01 자갈치플랫폼

AI 호출·작업 실행·제출 코드 상태를 검사와 사람 승인으로 확인합니다.

4/21

자갈치플랫폼

AI 학습 로드맵 서비스

자갈치플랫폼

개발자의 학습 목표·문서·질문을 받아 AI가 로드맵 생성, 문서 변환, 설명·추천·코칭을 해 주는 학습 서비스입니다. AI 기능마다 티켓 비용이 있어, 작업 전에 예약하고 실패하면 환불, 성공하면 확정합니다.

자갈치플랫폼 화면

#개인 주도 제품 #AI 실행 검증

기간

2026.08 – 진행 중

GitHub

저장소 보기

기여

01 Web·API·Infra 담당

02 AI 티켓 예약·환불·확정 경계 구현

03 closed alpha 직접 운영

기술

Next.js · NestJS · Django · PostgreSQL · GitHub App · Docker

5/21

자갈치플랫폼 · 결과 신뢰

제출한 코드가 바뀌면 이전 검증과 승인을 다시 받습니다

상황

검증과 별도 reviewer 승인이 끝난 PR에도 새 커밋이 push될 수 있습니다.

원인

승인이 코드 버전에 묶여 있지 않으면, 바뀐 코드가 이전 검증과 승인을 그대로 가져갑니다.

해결

완료 조건, GitHub 증거와 별도 reviewer 승인을 같은 PR head에 묶고, head가 바뀌면 이전 검증과 승인을 무효로 했습니다.

결과

2026-08-27 운영에서 PR head를 e5f8c58 → ce45ade로 바꾸자 webhook 직후 APPROVED → BOUND로 돌아갔고, 재검증·별도 reviewer 재승인 뒤에만 다시 APPROVED가 됐습니다(작성자 승인은 403).

jagalchi-platform #13 · closed alpha 증거 ↗

직접 해 보기 →

실제로 확인한 코드 버전 변화

A → B

새 커밋 뒤 상태 변화를 확인했습니다.

코드 버전 A

검증·승인 완료

↓

코드 버전 B

A의 검증·승인 무효

↓

같은 버전 B

재검증·재승인 완료

검증과 승인은 같은 코드 버전에만 유효합니다

버전 B 재검증·재승인 완료

6/21

자갈치플랫폼 · 운영과 복구

API 재기동 46초, 이전 버전 복귀 45초를 확인했습니다

closed alpha 운영 환경에서 재기동·rollback·DB 복원을 직접 실행했습니다. stop→start 46초 안에 readiness 200 · rollback 45초 / forward 35초 · DB 13개 테이블 행 수 일치.

jagalchi-infra · deploy/smoke.sh · self-hosted compose 점검

01 deadline=$((SECONDS + 300)) 02 while ((SECONDS < deadline)); do 03 health_endpoints_ready || continue 04 healthy=$(check_services api ai ai-db minio cloudflared) 05 ((healthy == 0)) && break 06 done 07 ((SECONDS >= deadline)) && exit 1 08 echo "production smoke check passed"

✓ compose로 띄운 서비스의 준비 상태 점검 스크립트

이 스크립트는 compose로 띄운 서비스의 준비 상태를 확인합니다. 재기동·rollback·DB 복원 시간은 closed alpha 운영 기록(#13)에서 측정했습니다.

jagalchi-platform #13 · closed alpha 증거 ↗

확인한 범위

재기동 46초 rollback 45초 forward 35초

7/21

개인 제품

01 라피

재시작해도, 겹쳐 돌아도 같은 기간의 브리핑은 한 번만

02 stackot

전달에 실패해도 잃지 않는 이벤트

8/21

라피

개인 에이전트

라피

여기저기 흩어진 소식을 모아 Discord와 이메일(SMTP)로 브리핑하고, 제가 승인한 일만 대신 하는 개인 에이전트입니다. 2026-09-28에 v0.1.2를 배포했습니다.

라피가 공개 블로그에 올린 데일리 브리핑

#개인 에이전트 #v0.1.2 배포

기간

2026.09 – 지금

GitHub

저장소 보기

기여

01 RSS · GitHub · 웹훅 수집

02 Discord · 이메일(SMTP) 브리핑

03 공개 분석만 올리는 블로그

04 USER · ADMIN · SUPERADMIN 권한

05 승인한 작업만 실행

06 취소하면 프로세스 종료

기술

TypeScript · Node.js · PostgreSQL · Zod · MDX · Discord

9/21

라피 · 개인 에이전트 · v0.1.2 배포

같은 기간의 브리핑이 두 번 나가지 않게 했습니다

상황

여기저기 흩어진 소식을 모아 Discord와 이메일(SMTP)로 브리핑하는 개인 에이전트를 직접 만들었습니다. 스케줄러가 재시작되거나 겹쳐 돌 수 있습니다.

원인

"이 기간은 이미 만들었다"를 가릴 기준이 없으면, 재시작이나 동시 실행 때마다 같은 기간의 브리핑 묶음이 새로 생깁니다.

해결

(구독, 기간 시작, 기간 끝)이 같으면 묶음을 하나만 인정하도록 데이터베이스가 막고, 이미 있으면 그 묶음을 다시 씁니다.

결과

동시 요청 4건에도 묶음은 1개만 생깁니다. 이 동작을 담아 2026-09-28에 v0.1.2를 배포했습니다.

근거 · rapi-agent · postgres-store.ts ↗

직접 해 보기 →

같은 기간 · 같은 구독

묶음 1개

몇 번을 돌려도 결과가 같습니다.

스케줄러 실행

묶음 생성 → 브리핑 발송

재시작 후 실행

있던 묶음을 다시 씀

동시에 4번

묶음 1개만 생성

ON CONFLICT DO NOTHING → 있던 묶음 사용

같은 기간의 브리핑은 한 번만

10/21

stackot · GitHub → Discord 봇

Gateway가 잠깐 죽어도 이벤트를 잃지 않게 했습니다

상황

GitHub 이벤트를 받아 Discord 스레드로 이어 주는 봇입니다. 이벤트를 넘겨받는 OpenClaw Gateway가 잠깐 502를 낼 수 있습니다.

원인

웹훅에는 이미 성공으로 응답했기 때문에 GitHub는 다시 보내 주지 않고, 받자마자 보내고 끝내면 실패한 전달을 되살릴 곳이 없습니다.

해결

응답하기 전에 받은 이벤트를 outbox에 pending으로 적고, 실패하면 간격을 늘려 최대 5번 다시 보내고, 모두 실패하면 dead_letter로 남깁니다. 전달되면 sent로 바꾸고, 재시작하면 남은 pending부터 보냅니다.

결과

Gateway 502 뒤 보존과 재시작 후 재전달을 확인했습니다. 백업은 VACUUM INTO 스냅샷으로 바꿔 integrity_check를 통과합니다.

근거 · stackot · outbox ↗

직접 해 보기 →

이벤트 한 건의 흐름

pending → sent

전달될 때까지 디스크에 남습니다.

웹훅 수신

응답 전에 outbox에 기록

↓

Gateway 502

간격을 늘려 다시 시도

↓

서버 재시작

남은 pending부터 재전송

SQLite WAL · synchronous=FULL

받은 이벤트는 사라지지 않습니다

11/21

조직 운영

01 stacking-money-forever

제품별 책임을 분리하고 자동화 개입 조건을 명시했습니다.

02 BSSM-OSS

프로젝트 선정·소개·문서·유지 기준

12/21

조직 운영 · stacking-money-forever

제품별 담당 범위와 공개 상태를 구분했습니다

자갈치플랫폼 Web·API·Infra와 벙개 프론트엔드·디자인을 맡았습니다.

제품별 책임 · 공개 범위

프로젝트

본인 기여

공개·개발 단계

자갈치플랫폼

Web·API·Infra

공개 저장소 · alpha

벙개

frontend · design

공개 저장소 · 2인 협업

Watchdog

프로세스 제어 전 대상 재확인

공개 v0.2.1

stackot

승인 기반 agent 작업

공개 저장소 · MVP

rapi-agent

승인 기반 Agent 설계

v0.1.2 배포

Watchdog v0.2.1 릴리스 ↗

앱 화면
13/21

조직 체계 · BSSM-OSS

외부에서 찾고 기여할 수 있게 공개 기준을 정리했습니다

외부 사람이 프로젝트를 이해하고 실행·기여할 수 있도록 공개 기준을 정리했습니다.

대표 목록

대표 프로젝트를 첫 화면에서 바로 찾을 수 있게 정리했습니다.

README

조직 소개 README를 영/한으로 분리하고 분야별 카탈로그로 재구성했습니다.

기여 경로

조직 공통 Issue 양식 5종과 PR 양식을 만들었습니다.

유지 기준

운영 중인 저장소만 대표 목록에 올렸습니다.

조직 전체 공개 저장소 98개 · 2026.09.08

근거 · BSSM-OSS Organization ↗

BSSM-OSS 대표 프로젝트 목록
14/21

구현의 기반

01 Maru

사용자가 보는 입력과 실제 제출값의 일치

02 자갈치

함께 바뀐 편집 상태를 같은 시점으로 복원

15/21
Maru 로고

부산소프트웨어마이스터고 입학 전형 서비스

Maru

입학전형 지원서에서 늦게 온 임시저장 응답이 사진 값을 덮어쓰던 race와 검정고시 원서 제출 400을 수정했습니다. 화면에 보이는 값과 전송 데이터가 어긋나는 두 문제입니다.

Maru 원서 작성 화면

#입학 전형 서비스 #Frontend · DX

기간

2025.04 – 2026.03

GitHub

저장소 보기

기여

01 사진 값 덮어쓰기 race 수정

02 검정고시 원서 제출 400 해결

기술

Next.js · React · TypeScript · Recoil · TanStack Query

16/21

Maru · 입학전형 지원서

사진을 올렸는데 다음 단계가 열리지 않았습니다

상황

증명사진을 올려 화면에 보이는데도 '다음' 단계 검증이 실패할 수 있었습니다.

원인

사진 값이 반영된 뒤 늦게 도착한 임시저장 응답이 사진 값을 빈 값으로 덮어썼습니다.

해결

다음 단계 버튼을 누른 시점의 이미지와 업로드 주소를 함께 읽어 진입 조건을 판단하도록 바꿨습니다.

결과

늦은 응답 순서에서 '다음' 막힘 100% → 0%, 무작위 순서 100회에서 21회 → 0회.

근거 · PR #268 · 사진 값 덮어쓰기 race ↗

다음 단계 검증 기준

2개 상태

보이는 이미지와 업로드 주소를 같은 시점에 확인합니다.

이미지 미리보기

READY

AND

업로드 URL

READY

두 값이 모두 준비되면

다음 단계 진입 조건 충족

구현 조건

image && (downloadUrl || uploadUrl)

17/21

Maru · 전형별 입력

검정고시 지원자의 원서 제출이 400으로 거절됐습니다

상황

검정고시를 선택하면 학교 입력 항목이 사라지는데, 제출하면 서버가 거절했습니다.

원인

숨긴 학교 칸이 빈 문자열로 전송돼 서버의 schoolCode 7자 검사에 걸렸습니다.

해결

제출 직전에 graduationType을 확인하고 학교 관련 7개 필드를 null로 만들었습니다.

결과

검정고시 지원서도 학교 정보 없이 정상 제출되고, 숨긴 학교 값 전송은 7개 → 0개가 됐습니다.

근거 · PR #287 · 학교 정보 7개 제거 ↗

직접 해 보기 →

BEFORE · 화면만 변경

학교 정보는 숨겨졌지만

제출값에는 빈 값이 남았습니다.

서버는 빈 schoolCode를 400으로 거절했습니다.

AFTER · 제출값도 변경

지원 유형을 다시 확인하고

학교 관련 7개 값을 비웠습니다.

검정고시 전형에서는 학교 관련 값을 비웁니다.

결과

보이는 조건과 보내는 조건을 하나의 기준으로 맞췄습니다.

18/21
자갈치 로고

개발자 학습 경로를 만드는 노드 편집기

자갈치

노드와 선으로 학습 경로를 만들고 공유하는 6인 팀 프로젝트입니다. 학습 경로 편집기의 상태·저장·복구 구현을 맡았습니다.

자갈치 로드맵 편집기 화면

#Team Lead · Frontend Lead · PM

기간

2025.12 – 2026.05

GitHub

저장소 보기

기여

01 변경 빈도와 역할에 따른 상태 분리

02 노드·선의 통합 실행 취소와 복원

03 실행 취소 깨짐 59.9% → 0%

04 손상 항목만 제외하는 부분 복구

05 복사한 노드의 ID와 연결 관계 갱신

기술

Next.js · React · TypeScript · Jotai · React Flow

19/21

자갈치 · 로드맵 저장

자동 저장 한 번에 다른 로드맵이 지워졌습니다

상황

텍스트 상자나 섹션이 든 로드맵이 하나라도 있으면, 자동 저장할 때 저장돼 있던 다른 로드맵이 사라졌습니다.

원인

저장할 때마다 목록 전체를 한 번에 검사했고, 이름 칸이 없는 게 정상인 텍스트 상자·섹션이 규칙 위반으로 걸렸습니다. 검사에 실패하면 목록을 빈 것으로 보고 덮어썼습니다.

해결

로드맵을 하나씩 검사해 깨진 것만 건너뛰고, 텍스트 상자·섹션은 label 없이도 통과하게 규칙을 바로잡았습니다.

결과

저장할 때 다른 로드맵이 사라지는 비율 100% → 0% (무작위 저장 1,000회).

근거 · PR #172 · 항목별 검증 ↗

직접 해 보기 →

BEFORE · 목록 전체 검사

하나라도 검사에 걸리면

목록 전체를 버렸습니다.

지금 로드맵 하나만 남기고 덮어썼습니다.

AFTER · 로드맵마다 검사

깨진 항목만 건너뛰고

나머지는 그대로 남깁니다.

텍스트 상자·섹션은 이름 없이도 통과합니다.

결과

다른 로드맵 손실 100% → 0% (1,000회)

20/21

황준혁

제품을 만들고 진행 상태를 정직하게 남깁니다

justn.hyeok@gmail.com

PDF 다운로드