QA, from strategy to tooling.
Across 14 years as a QA engineer and Head of QA, I've worked on how to judge release risk and how to build QA orgs - and I implement that same thinking in software. This portfolio runs QA approach → org building → tools I built → writing, showing how I design software QA.
By the numbers
- 14yr+in QAmobile · web · embedded
- 0→1QA teams builtKorea · US
- 93%E2E test coverageOpenedges · Playwright migration
- 20%↓issue lead timeRiiid · after the QA system
- 11.81%↓duplicate issuesOpenedges · OpenProject workflow redesign
- 2QA books published+ 3 QA Korea talks
- 5QA tools builtReleaseGate, QAlity, and more
- ISO 13485medical-device QMSAsleep · Quality Mgmt Representative (QMR)
Each figure was measured and recorded at the company at the time.
QA approach · principles
Release decisions run on data, not gut
I design release gates so GO/HOLD comes from a score and its reasoning, not the loudest voice. I've made that gate a team standard across several orgs, and turned the decision itself into a tool, ReleaseGate.
Test design is risk-based
I set test scope, where to invest automation, and release-blocking conditions from requirements risk. The core of QA strategy isn't automating everything - it's deciding where, and how much, to put it.
Automate regression, observe operations
Core user journeys get automated as E2E and run in a daily regression pipeline; after launch, Sentry·Datadog·Grafana monitoring and on-call carry quality into operations.
Testing is a loop that narrows a hypothesis
I treat testing as a reproducible experiment, not a pre-release ritual. What breaks and why belongs in feature design - and that QA instinct carries into product judgment.
QA process
Two principles - shift-left (pull testing into the design stage) and risk-based (risk sets the scope, depth, and priority of testing).
- 01Shift-left
Requirements & design review
QA joins at the planning and design outputs to catch ambiguity and risk early - pulling testing into the spec stage, not after code.
- 02Risk-based
Risk assessment & priority
Rate risk by impact and likelihood to set test scope, depth, and where to invest automation - concentrating on the high-risk areas rather than testing everything.
- 03
Test design & automation
Design cases starting from the highest-priority paths and automate core journeys as E2E; manage cases in Qase.
- 04
Run & regression pipeline
Run daily regression in CI automatically and read results in Allure; separate flaky from real regressions.
- 05
Release gate (GO/HOLD)
Judge the release from coverage, open defects, and residual risk - the score and its reasoning together.
- 06
Monitor & on-call → feedback
After launch, observe with Sentry·Datadog·Grafana and feed real incidents back as risk input for the next cycle.
Building QA orgs
RiiidSenior QA → Head of QA
2021.02 - 2022.05 · AI education- ·Localized the Korean QA system to run integrated with US R&D, aligning shared automation, monitoring, and on-call standards across both orgs
- ·Built the US QA team 0→1 - designed the Lever·HackerRank hiring pipeline and hired multiple QA engineers
- ·After establishing the QA system, cut issue lead time 20% (owned quality through the SoftBank funding round)
AsleepHead of QA
2022.06 - 2024.02 · Sleep data · digital therapeutics- ·B2C (app), B2B (hospitals), and B2H (digital therapeutics) carry different risk, so I set a distinct QA strategy per product line
- ·Built the QA team, ran company-wide quality education, and moved test cases from spreadsheets onto Qase
- ·Built the mobile and web regression-automation framework through the Sleep Routine Hybrid→Native migration
RegulatedRegulated QA: designed and ran the ISO 13485 quality management system and owned MFDS certification as Quality Management Representative (QMR) for the medical-device line.
Openedges SqaureWeb QA Engineer · solo owner
2024.07 - 2025.10 · Web Canvas2D- ·As the sole QA owner, designed and ran the end-to-end quality strategy from requirements to release
- ·Re-architected E2E automation from Selenium to Playwright, reaching 93% coverage
- ·Redesigned OpenProject workflows - duplicate issues down 11.81%
Day1CompanyQA Engineer · 0→1 owner
2025.11 - 2026.04 · Live education- ·Built the risk-based QA strategy 0→1 and standardized ticket handling, test flow, and release gates as the team's bar
- ·0→1 QA team building - role definition, collaboration process, accountability for quality
- ·Designed and built an E2E automation framework along core user journeys, running it as a daily regression pipeline
QA tools I built
Stack studied and applied while building QA tools
- TypeScript
- Zod
- JSON Schema
- OpenAPI 3.x
- vitest
- tsup
- npm
- FastAPI
- React
- PostgreSQL
- OpenAI API
- Python
- OpenAI Embeddings
- Playwright
- Jira REST API
- Vite
- GPT-4o-mini
- Tailwind
- Zustand
- React Query
- i18next
- SQLAlchemy
- Redis
- WebSocket
- pytest
- Locust
- Sentry
- Cloudflare Pages
- Cloudflare Tunnel
- Mac Mini
Adversary
LiveAn open-source library that turns one schema into explained adversarial test inputs - boundary values, i18n, and injection, each with a plain-language reason it might break.
QA problem
Most people writing input-validation code can't recall every boundary, Unicode, and injection case by hand. After you write `z.string().min(3)`, building a table of the hostile inputs that field will actually accept - a value one character short of 3, a family emoji that is 11 UTF-16 code units, a URL starting with `javascript:` - is a separate job, and usually it doesn't get done.
What I built
- ·Generate explained adversarial inputs from a schema - each value labelled with its technique (BVA / EP / i18n / injection), family, failureHypothesis, and validity
- ·Four-technique catalog - boundary-value analysis, equivalence partitioning, i18n/Unicode (normalization, grapheme vs code unit, bidi, homoglyph), and injection (SQL, XSS, SSTI, CSV formula, OS command, path traversal, CRLF, NUL)
- ·Type coverage - string, number/integer, boolean, enum/literal, array, date/date-time, union, each with generators aimed at that type's traps
QA verification lens
- ·Does it label correctly whether a generated value satisfies the field's own constraints (validity: valid / invalid / unknown) - i18n and injection are left "unknown" honestly, because whether they're accepted is exactly the behaviour under test
- ·Is the fact each failureHypothesis rests on actually true - 217 tests pin facts one by one ('ß'.toUpperCase() is 'SS', the family emoji is 11 code units, z.url() really accepts javascript:)
- ·Do values JSON can't represent (absent, NaN, Infinity, -0) silently vanish from output - encoded as literal strings / null so nothing is lost
Result · Outlook
The clearest outcome was proving "validation is not safety" as a tool. Feed z.url() a javascript:, a file://, or a cloud-metadata SSRF address and every one passes safeParse - showing, in front of you, that a validated value can still be dangerous carries the point that the code behind the field is the real line of defense, no explanation needed.
Studied & applied
- TypeScript
- Zod v4
- JSON Schema
- OpenAPI 3.x
- vitest
- tsup
- npm
The CLI turning one Zod schema into explained adversarial inputs - each value labelled with its technique and reason.
Turning an OpenAPI spec into a per-endpoint hostile-input report - no Zod schema, from the spec alone.
Applied to a real FastAPI project (frameboard) - its Pydantic model exported via model_json_schema() and fed straight to adversary.
ReleaseGate
MVPAn AI evaluation SaaS that turns release-or-hold decisions into data - just before launch.
QA problem
In release meetings, "can we ship this?" is decided by gut feel and whoever speaks loudest.
What I built
- ·Designed the Release Confidence Score (0-100) - weighted blend of coverage, open defects, and change-risk areas
- ·Report UI that shows the GO / HOLD recommendation alongside its reasoning
- ·AI-drafted test case starters so QA opens an editable draft rather than a blank screen
QA verification lens
- ·Score reproducibility - the same inputs (coverage, open defects, change-risk) yield the same confidence score (deterministic rubric)
- ·The GO/HOLD recommendation and the human final call stay clearly separated - so it isn't mistaken for an automated verdict
- ·Input boundaries - empty input and the 50,000-char overflow are safely rejected (TC-P0-001/002)
Result · Outlook
Confirmed how hard it is to fit "the weight of a release decision" onto one screen. Putting up a one-line score is easy, but for that score to land in a meeting, "how did this score come to be?" has to be visible on the same screen right next to it.
Studied & applied
- FastAPI
- React
- PostgreSQL
- OpenAI API
Python CLI that finds duplicate Jira issues by embedding their title and description and flagging pairs above a threshold - Excel reports plus usage and cost stats.
QA problem
In a QA backlog, the same issue gets filed multiple times under different wording. The cost of a human scanning for duplicates grows with backlog size and headcount, and usually it just gets left alone.
What I built
- ·Bulk-fetches issues via the Jira API (JQL, MAX_ISSUES default 50) and excludes keyword issues like [UI]
- ·Embeds title + description with OpenAI text-embedding-ada-002 and finds duplicate candidate pairs by cosine similarity
- ·Caches embeddings (issue_embeddings_cache.json) to cut the cost of re-runs
QA verification lens
- ·The similarity threshold's precision/recall - lowering it yields false positives (unrelated pairs), raising it misses real duplicates; where is the tradeoff set?
- ·False-positive cost - flagging a non-duplicate as a duplicate actually adds human review time, so that cost is acknowledged
- ·The embedding cache (
issue_embeddings_cache.json) doesn't misjudge on a stale vector when an issue's body changes
Result · Outlook
Originally a 2025 CLI that sat parked - an "underused gem." Bringing it back into the active set after recognizing that "duplicate issues" is one of the most common backlog problems I've seen across 14 years in QA; reviewing it as either an Atlassian Marketplace app or a consulting side tool.
Studied & applied
- Python
- OpenAI Embeddings
Triggers Playwright automation from Jira issues and writes results back as comments.
QA problem
The manual regression-testing loop - file an issue → run → write results → move state - lives in separate places, which kills consistency. Runs happen locally, results live in memory, state transitions happen later, and records leak in between.
What I built
- ·Treats a Jira (QAlity) issue as the scenario unit and runs pytest + Playwright
- ·Posts the result back to Jira as an ADF (Atlassian Document Format) comment
- ·Auto-transitions the Jira issue status by outcome
QA verification lens
- ·Jira round-trip integrity - issue → run → comment reply → status transition runs end-to-end with nothing dropped in between
- ·Re-run idempotency - re-running the same issue doesn't double up comments/status or leave them inconsistent
- ·A forced-failure case (QAP-2) confirms that failures, not just successes, are reported and transitioned accurately
Result · Outlook
Kept as a QA portfolio piece. The workflow integration itself - "trigger Playwright from a Jira issue, post the result back to Jira" - is where fourteen years of QA decisions land condensed, so its value as a kept piece comes before commercialization.
Studied & applied
- Python 3.11+
- Playwright
- Jira REST API
CaseMaker (Figma2Checklist)
ArchivedA full-stack tool where you paste a document URL (a public Notion page) and GPT-4o-mini drafts and groups a QA test checklist - an experiment testing "from design/docs to QA" (shift-left), wired up through auth and payments.
QA problem
There's no shared standard between design/planning outputs and QA. Without a spec, QA can hardly infer the test scope, and building checklists by hand every time breeds omissions and inconsistency.
What I built
- ·Document URL input → read a public Notion page with Playwright and extract text (BeautifulSoup) → GPT-4o-mini drafts and groups QA checklist items
- ·Save and reload generated checklists per account
- ·A React + FastAPI full stack with email/password auth, PostgreSQL, and Toss payment-integration code
QA verification lens
- ·How do you measure an auto-generated checklist's accuracy and omissions and prevent regressions - without that, plausible items still don't earn trust (the core problem this project didn't solve)
- ·GPT-4o-mini can emit different items and groupings for the same document across runs, so without a regression-prevention design the accuracy can't be pinned down in the first place - which is why it stopped
- ·Does the public-Notion-page parsing (Playwright + BeautifulSoup) fail robustly on structure changes, private pages, and empty pages?
Result · Outlook
Stood up as a full stack (auth, storage, payment integration) and then dormant. It never reached real usage or real payments, and there's no live URL. The real reason it stopped wasn't features - it was that without a design to regression-test an auto-generated checklist's accuracy and omissions, plausible items still don't earn trust - and that lesson is what the project leaves behind. The gap between the name (Figma2Checklist) and the actual build (Notion-based) is left honestly as is.
Studied & applied
- React 19
- Vite
- FastAPI
- PostgreSQL
- GPT-4o-mini
- Playwright
QA Learning 101
LiveA QA learning platform for picking up testing methodology and automation hands-on - you write tests against practice apps that look like the real thing.
QA problem
QA-engineering beginners don't have a map of "what to learn in what order." Books are heavy, and lectures are one-way - hands stay still.
What I built
- ·Full-stack learning app - FastAPI + PostgreSQL backend, React + TypeScript frontend (auth, posts, comments, todos, kanban, calendar, real-time chat, files)
- ·QA Hub - realistic practice apps (a banking dashboard, a booking system, e-commerce, a social feed) built as targets to write automated tests against
- ·Stable data-testid selectors across the UI, independent of CSS and component structure, so E2E doesn't break on refactors
QA verification lens
- ·data-testid selectors survive CSS and component-structure changes so E2E holds up on refactors (proving out the learning standard)
- ·The QA Hub practice apps (banking, booking, e-commerce, social feed) actually carry realistic states and edge cases to test against
- ·The accuracy of the learning content itself - a wrong methodology explanation or example teaches a beginner a bad habit that lasts five years, so it's the regression most worth avoiding
Result · Outlook
Kept as a learning tool. Commercialization is on hold - this tool grew out of fourteen years of "beginners have no map of what to learn in what order" as a QA engineer, so its value as study material comes before revenue.
Studied & applied
- React
- TypeScript
- Vite
- Tailwind
- Zustand
- React Query
- i18next
- FastAPI
- Python
- PostgreSQL
- SQLAlchemy
- Redis
- WebSocket
- Playwright
- pytest
- Locust
- Sentry
- Cloudflare Pages
- Cloudflare Tunnel
- Mac Mini
Writing & talks
Books
- Quality and Coding You Must Know2024.11.27Print · eBook
- The Little-Known World of the SQA Engineer2022.04.25eBook · out of print
Talks
- QA Korea Conference 4th - Live Q&A Speaker2025.07.05QA Korea Conference
- QA Korea OFF-QA - Lightning Talk Speaker2024.12.06QA Korea Conference
- QA Korea Conference 1st - Speaker2023.01.28QA Korea Conference
Core skills
- Test Automation
- Playwright · Selenium · Cypress · Appium · Detox · Espresso/XCUITest · Locust · Lighthouse
- Test Mgmt · Tracking
- Qase · Jira · OpenProject · Allure · Bugzilla
- CI/CD · Monitoring
- GitHub Actions · BrowserStack · Sentry · Datadog · Grafana · OpsGenie
- QA Leadership
- QA strategy · 0→1 team building (KR·US) · release gates · regression automation · on-call · quality education · ISO 13485/QMR
- AI-assisted QA
- Embedding-based duplicate detection · LLM scoring/analysis pipelines
- Stack
- TypeScript · Python · Java · SQL
Domains
- Platforms
- Mobile apps · Web · Embedded · Firmware
- Industries
- AI education · Digital therapeutics (medical, regulated) · Live education · Smart-pen hardware · Multilingual localization · Apparel-sizing B2B SaaS
- Segments
- B2C · B2B (hospitals) · B2H (digital therapeutics)
Looking for the next QA role to build with.
Open to QA lead/engineer roles - and to teams and people to build quality with.