singsangssong.
KOContact me
Open to Opportunities

With the hands that once tended a ship's engine,I build services.

I worked as a marine engineer on container ships, running monitoring and safety systems for long, non-stop voyages. Now I'm a full-stack developer: I build screens with React, Next.js and TypeScript and servers with Express and Prisma, and I design the invisible parts, like authentication, caching and deployment, with my reasoning on record.

Scroll

About

Portrait of Hyeongyu Song

Hyeongyu Song송현규

I'm a full-stack developer who works on both the backend and the frontend.

I don't stop at making features work. I compare options such as where to store auth tokens, caching strategy and how to manage environment variables, and I decide with the reasons written down. On a ship, a small misjudgment can become a serious accident, and the habit of following procedure and keeping records there still shows up in my code.

Languages
JavaScriptTypeScript
Frontend
ReactNext.js (App Router)TanStack QueryTailwind CSSFramer Motion
Backend
Express.jsPrisma ORMZodPostgreSQLMongoDB
Infra / Security
AWS IAMAWS Systems Manager Parameter Store (SecureString / KMS)
Tools & Collaboration
GitSwaggerDBeaverFigmaCodeRabbitVercelRenderAWSSupabaseCloudflare
  1. Codeit Bootcamp, Full-stack CourseA curriculum that covers React/Next.js frontend and Express/Prisma backend together. Learned server-state management with TanStack Query and applied it in mission projects.
  2. Marine engineer on a container shipOperated engine monitoring and alarm systems on long, non-stop voyages, following safety procedures and judging equipment status in real time under a 24-hour watch system.
  3. Oil/chemical tanker trainingPracticed safety protocols aboard ships that carry hazardous cargo.
  4. Graduated from Busan Maritime High School

Selected Works

Moving landing pageMoving
2026.08.26 – 2026.10.16

Moving

TypeScriptNext.jsExpressPrismaPostgreSQLAWS
Study Forest landing pageStudy Forest
2026.05.18 – 2026.06.08

Study Forest

ReactNode.jsExpressPrismaPostgreSQLZod
Bias Photo landing pageBias Photo
2026.07.08 – 2026.07.31

Bias Photo

Next.jsReactNode.jsExpressPrismaPostgreSQL
Read the full project log ↗

Engineering Notes

I record why I chose something, not just what came out.

Moving · Security

Moving plaintext-shared environment variables to AWS Parameter Store

I pointed out that sharing API keys and DB credentials over Discord and Notion leaves a permanent record and gives no way to split permissions. I used String and SecureString (KMS) according to how risky each value is to expose, and chose a group IAM policy over per-person ones so it keeps working when team members change.

Moving · Debugging

Finding the cause of a hydration mismatch instead of hiding the warning

After ruling out suspects one by one, starting with the responsive hook, I confirmed that Math.sin and Math.cos return results that differ in the last decimal digits between Node and the browser. Instead of suppressHydrationWarning, I rounded both sides to six decimal places, and I recorded the cost of the larger image size too.

Moving · Payment

Not trusting client values in the payment approval API

The amount and order info in the Toss payment success URL can be edited in the address bar, so before approving I compared them with the amount the server calculates and the order number rule. A wrong request never reaches Toss. I blocked double payment with the updated-row count of an updateMany guarded by a status condition. I also hit an incident in the local convenience mode, where a fake paymentKey went through as paid when no key was set, and I recorded it as a pre-release risk.

Moving · Realtime

Building chat on SSE and sending only a signal

I widened the single SSE connection used for notifications to carry chat as well. The server sends only a signal that a new message exists, and the browser fetches the content again through the API. I chose this so the rule for assembling notification text does not split across two places, and so a lost signal is fixed by re-fetching. Signals are published only after the transaction commits, so rolled-back notifications never reach clients, and I wrote the single-server assumption down as a known limit.

Moving · Security

Putting bot verification before the rate limit

A per-account rate limit alone cannot stop requests that rotate through accounts, so I introduced Cloudflare Turnstile. I put the check before the rate limit because, placed after it, a bot could use up other people's attempt counts and lock out real users. The server fails closed when the verification call fails, and I noted the limit that it cannot stop the requests from arriving in the first place.

Moving · Auth

From a client hook guard to a server component guard

A route guard inside useEffect decides after the screen is painted, so a protected screen can flash, and a stale cache can send people to the wrong place. So the decision is made in a server layout with redirect(), and the real line of defense is the backend's requireAuth and requireRole. In effect, I decided up front how far the frontend guard is responsible.

Moving · Review

Not accepting AI review as-is

When CodeRabbit, which I had introduced, flagged that IP-based rate limiting had no authentication, I pushed back on the grounds that the route's only logged-out path was a showcase page that would be deleted before release, and then reviewed the alternatives it proposed.

Interests

How AI fits into a development workflow

Starting from adopting CodeRabbit for code review, I'm watching how productivity changes when agents like Claude Code are used across planning, documentation and development.

Technical choices under constraints

I value being able to explain why I made a choice under less-than-ideal conditions: free-tier hosting, short schedules, the security limits of collaboration tools.

Contact

Let's work together.

kuu0528888@gmail.com