Published on

πŸ“ Form-ation

Chrome Store : πŸ”—
Github : πŸ”—

ν”„λ‘œμ νŠΈ μ†Œκ°œ

QA μž‘μ—…μ„ ν•˜μ‹œλŠ” λ™λ£ŒλΆ„λ“€μ˜ 반볡적인 폼 μž…λ ₯ λΆˆνŽΈν•¨μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ κ°œλ°œν•œ 크둬 ν™•μž₯ν”„λ‘œκ·Έλž¨μž…λ‹ˆλ‹€. μ…€λ ‰ν„° λͺ¨λ“œλ‘œ μ €μž₯ν•˜κ³  싢은 μž…λ ₯ ν•„λ“œλ₯Ό 직접 μ„ νƒν•˜κ³ , 같은 νŽ˜μ΄μ§€λ₯Ό μž¬λ°©λ¬Έν•˜λ©΄ μ €μž₯된 값을 μžλ™μœΌλ‘œ μž…λ ₯ν•΄μ£ΌλŠ” 것이 핡심 κΈ°λŠ₯μž…λ‹ˆλ‹€. 2025λ…„ 8μ›”λΆ€ν„° ν˜„μž¬κΉŒμ§€ μ§€μ†μ μœΌλ‘œ 개발 쀑이며 Chrome μ›ΉμŠ€ν† μ–΄μ— λ°°ν¬λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

핡심 κΈ°λŠ₯

μ…€λ ‰ν„° λͺ¨λ“œ

μ €μž₯ν•˜κ³  싢은 μž…λ ₯ ν•„λ“œλ₯Ό 직접 ν΄λ¦­ν•˜μ—¬ 선택, 별칭과 ν•¨κ»˜ μ €μž₯

μžλ™ μž…λ ₯

같은 URL 재방문 μ‹œ μ €μž₯된 데이터 λͺ©λ‘ ν‘œμ‹œ, μ›ν•˜λŠ” 데이터 μ„ΈνŠΈλ₯Ό μ„ νƒν•˜μ—¬ μžλ™ μž…λ ₯

데이터 관리

URL별 μ—¬λŸ¬ 데이터 μ„ΈνŠΈ μ €μž₯, Options νŽ˜μ΄μ§€μ—μ„œ 쑰회/μˆ˜μ •/μ‚­μ œ, μ‚¬μš© 톡계 좔적

μ•ˆμ „ν•œ μ €μž₯

password νƒ€μž… ν•„λ“œ μžλ™ μ œμ™Έ, λͺ¨λ“  λ°μ΄ν„°λŠ” λ‘œμ»¬μ—λ§Œ μ €μž₯ (μ„œλ²„ 전솑 μ—†μŒ)

μ‚¬μš© 기술

React 19 + TypeScript
μ΅œμ‹  React와 νƒ€μž… μ•ˆμ •μ„±μ„ μœ„ν•œ TypeScript 100% 적용
Chrome Extension MV3
Manifest V3, Storage API, Content Scripts
Vite + SWC
λΉ λ₯Έ λΉŒλ“œμ™€ 개발 κ²½ν—˜μ„ μœ„ν•œ μ΅œμ‹  λ²ˆλ“€λŸ¬
@crxjs/vite-plugin
Chrome ν™•μž₯ν”„λ‘œκ·Έλž¨ μ „μš© Vite ν”ŒλŸ¬κ·ΈμΈ
Message Passing
Content Script ↔ Background Script κ°„ μ•ˆμ •μ  톡신
MutationObserver
CSR μ•±μ—μ„œ 동적 DOM λ³€ν™” 감지

β—ΌοΈŽ ν”„λ‘œμ νŠΈ 이슈 (v1.0)

macOS Chromeμ—μ„œ λΈŒλΌμš°μ € μ•Œλ¦Ό ν‘œμ‹œ 문제

문제 상황

