HWANG JUNHYEOK · PORTFOLIO 2026
PORTFOLIO
사용자가 겪는 문제를 실제 제품에서 작동하는 화면으로 풀고, 입력과 제출, 편집과 복원이 맞아떨어지게 만듭니다.
CONTACT
WEB
GITHUB

안녕하세요
황준혁입니다.
HWANG JUNHYEOK · JUSTN
Frontend · Product Engineer
학력
2024.03 - 2027.01
부산소프트웨어마이스터고 소프트웨어개발과 졸업 예정
자격
2025.07 정보처리산업기사
2026.03 SQL 개발자 (SQLD)
2026.04 리눅스마스터 2급
다루는 영역
기반 역량 · Frontend
TypeScript·React·Next.js로 사용자 흐름을 구현합니다. 입력과 제출, 편집 상태와 복원이 일치하도록 조건을 정합니다.
AI-native 제품 개발
사용자 문제를 화면·API·AI 기능으로 구현하고, 실패와 검증 조건까지 제품에 연결합니다. 개발 과정에서도 agent가 반환한 코드와 실행 결과를 다시 확인합니다.
목차
입력과 복구에서 AI 실행·검증까지 확장합니다.
01
제품 구현의 기반
Maru의 입력 · 제출, 자갈치의 저장 · 복원, justn.me의 첫 화면 성능
02
오픈소스 기여
React Flow · Gajae Code의 문제 재현과 공개 반영
구현의 기반
01 Maru
사용자가 보는 입력과 실제 제출값의 일치
02 자갈치
함께 바뀐 편집 상태를 같은 시점으로 복원
03 justn.me
모바일 첫 화면 성능과 레이아웃 흔들림
부산소프트웨어마이스터고 입학 전형 서비스
Maru
입학전형 지원서에서 늦게 온 임시저장 응답이 사진 값을 덮어쓰던 race와 검정고시 원서 제출 400을 수정했습니다. 화면에 보이는 값과 전송 데이터가 어긋나는 두 문제입니다.

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

개발자 학습 경로를 만드는 노드 편집기
자갈치
노드와 선으로 학습 경로를 만들고 공유하는 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
자갈치 · 노드 편집기
실행 취소가 노드와 선을 서로 다른 시점으로 돌렸습니다
상황
노드와 선을 함께 바꾸고, 실행 취소도 그래프 전체를 한 시점으로 복원해야 했습니다.
원인
노드와 선의 기록을 따로 관리해, 한 번의 실행 취소에서 서로 다른 시점이 선택됐습니다.
해결
독립적으로 바뀌는 상태는 나누고, 실행 취소에서 함께 돌아가야 하는 노드와 선은 하나의 편집 이력으로 묶었습니다.
결과
실행 취소·다시 실행 시 노드와 연결선이 같은 편집 시점으로 복원됩니다. 무작위 편집 1,000회 기준 깨짐 59.9% → 0%.
이전 구조
노드
선
t-1
t-2
서로 다른 시점
통합 후
실행 취소
EditorState
{ nodes, edges } snapshot
결과
한 번의 실행 취소가 하나의 그래프를 복원합니다.
자갈치 · 로드맵 저장
자동 저장 한 번에 다른 로드맵이 지워졌습니다
상황
텍스트 상자나 섹션이 든 로드맵이 하나라도 있으면, 자동 저장할 때 저장돼 있던 다른 로드맵이 사라졌습니다.
원인
저장할 때마다 목록 전체를 한 번에 검사했고, 이름 칸이 없는 게 정상인 텍스트 상자·섹션이 규칙 위반으로 걸렸습니다. 검사에 실패하면 목록을 빈 것으로 보고 덮어썼습니다.
해결
로드맵을 하나씩 검사해 깨진 것만 건너뛰고, 텍스트 상자·섹션은 label 없이도 통과하게 규칙을 바로잡았습니다.
결과
저장할 때 다른 로드맵이 사라지는 비율 100% → 0% (무작위 저장 1,000회).
BEFORE · 목록 전체 검사
하나라도 검사에 걸리면
목록 전체를 버렸습니다.
지금 로드맵 하나만 남기고 덮어썼습니다.
AFTER · 로드맵마다 검사
깨진 항목만 건너뛰고
나머지는 그대로 남깁니다.
텍스트 상자·섹션은 이름 없이도 통과합니다.
결과
다른 로드맵 손실 100% → 0% (1,000회)
justn.me · 이력서·포트폴리오 편집기
모바일 첫 화면 성능을 50점에서 82점으로 올렸습니다
상황
1920×1080 슬라이드를 화면 폭에 맞춰 줄여 보여 주는 포트폴리오인데, 모바일 첫 화면 Lighthouse 성능이 50점이었습니다.
원인
축소 비율을 화면이 그려진 뒤 계산해 레이아웃이 한 번 밀렸고(CLS 0.77), 한글 폰트 295개 조각(2.5MB)과 원본 크기 이미지가 첫 화면을 늦췄습니다.
해결
축소 비율을 첫 화면 전에 계산하고, 자주 쓰는 한글 2,350자와 문서에 쓰인 글자만 남긴 폰트 4개를 직접 제공하고, 이미지를 화면 크기의 AVIF/WebP로 바꿨습니다.
결과
모바일 성능 50 → 82, CLS 0.77 → 0, LCP 15.0초 → 4.9초 (2026-10-06). PDF는 페이지를 열 때 미리 만들어 캐시해, 첫 생성 10초대 → 캐시 응답 0.17초.
모바일 첫 화면 · Lighthouse
50 → 82
레이아웃 흔들림(CLS) 0.77 → 0 주요 콘텐츠 표시(LCP) 15.0초 → 4.9초
한글 폰트 전송
2.5MB → 510KB
모바일 이미지
2.7MB → 0.1MB
첫 화면 전체 전송량
3.97MB → 0.80MB
축소 비율 · 첫 화면 전에 계산
min(1, (innerWidth − 80) / 1920)
오픈소스 기여
01 React Flow · Gajae Code
보고된 문제를 재현·분석해 PR로 연결했습니다.
주요 작업 · 오픈소스 · React Flow
연결선 양 끝에서 둥근 모서리가 사라지는 문제를 재현했습니다
중복 좌표 때문에 두 점 사이 거리와 모서리를 둥글게 만드는 값이 0이 되는 조건을 찾았습니다.

PR #5730 제안
근거 · 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로 제출했습니다.

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

Command Code GOAT Plan 인증
API key 로그인과 해당 모델 제공자로 요청을 보내는 경로를 구현했습니다.
두 변경 모두 원 저장소에 병합됐습니다.
황준혁