HWANG JUNHYEOK · PORTFOLIO 2026
PORTFOLIO
사용자가 겪는 문제를 실제 제품에서 작동하는 기능으로 풀고, AI 실행과 검증 조건을 설계합니다.
CONTACT
justn.hyeok@gmail.comjustn.hyeok@gmail.com
WEB
justn.mejustn.me
GITHUB
justn-hyeokjustn-hyeok
justn-hyeokjustn-hyeok

안녕하세요
황준혁입니다.
HWANG JUNHYEOK · JUSTN
AI Native Problem Solver
학력
2024.03 - 2027.01
부산소프트웨어마이스터고 소프트웨어개발과 졸업 예정
자격
2025.07 정보처리산업기사
2026.03 SQL 개발자 (SQLD)
2026.04 리눅스마스터 2급
다루는 영역
AI-native 제품 개발
사용자 문제를 화면·API·AI 기능으로 구현하고 실패와 검증 조건까지 제품에 연결합니다. 개발 과정에서도 agent가 반환한 코드와 실행 결과를 다시 확인합니다.
기반 역량 · Frontend
TypeScript·React·Next.js로 사용자 흐름을 구현합니다. 입력과 제출, 편집 상태와 복원이 일치하도록 조건을 정합니다.
목차
입력과 복구에서 AI 실행·검증까지 확장합니다.
01
제품 구현의 기반
Maru의 입력 · 제출과 자갈치의 저장 · 복원
02
AI 기능의 실행과 결과 검증
brgr의 워커 결과 승인과 적용
03
개인 제품
라피 · Watchdog · justn.me의 확인된 취소 · 안전한 개입 · 즉시 반영
04
협업과 의사결정
자갈치의 리뷰 기준 정리
05
조직 운영
제품 팀과 공개 프로젝트 조직의 서로 다른 책임
06
오픈소스 기여
React Flow · Gajae Code의 문제 재현과 공개 반영
부산소프트웨어마이스터고 입학 전형 서비스
Maru
입학전형 지원서에서 늦게 온 임시저장 응답이 사진 값을 덮어쓰던 race와 검정고시 원서 제출 400을 수정했습니다. 화면에 보이는 값과 전송 데이터가 어긋나는 두 문제입니다.

#입학 전형 서비스 #Frontend · DX
기간
2025.04 – 2026.03
GitHub
저장소 보기저장소 보기
기여
01 사진 값 덮어쓰기 race 수정
02 검정고시 원서 제출 400 해결
기술
Next.js · React · TypeScript · Recoil · TanStack Query
Maru · 입학전형 지원서
사진을 올렸는데 다음 단계가 열리지 않았습니다
상황
증명사진을 올려 화면에 보이는데도 '다음' 단계 검증이 실패할 수 있었습니다.
원인
사진 값이 반영된 뒤 늦게 도착한 임시저장 응답이 사진 값을 빈 값으로 덮어썼습니다.
해결
다음 단계 버튼을 누른 시점의 이미지와 업로드 주소를 함께 읽어 진입 조건을 판단하도록 바꿨습니다.
결과
늦은 응답 순서에서 '다음' 막힘 100% → 0%.
근거 · PR #268 · 사진 값 덮어쓰기 race ↗근거 · PR #268 · 사진 값 덮어쓰기 race ↗
다음 단계 검증 기준
2개 상태
보이는 이미지와 업로드 주소를 같은 시점에 확인합니다.
이미지 미리보기
READY
AND
업로드 URL
READY
두 값이 모두 준비되면
다음 단계 진입 조건 충족
구현 조건
image && (downloadUrl || uploadUrl)
Maru · 전형별 입력
검정고시 지원자의 원서 제출이 400으로 거절됐습니다
상황
검정고시를 선택하면 학교 입력 항목이 사라지는데, 제출하면 서버가 거절했습니다.
원인
숨긴 학교 칸이 빈 값이나 이전에 입력한 값 그대로 전송됐고 빈 schoolCode는 서버의 7자 검사에 걸렸습니다.
해결
제출 직전에 graduationType을 확인하고 학교 관련 7개 필드를 null로 만들었습니다.
결과
검정고시 지원서도 정상 제출되고 숨긴 학교 7개 필드는 값 대신 null로 전송됩니다.
근거 · PR #287 · 학교 정보 7개 제거 ↗근거 · PR #287 · 학교 정보 7개 제거 ↗
직접 해 보기 →직접 해 보기 →
BEFORE · 화면만 변경
학교 정보는 숨겨졌지만
제출값에는 빈 값이 남았습니다.
서버는 빈 schoolCode를 400으로 거절했습니다.
AFTER · 제출값도 변경
지원 유형을 다시 확인하고
학교 관련 7개 값을 비웠습니다.
검정고시 전형에서는 학교 관련 값을 비웁니다.
결과
보이는 조건과 보내는 조건을 하나의 기준으로 맞췄습니다.

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