Windowsμ—μ„œλŠ” μž‘λ™ν•˜μ§€λ§Œ, macOS Chromeμ—μ„œλŠ” μ €μž₯ 확인 μ•Œλ¦Όμ΄ μ „ν˜€ ν‘œμ‹œλ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. Content Script와 Background Script κ°„ 톡신은 정상이고, μ•Œλ¦Ό κΆŒν•œλ„ 'granted' μƒνƒœμ˜€μ§€λ§Œ μ‹€μ œ μ•Œλ¦Όμ΄ 화면에 λ‚˜νƒ€λ‚˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

해결방법

단계별 디버깅을 톡해 원인을 λΆ„μ„ν–ˆμŠ΅λ‹ˆλ‹€.

  1. Service Worker 톡신 문제 μ˜μ‹¬ β†’ μž¬μ‹œλ„ 둜직 μΆ”κ°€ν–ˆμ§€λ§Œ ν•΄κ²°λ˜μ§€ μ•ŠμŒ
  2. μ‹œμŠ€ν…œ μ•Œλ¦Ό μ„€μ • 문제 μ˜μ‹¬ β†’ κΆŒν•œμ€ μ •μƒμ΄μ—ˆμŒ
  3. μ•Œλ¦Ό μ•„μ΄μ½˜ 문제 μ˜μ‹¬ β†’ base64 더미 이미지λ₯Ό μ‹€μ œ μ•„μ΄μ½˜μœΌλ‘œ λ³€κ²½ν–ˆμ§€λ§Œ μ—¬μ „νžˆ 문제
  4. ν…ŒμŠ€νŠΈ μ•Œλ¦ΌμœΌλ‘œ 원인 뢄리 β†’ κ°„λ‹¨ν•œ μ•Œλ¦Όμ€ ν‘œμ‹œλ˜μ§€λ§Œ λ²„νŠΌμ΄ ν¬ν•¨λœ λ³΅μž‘ν•œ μ•Œλ¦Όμ€ ν‘œμ‹œλ˜μ§€ μ•ŠμŒμ„ 발견
  5. 핡심 원인: macOS Chromeμ—μ„œ λ²„νŠΌμ΄ 2개 이상 ν¬ν•¨λœ μ•Œλ¦Όκ³Ό requireInteraction: true 섀정이 μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠμŒ
결과 및 배운점

크둜슀 ν”Œλž«νΌ ν˜Έν™˜μ„±μ„ μœ„ν•΄ μ•Œλ¦Ό ꡬ쑰λ₯Ό λ‹¨μˆœν™”ν•˜κ³  1개의 λ²„νŠΌμœΌλ‘œ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€. 이 κ³Όμ •μ—μ„œ ν”Œλž«νΌλ³„ API λ™μž‘ 차이와 Chrome Extension의 μ œμ•½μ‚¬ν•­μ— λŒ€ν•΄ 배울 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

νŽ˜μ΄μ§€ 이동 μ‹œ 데이터 손싀 문제

문제 상황

넀이버 검색과 같이 폼 제좜 ν›„ μ¦‰μ‹œ νŽ˜μ΄μ§€κ°€ μ΄λ™ν•˜λŠ” ν™˜κ²½μ—μ„œ μ €μž₯ 확인 λͺ¨λ‹¬μ΄ ν‘œμ‹œλ˜κΈ° 전에 νŽ˜μ΄μ§€κ°€ λ°”λ€Œμ–΄ μ‚¬μš©μž 데이터가 μ†μ‹€λ˜λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. κΈ°μ‘΄ Content Script 기반 λͺ¨λ‹¬λ‘œλŠ” νŽ˜μ΄μ§€ 생λͺ…주기와 ν•¨κ»˜ μ‚¬λΌμ‘ŒμŠ΅λ‹ˆλ‹€.

해결방법

λΈŒλΌμš°μ € 레벨 μ•Œλ¦Ό μ‹œμŠ€ν…œμœΌλ‘œ μ „ν™˜ν–ˆμŠ΅λ‹ˆλ‹€.

  1. Chrome Notifications APIλ₯Ό ν™œμš©ν•œ νŽ˜μ΄μ§€ 독립적 μ•Œλ¦Ό
  2. Background Scriptμ—μ„œ 직접 μ €μž₯ 둜직 처리
  3. requireInteraction μ˜΅μ…˜μœΌλ‘œ μ‚¬μš©μž μ‘λ‹΅κΉŒμ§€ μ•Œλ¦Ό μœ μ§€
  4. Message Passing을 ν†΅ν•œ Content ↔ Background Script κ°„ μ•ˆμ •μ  톡신
