황준혁 포트폴리오 — Frontend · Product Engineer

HWANG JUNHYEOK · PORTFOLIO 2026

PORTFOLIO

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

CONTACT

justn.hyeok@gmail.com

WEB

justn.me

GITHUB

justn-hyeok

LINKEDIN

justn-hyeok

황준혁 사진

안녕하세요

황준혁입니다.

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가 반환한 코드와 실행 결과를 다시 확인합니다.

2/15

목차

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

01

제품 구현의 기반

Maru의 입력 · 제출, 자갈치의 저장 · 복원, justn.me의 첫 화면 성능

02

오픈소스 기여

React Flow · Gajae Code의 문제 재현과 공개 반영

3/15

구현의 기반

01 Maru

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

02 자갈치

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

03 justn.me

모바일 첫 화면 성능과 레이아웃 흔들림

4/15
Maru 로고

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

Maru

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

Maru 원서 작성 화면

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

기간

2025.04 – 2026.03

GitHub

저장소 보기

기여

01 사진 값 덮어쓰기 race 수정

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

기술

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

5/15

Maru · 입학전형 지원서

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

상황

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

원인

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

해결

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

결과

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

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

다음 단계 검증 기준

2개 상태

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

이미지 미리보기

READY

AND

업로드 URL

READY

두 값이 모두 준비되면

다음 단계 진입 조건 충족

구현 조건

image && (downloadUrl || uploadUrl)

6/15

Maru · 전형별 입력

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

상황

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

원인

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

해결

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

결과

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

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

직접 해 보기 →

BEFORE · 화면만 변경

학교 정보는 숨겨졌지만

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

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

AFTER · 제출값도 변경

지원 유형을 다시 확인하고

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

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

결과

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

7/15
자갈치 로고

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

자갈치

노드와 선으로 학습 경로를 만들고 공유하는 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

8/15

자갈치 · 노드 편집기

실행 취소가 노드와 선을 서로 다른 시점으로 돌렸습니다

상황

노드와 선을 함께 바꾸고, 실행 취소도 그래프 전체를 한 시점으로 복원해야 했습니다.

원인

노드와 선의 기록을 따로 관리해, 한 번의 실행 취소에서 서로 다른 시점이 선택됐습니다.

해결

독립적으로 바뀌는 상태는 나누고, 실행 취소에서 함께 돌아가야 하는 노드와 선은 하나의 편집 이력으로 묶었습니다.

결과

실행 취소·다시 실행 시 노드와 연결선이 같은 편집 시점으로 복원됩니다. 무작위 편집 1,000회 기준 깨짐 59.9% → 0%.

근거 · PR #120 · 통합 편집 이력 ↗

이전 구조

노드

선

t-1

t-2

서로 다른 시점

통합 후

실행 취소

EditorState

{ nodes, edges } snapshot

결과

한 번의 실행 취소가 하나의 그래프를 복원합니다.

9/15

자갈치 · 로드맵 저장

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

상황

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

원인

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

해결

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

결과

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

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

직접 해 보기 →

BEFORE · 목록 전체 검사

하나라도 검사에 걸리면

목록 전체를 버렸습니다.

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

AFTER · 로드맵마다 검사

깨진 항목만 건너뛰고

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

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

결과

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

10/15

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초.

justn.me ↗

모바일 첫 화면 · 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)

11/15

오픈소스 기여

01 React Flow · Gajae Code

보고된 문제를 재현·분석해 PR로 연결했습니다.

12/15

주요 작업 · 오픈소스 · React Flow

연결선 양 끝에서 둥근 모서리가 사라지는 문제를 재현했습니다

중복 좌표 때문에 두 점 사이 거리와 모서리를 둥글게 만드는 값이 0이 되는 조건을 찾았습니다.

React Flow 연결선 수정 전후 비교

PR #5730 제안

근거 · PR #5730 · @xyflow/system 0.0.76 ↗

PR #5730

문제 재현

꺾임 위치 0·1에서 각진 모서리를 재현했습니다.

계산 원인 분석

중복 좌표 → 두 점 사이 거리 0 → 곡률 값 0

메인테이너 병합

원인을 찾아 PR을 제출했고, 병합됐습니다(@xyflow/system 0.0.76).

13/15

주요 작업 · 오픈소스 · Gajae Code

에이전트의 완료 이벤트와 모델 연결 경로를 원 프로젝트에 구현했습니다

오픈소스 코딩 에이전트 Gajae Code에 완료 알림 연결과, 모델 제공자 Command Code의 GOAT 요금제 인증·요청 경로를 각각 PR로 제출했습니다.

Gajae Code PR #1272

PR #1272

작업 완료 알림

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

Gajae Code PR #5050

PR #5050

Command Code GOAT Plan 인증

API key 로그인과 해당 모델 제공자로 요청을 보내는 경로를 구현했습니다.

두 변경 모두 원 저장소에 병합됐습니다.

근거 · PR #1272 · PR #5050 ↗

14/15

황준혁

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

justn.hyeok@gmail.com

PDF 다운로드