#FE Lead · PM
기간
2025.12 – 2026.05
GitHub
저장소 보기저장소 보기
기여
01 변경 빈도와 역할에 따른 상태 분리
02 노드·선의 통합 실행 취소와 복원
03 실행 취소 깨짐 59.9% → 0%
04 손상 항목만 제외하는 부분 복구
05 복사한 노드의 ID와 연결 관계 갱신
기술
Next.js · React · TypeScript · Jotai · React Flow
자갈치 · 노드 편집기
실행 취소가 노드와 선을 서로 다른 시점으로 돌렸습니다
상황
노드와 선을 함께 바꾸고 실행 취소도 그래프 전체를 한 시점으로 복원해야 했습니다.
원인
노드와 선의 기록을 따로 관리해, 한 번의 실행 취소에서 서로 다른 시점이 선택됐습니다.
해결
독립적으로 바뀌는 상태는 나누고 실행 취소에서 함께 돌아가야 하는 노드와 선은 하나의 편집 이력으로 묶었습니다.
결과
실행 취소·다시 실행 시 노드와 연결선이 같은 편집 시점으로 복원됩니다. 무작위 편집 1,000회 기준 깨짐 59.9% → 0%.
근거 · PR #120 · 통합 편집 이력 ↗근거 · PR #120 · 통합 편집 이력 ↗
이전 구조
노드
선
t-1
t-2
서로 다른 시점
통합 후
실행 취소
EditorState
{ nodes, edges } snapshot
결과
한 번의 실행 취소가 하나의 그래프를 복원합니다.
자갈치 · 로드맵 저장
자동 저장 한 번에 다른 로드맵이 지워졌습니다
상황
텍스트 상자나 섹션이 든 로드맵이 하나라도 있으면, 자동 저장할 때 저장돼 있던 다른 로드맵이 사라졌습니다.
원인
저장할 때마다 목록 전체를 한 번에 검사했고 이름 칸이 없는 게 정상인 텍스트 상자·섹션이 규칙 위반으로 걸렸습니다. 검사에 실패하면 목록을 빈 것으로 보고 덮어썼습니다.
해결
로드맵을 하나씩 검사해 깨진 것만 건너뛰고 텍스트 상자·섹션은 label 없이도 통과하게 규칙을 바로잡았습니다.
결과
저장할 때 다른 로드맵이 사라지는 비율 100% → 0% (무작위 저장 1,000회).
근거 · PR #172 · 항목별 검증 ↗근거 · PR #172 · 항목별 검증 ↗
직접 해 보기 →직접 해 보기 →
BEFORE · 목록 전체 검사
하나라도 검사에 걸리면
목록 전체를 버렸습니다.
지금 로드맵 하나만 남기고 덮어썼습니다.
AFTER · 로드맵마다 검사
깨진 항목만 건너뛰고
나머지는 그대로 남깁니다.
텍스트 상자·섹션은 이름 없이도 통과합니다.
결과
다른 로드맵 손실 100% → 0% (1,000회)
brgr
코딩 에이전트 오케스트레이터
brgr
Codex나 Claude Code가 다른 코딩 에이전트에게 일을 넘기고, 각 워커가 옆 Herdr 패인에서 프롬프트를 누가 눌러 주지 않아도 끝까지 돌게 합니다.