결과 및 배운점

νŽ˜μ΄μ§€ 이동과 μ™„μ „νžˆ λ…λ¦½μ μœΌλ‘œ λ™μž‘ν•˜λŠ” μ‹œμŠ€ν…œμ„ κ΅¬μΆ•ν–ˆμŠ΅λ‹ˆλ‹€. Chrome Extension의 μ•„ν‚€ν…μ²˜μ™€ 생λͺ…μ£ΌκΈ°, 그리고 λΈŒλΌμš°μ € API의 ν™œμš©λ²•μ— λŒ€ν•΄ κ²½ν—˜μ„ μŒ“μ„ 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

μ‚¬μš©μž κ²½ν—˜ μ΅œμ ν™” - λΆˆν•„μš”ν•œ μ €μž₯ μš”μ²­ λ°©μ§€

문제 상황

λͺ¨λ“  폼 제좜 μ‹œλ§ˆλ‹€ μ €μž₯ 확인을 μš”μ²­ν•˜λ©΄ μ‚¬μš©μžμ—κ²Œ ν”Όλ‘œκ°μ„ μ£Όκ³ , μ‹€μ œλ‘œ μ €μž₯이 ν•„μš”ν•˜μ§€ μ•Šμ€ κ²½μš°λ„ λ§Žμ•˜μŠ΅λ‹ˆλ‹€. κΈ°μ‘΄ μžλ™μ™„μ„± λ„κ΅¬λ“€μ˜ μ£Όμš” λΆˆνŽΈν•¨μ΄μ—ˆλ˜ "κ³Όλ„ν•œ μ•Œλ¦Ό"을 ν•΄κ²°ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

해결방법

μ‚¬μš©μž 주도적 μ €μž₯ μ‹œμŠ€ν…œμ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

  1. κΈ°λ³Έ OFF μƒνƒœλ‘œ λΆˆν•„μš”ν•œ μ•Œλ¦Ό λ°©μ§€
  2. ν™•μž₯ μ•„μ΄μ½˜ 클릭으둜 μ €μž₯ λͺ¨λ“œ ON/OFF μ „ν™˜ (λΉ¨κ°„ "ON" λ°°μ§€ ν‘œμ‹œ)
  3. μ €μž₯ μ™„λ£Œ ν›„ μžλ™μœΌλ‘œ OFF μƒνƒœ 볡귀
  4. μ‚¬μ΄νŠΈλ³„ "λ‹€μ‹œ 묻지 μ•ŠμŒ" μ„€μ • 지원
  5. κΈ€λ‘œλ²Œ μ €μž₯ λͺ¨λ“œμ™€ μ‚¬μ΄νŠΈλ³„ μ„€μ •μ˜ 이쀑 필터링
결과 및 배운점

μ‚¬μš©μžκ°€ ν•„μš”ν•  λ•Œλ§Œ μ €μž₯ κΈ°λŠ₯을 ν™œμ„±ν™”ν•˜λŠ” 직관적인 UXλ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©μž 쀑심 섀계와 μƒνƒœ κ΄€λ¦¬μ˜ μ€‘μš”μ„±μ„ 체감할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

β—ΌοΈŽ ν”„λ‘œμ νŠΈ 이슈 (v2.0)

CSR μ•±μ—μ„œ μ…€λ ‰ν„° λ§€μΉ­ μ‹€νŒ¨ 문제

문제 상황

React, Vue λ“± CSR μ•±μ—μ„œ λ™μ μœΌλ‘œ μƒμ„±λ˜λŠ” 클래슀λͺ…μ΄λ‚˜ ID에 μ˜μ‘΄ν•˜λ‹€ λ³΄λ‹ˆ μ…€λ ‰ν„°κ°€ 자주 λ³€κ²½λ˜μ–΄ μ €μž₯된 데이터와 맀칭이 μ‹€νŒ¨ν•˜λŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. 특히 λΉŒλ“œλ§ˆλ‹€ ν•΄μ‹œκ°€ λ°”λ€ŒλŠ” CSS-in-JS ν™˜κ²½μ—μ„œ μ‹¬κ°ν–ˆμŠ΅λ‹ˆλ‹€.

해결방법

μ…€λ ‰ν„° 생성 μš°μ„ μˆœμœ„λ₯Ό μž¬μ„€κ³„ν–ˆμŠ΅λ‹ˆλ‹€.

  1. name 속성을 μ΅œμš°μ„ μœΌλ‘œ μ‚¬μš© (폼 ν•„λ“œμ—μ„œ κ°€μž₯ μ•ˆμ •μ )
  2. data-testid, data-test-id, data-cy λ“± ν…ŒμŠ€νŠΈμš© 속성 ν™œμš©
  3. id 속성은 κ·Έ λ‹€μŒ μš°μ„ μˆœμœ„λ‘œ 배치
  4. λΆˆμ•ˆμ •ν•œ μ…€λ ‰ν„° μ‚¬μš© μ‹œ μ‚¬μš©μžμ—κ²Œ κ²½κ³  μ•„μ΄μ½˜(⚠️) ν‘œμ‹œ
결과 및 배운점

μ•ˆμ •μ μΈ 속성을 μš°μ„  μ‚¬μš©ν•˜κ³ , λΆˆμ•ˆμ •ν•œ μ…€λ ‰ν„°λŠ” μ‚¬μš©μžκ°€ 인지할 수 μžˆλ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€. ν”„λ‘ νŠΈμ—”λ“œ μƒνƒœκ³„μ˜ λ‹€μ–‘ν•œ ν™˜κ²½μ„ κ³ λ €ν•œ μ„€κ³„μ˜ μ€‘μš”μ„±μ„ λ°°μ› μŠ΅λ‹ˆλ‹€.

신뒰도 기반 맀칭의 예츑 λΆˆκ°€λŠ₯ν•œ λ™μž‘

문제 상황

κΈ°μ‘΄μ—λŠ” μ…€λ ‰ν„°, ID, 클래슀, μœ„μΉ˜ λ“± μ—¬λŸ¬ κΈ°μ€€μœΌλ‘œ 신뒰도λ₯Ό κ³„μ‚°ν•˜μ—¬ λ§€μΉ­ν–ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ "λŒ€μΆ© λΉ„μŠ·ν•˜λ©΄ λ§€μΉ­"ν•˜λŠ” 방식은 잘λͺ»λœ ν•„λ“œμ— 데이터가 μž…λ ₯λ˜λŠ” μœ„ν—˜μ΄ μžˆμ—ˆκ³ , μ‚¬μš©μžκ°€ μ–΄λ–€ ν•„λ“œμ— μž…λ ₯될지 μ˜ˆμΈ‘ν•˜κΈ° μ–΄λ €μ› μŠ΅λ‹ˆλ‹€.

해결방법

신뒰도 기반 맀칭을 μ™„μ „νžˆ μ œκ±°ν•˜κ³  μ •ν™• λ§€μΉ­ λ°©μ‹μœΌλ‘œ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.

  1. 셀렉터와 input νƒ€μž…μ΄ μ™„μ „νžˆ μΌμΉ˜ν•΄μ•Όλ§Œ λ§€μΉ­
  2. λ§€μΉ­ μ‹€νŒ¨ μ‹œ ν•΄λ‹Ή ν•„λ“œλŠ” μŠ€ν‚΅ν•˜κ³  μ‚¬μš©μžμ—κ²Œ κ²°κ³Ό μ•Œλ¦Ό
  3. λͺ‡ 개 ν•„λ“œκ°€ μ±„μ›Œμ‘Œκ³ , λͺ‡ κ°œκ°€ μŠ€ν‚΅λ˜μ—ˆλŠ”μ§€ λͺ…ν™•ν•˜κ²Œ ν‘œμ‹œ