#코딩 에이전트 오케스트레이터 #공개 저장소
기간
2026.09 – 지금
GitHub
저장소 보기저장소 보기
기여
01 워커마다 Herdr 패인 하나
02 신뢰·계속 프롬프트 자동 응답
03 모르는 화면은 3분 뒤 실패
04 결과 봉인 후 승인해야 적용
05 실패는 확인할 때까지 알림
06 owner·워커 간 질문과 답장
기술
Rust · SQLite · git worktree · Herdr
brgr · 결과 승인과 적용
승인한 변경인데 새 파일이 빠진 채 적용됐습니다
상황
brgr는 워커 결과를 봉인해 두고 owner가 승인해야만 저장소에 적용합니다. 그런데 승인한 결과를 적용했더니 워커가 새로 만든 파일이 오류 없이 빠져 있었습니다.
원인
결과를 git diff로 봉인했는데, git diff는 git이 이미 추적하는 파일만 담습니다. 워커가 새로 만든 파일은 아직 추적 전이라 통째로 빠졌습니다.
해결
봉인할 때 index를 임시로 복사해 새 파일을 담을 대상으로 표시한 뒤 diff를 만듭니다. 워커의 실제 index는 건드리지 않습니다.
결과
새 파일 10개를 만든 결과에서 봉인에 담긴 새 파일 0/10 → 10/10. 워커 index 변경 0개, 관련 테스트 2개 통과 (2026-10-08 재현).
근거 · brgr · git_diff.rs ↗근거 · brgr · git_diff.rs ↗
BEFORE · git diff로 봉인
승인한 결과를 적용해도
새 파일은 빠져 있었습니다.
추적 전 파일은 diff에 안 들어갑니다.
AFTER · 임시 index에 새 파일 표시
새 파일까지 diff에 담고
승인한 그대로 적용합니다.
워커의 실제 index는 그대로.
봉인에 담긴 새 파일 (10개 중)
0개 → 10개
라피
개인 에이전트
라피
여기저기 흩어진 소식을 모아 Discord와 이메일(SMTP)로 브리핑하고 제가 승인한 일만 대신 하는 개인 에이전트입니다.