결과 및 배운점

"λ˜‘λ˜‘ν•œ μΆ”μΈ‘"보닀 "예츑 κ°€λŠ₯ν•œ λ™μž‘"이 μ‚¬μš©μž 신뒰에 더 μ€‘μš”ν•˜λ‹€λŠ” 것을 λ°°μ› μŠ΅λ‹ˆλ‹€. μ‹€νŒ¨ν•˜λ”λΌλ„ λͺ…ν™•ν•˜κ²Œ μ•Œλ €μ£ΌλŠ” 것이 더 λ‚˜μ€ UXμž„μ„ μ²΄κ°ν–ˆμŠ΅λ‹ˆλ‹€.

SPA ν™˜κ²½μ—μ„œ Content Script 쀑볡 μ‹€ν–‰

문제 상황

SPA(Single Page Application)μ—μ„œ soft navigation(νŽ˜μ΄μ§€ μƒˆλ‘œκ³ μΉ¨ 없이 URL만 λ³€κ²½) μ‹œ Content Scriptκ°€ μ—¬λŸ¬ 번 μ‹€ν–‰λ˜μ–΄ 이벀트 λ¦¬μŠ€λ„ˆκ°€ 쀑볡 λ“±λ‘λ˜κ³ , λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.

해결방법

μ „μ—­ ν”Œλž˜κ·Έλ₯Ό ν™œμš©ν•œ 싱글톀 νŒ¨ν„΄μ„ μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

  1. globalThis.__formationInitialized ν”Œλž˜κ·Έλ‘œ 쀑볡 μ΄ˆκΈ°ν™” λ°©μ§€
  2. MutationObserverλŠ” νŽ˜μ΄μ§€ μ–Έλ‘œλ“œ μ‹œ μžλ™ 정리
  3. μ…€λ ‰ν„° λͺ¨λ“œ λΉ„ν™œμ„±ν™” μ‹œ λͺ¨λ“  이벀트 λ¦¬μŠ€λ„ˆ ν•΄μ œ
결과 및 배운점

Chrome Extensionκ³Ό SPA의 생λͺ…μ£ΌκΈ° 차이λ₯Ό μ΄ν•΄ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λ¦¬μ†ŒμŠ€ μ •λ¦¬μ˜ μ€‘μš”μ„±κ³Ό λ©”λͺ¨λ¦¬ 관리에 λŒ€ν•΄ 깊이 있게 배울 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

μ—…λ°μ΄νŠΈ λ‚΄μ—­

μ•„ν‚€ν…μ²˜ μž¬μ„€κ³„: λͺ¨λ“ˆν™” 및 단일 μ±…μž„ 원칙 적용, 역할별 파일 뢄리
μ…€λ ‰ν„° λͺ¨λ“œ λ„μž…: λΈŒλΌμš°μ € μ•Œλ¦Ό λ°©μ‹μ—μ„œ μ‚¬μš©μžκ°€ 직접 ν•„λ“œλ₯Ό μ„ νƒν•˜λŠ” λ°©μ‹μœΌλ‘œ λ³€κ²½
μ •ν™• λ§€μΉ­ 방식: 신뒰도 기반 λ§€μΉ­μ—μ„œ μ…€λ ‰ν„° + νƒ€μž… μ™„μ „ 일치 맀칭으둜 λ³€κ²½
URL λ§€μΉ­ κ°œμ„ : 쿼리 νŒŒλΌλ―Έν„°μ™€ ν•΄μ‹œλ₯Ό λ¬΄μ‹œν•˜κ³  pathname만 비ꡐ
μ…€λ ‰ν„° μ•ˆμ •μ„± κ°œμ„ : name, data-testid λ“± μ•ˆμ •μ  속성 μš°μ„  μ‚¬μš©, λΆˆμ•ˆμ • μ…€λ ‰ν„° κ²½κ³  ν‘œμ‹œ
UI κ°œμ„ : 컨트둀 νŒ¨λ„ λ“œλž˜κ·Έ 이동 지원, μ—λŸ¬ 처리 κ°•ν™”