#개인 에이전트 #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
라피 · 운영과 복구
혼자 운영하는 서비스라 되돌리는 길부터 만들었습니다
상황
라피는 VM 한 대에서 수집·발송·실행 서비스 8개가 함께 돕니다. 혼자 운영하다 보니 배포가 잘못되거나 서버가 멈춰도 바로 붙어 있지 못할 때가 많습니다.
원인
배포와 복구를 손으로 하면 장애를 늦게 알거나, 되돌리는 도중에 데이터를 잃을 수 있었습니다. 재시작 중 잠깐의 오류를 복구로 착각해 알림을 끄는 것도 위험했습니다.
해결
CI를 통과한 커밋은 5분 안에 자동 배포하고, 전환이 실패하면 직전 릴리스로 되돌립니다. 외부 감시는 재시작 중에는 장애 상태를 유지하고, 실제 응답이 돌아와야 복구로 알립니다.
결과
운영 DB 덤프를 별도 PostgreSQL에 복원해 테이블 31개·migration 12개·제약 105개 일치 (2026-09-28). 장애 알림 1번, 재시작 중 잘못된 복구 알림 0번, 복구 확인 뒤 알림 1번.
근거 · 라피 운영 기록 2026-09-28 ↗근거 · 라피 운영 기록 2026-09-28 ↗
배포와 복구
31 · 12 · 105
복원 점검: 테이블 · migration · 제약
배포
CI 통과 후 5분 안에 자동
전환 실패
직전 릴리스로 롤백
외부 감시
복구 확인 후에만 알림
운영 데이터
덮어쓰지 않고 별도 DB에 복원
라피 · 개인 에이전트 · v0.1.0 배포
취소했다고 답한 뒤에도 에이전트가 계속 돌고 있었습니다
상황
디스코드에서 /취소를 보내면 라피는 "작업을 취소했습니다"라고 답했지만, 그사이 Codex가 제 저장소를 계속 고칠 수 있었습니다.
원인
취소는 DB 상태만 바꿨고 실행기에는 Codex를 멈출 방법이 없었습니다. 시간 초과 때도 직접 띄운 프로세스에만 SIGTERM을 보내서, 신호를 무시하거나 그 아래에서 뜬 프로세스는 살아남았습니다.
해결
Codex를 프로세스 그룹으로 띄우고 그룹 전체에 SIGTERM, 1초 뒤 SIGKILL을 보냅니다. 종료를 확인한 뒤에만 취소로 기록하고, 확인이 안 되면 "미확정"이라고 답합니다.
결과
취소 후 살아남은 실행 20회 중 20회 → 0회 (2026-10-07 재현). 운영에서도 실제 Codex 프로세스의 PID가 사라지고 DB와 일치했습니다.
근거 · 라피 v0.1.0 · process.ts ↗근거 · 라피 v0.1.0 · process.ts ↗
직접 해 보기 →직접 해 보기 →
BEFORE · DB만 취소
"작업을 취소했습니다"라고 답해도
Codex 프로세스는 남아 있었습니다.
신호를 무시하는 자식·손자 2개가 그대로.
AFTER · 종료 확인 후 기록
프로세스 그룹에 SIGTERM → SIGKILL
끝난 걸 확인해야 취소로 기록합니다.
확인이 안 되면 "미확정"으로 답합니다.
취소 후 살아남은 실행 (20회)
20회 → 0회
Watchdog · macOS 메뉴바 앱 · 2026.08–2026.09 · v0.2.1 공개
멈추려던 PID가 다른 프로세스일 수 있었습니다
상황
폭주하거나 고아가 된 프로세스를 찾아 메뉴바에서 멈추게 합니다. 감지한 순간과 멈추기를 누르는 순간 사이에 원래 프로세스가 끝날 수 있습니다.
원인
끝난 프로세스의 PID는 다른 프로세스에 다시 배정될 수 있고 macOS에는 신원 확인과 신호 보내기를 한 번에 하는 방법이 없습니다.
해결
신호를 보내기 직전에 PID·UID·시작 시각을 다시 읽어 감지 당시와 같을 때만 보냅니다. 멈춤은 되돌릴 수 있는 일시정지부터 씁니다.
결과
신호 직전 재확인에서 신원이 바뀌었으면 processChanged로 중단합니다.
근거 · Watchdog v0.2.1 · ProcessController ↗근거 · Watchdog v0.2.1 · ProcessController ↗
직접 해 보기 →직접 해 보기 →
BEFORE · PID만 기억
감지한 PID로 바로 보내면
다른 프로세스가 멈출 수 있습니다.
그사이 PID가 재사용될 수 있었습니다.
AFTER · 직전 재확인
PID·UID·시작 시각을 다시 읽고
같을 때만 일시정지합니다.
바뀌었으면 processChanged로 멈춥니다.
결과
신원이 바뀐 PID는 processChanged로 중단합니다.
justn.me · 이력서·포트폴리오 편집기
고치는 즉시 보이는 문서를 CDN 캐시에 올렸습니다
상황
PDF 모양 그대로 웹에서 고치는 이력서·포트폴리오입니다. 공개 화면이 요청마다 GitHub에서 문서를 읽어 서버 첫 응답에 640ms가 걸렸습니다.
원인
같은 문서를 편집기에서 수시로 고치고 자소서는 로그인해야 보여서, 화면을 그대로 캐시하면 저장한 내용이 늦게 보이거나 비공개 문서가 캐시에 남을 수 있었습니다.
해결
공개 문서만 미리 그려 CDN에 두고 저장하면 그 주소만 다시 그리게 했습니다. 자소서·회사별 문서는 매번 로그인을 확인하는 주소로 넘기고, git으로 직접 고친 내용은 5분 안에 다시 그립니다.
결과
서버 첫 응답 640ms → 17ms (2026-10-06, Lighthouse 모바일). 프로덕션 빌드에서 저장 직후 반영, 로그인 전 자소서 404를 확인했습니다.
justn.me ↗justn.me ↗
문서마다 다르게 그리기
640ms → 17ms
공개 화면 서버 첫 응답
공개 문서
CDN에 미리 그려 둠
편집기 저장
그 주소만 바로 다시 그림
자소서·회사별
매번 로그인 확인
git으로 직접 고친 내용
5분 안에 다시 그립니다
자갈치 · 6인 팀 FE Lead · 코드 리뷰
팀원 PR을 바로 머지하지 않고 기준부터 먼저 고쳤습니다
상황
2026-01-12 팀원이 올린 커뮤니티 화면 PR(#41)에 테스트가 없었고, 기존 코드의 꼬인 테스트 구조를 그대로 따르고 있었습니다.
원인
기존 코드베이스의 테스트 구조와 이름·export 규칙이 정리돼 있지 않아, 새 코드가 따를 기준이 없었습니다.
해결
PR에는 수정을 요청하고, 같은 날 직접 이슈(#44)를 열어 기존 코드의 구조와 컨벤션부터 통일했습니다(#45, 파일 52개).
결과
정리된 기준에 맞춰 고친 PR을 다음 날 승인했습니다. 확립한 규칙은 팀 문서(CLAUDE.md)에 남겼습니다.
근거 · PR #41 리뷰 · #45 ↗근거 · PR #41 리뷰 · #45 ↗
2026-01-12 ~ 01-14
요청 → 정리 → 승인
팀원 PR을 막기 전에 따를 기준을 먼저 만들었습니다.
PR #41 (팀원)
변경 요청 → 승인
PR #45 (기준 정리)
파일 52개 · 머지
순서
기준을 먼저 고치고 머지
조직 체계 · BSSM-OSS 관리자
외부에서 찾고 기여할 수 있게 공개 기준을 정리했습니다
외부 사람이 프로젝트를 이해하고 실행·기여할 수 있도록 공개 기준을 정리했습니다.
대표 목록
대표 프로젝트를 첫 화면에서 바로 찾을 수 있게 정리했습니다.
README
조직 소개 README를 영/한으로 분리하고 분야별 카탈로그로 재구성했습니다.
기여 경로
조직 공통 Issue 양식 4종과 PR 양식을 만들었습니다.
유지 기준
운영 중인 저장소만 대표 목록에 올렸습니다.
조직 전체 공개 저장소 98개 · 2026.09.08
근거 · BSSM-OSS Organization ↗근거 · BSSM-OSS Organization ↗

주요 작업 · 오픈소스 · React Flow
연결선 양 끝에서 둥근 모서리가 사라지는 문제를 재현했습니다
중복 좌표 때문에 두 점 사이 거리와 모서리를 둥글게 만드는 값이 0이 되는 조건을 찾았습니다.

PR #5730 제안
근거 · PR #5730 · @xyflow/system 0.0.76 ↗근거 · PR #5730 · @xyflow/system 0.0.76 ↗
PR #5730
문제 재현
꺾임 위치 0·1에서 각진 모서리를 재현했습니다.
계산 원인 분석
중복 좌표 → 두 점 사이 거리 0 → 곡률 값 0
메인테이너 병합
원인을 찾아 PR을 제출했고 병합됐습니다(@xyflow/system 0.0.76).
주요 작업 · 오픈소스 · Gajae Code
에이전트의 완료 이벤트와 모델 연결 경로를 원 프로젝트에 구현했습니다
오픈소스 코딩 에이전트 Gajae Code에 완료 알림 연결과, 모델 제공자 Command Code의 GOAT 요금제 인증·요청 경로를 각각 PR로 제출했습니다.

PR #1272PR #1272
작업 완료 알림
작업이 끝나면 완료 정보를 외부 명령으로 전달하는 연결 기능을 추가했습니다.

PR #5050PR #5050
Command Code GOAT Plan 인증
API key 로그인과 해당 모델 제공자로 요청을 보내는 경로를 구현했습니다.
두 변경 모두 원 저장소에 병합됐습니다.
근거 · PR #1272PR #1272 · PR #5050PR #5050 ↗
황준혁
제품을 만들고 진행 상태를 정직하게 남깁니다
justn.hyeok@gmail.comjustn.hyeok@gmail.com