What happens when you hit a URL?
DNS → TCP → TLS → HTTP 請求/回應 → 瀏覽器解析與渲染
當你在瀏覽器輸入一個 URL 並按下 Enter,大致會經歷以下流程:
DNS 解析 (DNS Resolution)
瀏覽器需要知道這個網域名稱(例如 example.com)對應的伺服器 IP。
它會先查快取(瀏覽器快取 → 作業系統 → 路由器 → ISP DNS),如果沒有找到,就透過 DNS 系統一路詢問,直到取得正確的 IP。
建立 TCP 連線 (TCP Handshake)
瀏覽器使用獲得的 IP,跟伺服器進行 三次握手 (3-way handshake),建立可靠的 TCP 連線。
TLS/SSL 加密協商 (TLS Handshake, 若是 HTTPS)
若 URL 是 https://,會進行 TLS/SSL 機制:交換憑證、加密金鑰,建立安全加密的通道。
發送 HTTP 請求 (HTTP Request)
瀏覽器向伺服器發出請求(例如 GET /index.html HTTP/1.1),附帶 headers、cookies 等資訊。
伺服器處理並回應 (HTTP Response)
伺服器接收到請求,處理後回傳對應的內容(例如 HTML、JSON、圖片等)。
首字節時間 (TTFB, Time to First Byte)
瀏覽器等候伺服器傳回第一個位元組。這個指標常用來衡量伺服器回應速度。
瀏覽器渲染 (Rendering)
瀏覽器開始解析 HTML,建立 DOM 樹 (DOM Tree)。
同時下載並解析 CSS,建立 CSSOM 樹 (CSS Object Model)。
DOM + CSSOM 合併成渲染樹 (Render Tree)。
開始布局 (Layout),計算每個元素在頁面上的大小與位置。
繪製 (Painting) 元素到畫面上,最後顯示在螢幕。
如果有 JavaScript,可能會修改 DOM 或 CSSOM,導致重新渲染 (Reflow / Repaint)。
英文自我介紹
Hi, I’m Kuei-Hung Lin, but you can call me Andrea. I’m currently based in Sydney, working as a Senior Software Engineer at Lendi Group.
I have more than ten years of experience in software development, mostly focusing on the front-end. My main stack is React and TypeScript, and I also work with state management libraries like Redux and React Query. On the backend, I’ve built services with Node.js and AWS, including Lambda and DynamoDB.
At Lendi, beyond building features, I contribute to our front-end guild and design system discussions. That means thinking about how to make components reusable across teams, how to standardize best practices, and how to improve our overall developer experience.
What I really enjoy is creating clean, maintainable solutions and collaborating closely with designers and backend engineers to ship end-to-end features. I’m excited about opportunities where I can bring both hands-on coding and architectural thinking, while continuing to learn and grow with the team.
在目前工作的最大挑戰
中文長版回答示範
情境 (Situation / Challenge)
在我目前的公司,有一次最大的挑戰是參與 Required Documents 系統 的開發。這個系統對於整個貸款流程非常關鍵,因為能不能順利收集到必要文件,幾乎決定了貸款能否成功核准。對客戶來說,這是流程中最耗時、最容易卡住的環節;對公司來說,它涉及到非常嚴格的合規性與法律風險。
當時公司剛開始嘗試用 跨功能團隊 (cross-functional team) 的方式運作。但實際上,這個團隊的人員配置並不平衡:大部分成員雖然是前端工程師,卻對前端並不感興趣,他們寧願去學後端,所以導致後端程式碼寫得零零散散,缺乏架構,前端的部分同時也沒有被好好處理。更大的挑戰是,當時的主管在需求管理上沒有做好,常常是自己想到一個功能就直接推動開發,卻沒有確認這些功能是否真的符合使用者或業務需求,結果就是需求混亂、方向不明確,專案的上線時間不斷延後。
我加入的時候,專案已經進入「準備上線」的階段,但前端幾乎完全沒有準備好,架構混亂、功能缺失,而且 deadline 迫在眉睫。
任務 (Task)
我的挑戰就是在這樣的環境下,把前端部分救回來,確保能夠在短時間內交付一個符合需求、可以真正被使用的系統。
行動 (Action)
我採取了幾個具體行動:
需求釐清與對齊
我先跟 PM 和相關的 stakeholders 一起確認整個系統的實際需求。我不再只是接主管臨時新增的單一功能,而是用 end-to-end 的方式 去看整個文件流程,從「客戶上傳文件 → Broker 檢視 → 系統判斷是否完整 → 合規部門確認」的完整路徑出發,去檢視哪些是最重要的需求,哪些是延伸功能。
重整前端架構
我發現現有程式碼沒有明確的結構,所以我先整理出整個系統的前端大架構,把 核心功能(例如文件清單、文件上傳與檢視、權限控制)和 共用元件(例如上傳模組、錯誤提示、進度指引)分離出來。這樣做的目的是確保開發過程可以被多人分工,也讓未來維護更清楚。
帶領協作
我不是自己單打獨鬥,而是把架構整理好後,再分配給其他前端同事一起完成。我確保每個人都知道自己負責的部分,並且知道這些部分如何整合到整體架構裡。
改善溝通流程
因為之前的問題之一是需求零散、票務混亂,我選擇在跟 PM 和 stakeholders 確認需求後,主動把需求整理成 清楚的 ticket,再提交給主管與團隊,讓大家都能看到清楚的規格和目標。這樣不僅提升了透明度,也避免了主管想到什麼就臨時加一張票,導致團隊失焦。
結果 (Result)
最後,我們成功在 deadline 前完成了前端的交付,並且把系統的可用性大幅提升。這個系統上線後,讓文件收集流程更清楚,也降低了合規部門對資料安全的擔憂。從團隊角度來看,前端有了一個更合理的架構,未來的擴充和維護也更容易。
學習 (Learning)
這次經驗給我最大的學習有三點:
要不斷問「為什麼」
不只是執行任務,而是要確定我們正在解決的到底是什麼問題。這樣才能避免做了很多事,但最後卻沒有解決核心痛點。
專業溝通的重要性
即使在管理或需求流程混亂的情況下,我也學會用專業的方式來引導大家對齊。不是去抱怨,而是用「整理需求 → 確認 → 文件化」的方式,把混亂轉換成團隊能跟隨的計畫。
如何在壓力下帶領團隊
在有限時間內整理架構、分配工作,讓其他前端同事能夠快速進入狀況,這是我第一次體會到自己不只是工程師,也是帶領者。
在目前工作中最重要的經歷或學習
有沒有主動為公司、專案做過什麼
design ops, frontend guild master
我曾經自願擔任 Frontend Guild 的 Master。雖然沒有強制制定統一的 code style(因為各 team 有自己的工作方式),但我更專注在能帶來跨團隊效益的改進。
例如,我推動淘汰 Sentry,統一只用 Datadog,讓公司避免維護兩套系統的浪費,也提升了追蹤錯誤的一致性。同時,我也主導把舊的 TSLint 換成 ESLint,讓團隊能跟上業界主流工具,提升長期維護性與品質。
我的重點是推動實際能帶來價值的最佳實踐,而不是流於形式的規範。
I volunteered as the Frontend Guild Master. Instead of enforcing a rigid code style across all teams, I focused on driving changes that had real, cross-team impact. For example, I led the initiative to retire Sentry and consolidate monitoring on Datadog, which reduced redundant costs and improved consistency. I also spearheaded the migration from TSLint to ESLint, aligning with industry standards and ensuring better long-term code quality. My priority was to introduce best practices that delivered tangible value, rather than cosmetic rules.
在工作上犯過最大的錯、performance review 中被給的負評/需改進項目
在一個專案中,我一開始低估了需求變動的影響,沒有及時和 PM 與設計師確認,結果最後花了額外時間返工。這也是在 performance review 中被提到的改進點。
後來我調整做法,會主動在需求不清楚時提出澄清問題,並且在早期先畫 prototype 給團隊確認,避免方向錯誤。這樣之後參與的專案,需求變更帶來的影響就大幅降低。
在工作上有哪些地方可以改進
假設現在打給你 team lead 問他你有什麼優缺點,你覺得他會說什麼
如果打給我 team lead,他可能會說我的優點是很有責任感,遇到專案進度緊張時,能主動找到解法,不會把問題丟給別人。另外我在 code 上也很細心,會注意可維護性與一致性。
至於缺點,他可能會提到我在會議裡有時候比較安靜,因為需要更多時間消化資訊。不過我已經在練習事前閱讀文件並準備問題,這樣在會議中就能更快參與討論。
你覺得工作項目中某個 project 最核心的 feature 是什麼
在我目前的公司,對我來說最核心的專案是 Required Documents 系統。這個系統的重要性在於,它幾乎決定了一個客戶能不能順利完成貸款。因為貸款流程中,收集文件往往是最耗時、最容易出現問題的環節。如果沒有一個清楚、有效率的文件收集流程,貸款就很容易卡住。
我認為這個系統最核心的功能是 「動態的文件需求與指引」。也就是說,系統必須能夠判斷哪些是所有案件都必須具備的文件,哪些則是特定情況下才需要的文件,並且即時告訴 Broker 或客戶「接下來還需要準備哪些文件」。如果沒有這個功能,整個流程會變得非常混亂,Broker 和客戶都會感到挫折,甚至可能導致貸款失敗。
除此之外,這個系統還面臨 合規與安全 的挑戰。文件裡面有非常多敏感的個人資訊,公司必須確保這些資料能夠安全地儲存在雲端,而不是被下載到員工的本地電腦,否則就可能違反合規規範並造成風險。
在這個專案裡,我的角色是 前端介面的主要負責人。我的工作除了設計文件上傳、檢視的 UI 之外,還必須處理複雜的 文件所有權邏輯,例如:某些文件只能由客戶上傳,Broker 只能檢視;某些文件則可能需要雙方共同操作。我需要確保這些權限邏輯在 UI 上被正確地反映,讓使用者可以清楚知道自己能做什麼,不能做什麼。
這個專案讓我學到的一點是:在金融科技領域,最核心的功能往往是在 使用者體驗與合規要求 之間找到平衡。一方面,我必須設計直觀、簡單的使用流程;另一方面,也要確保系統符合嚴格的安全與法規標準。能在這兩者之間找到平衡,就是這個專案最有價值、也最具挑戰的地方。
目前的團隊架構、與哪些角色共事
為什麼想轉職
想回來台灣,想找尋與現在產業不同的挑戰
用了什麼技術,為什麼選擇他
JS 或網頁相關的基礎觀念題event loop
有嘗試效能優化的改動?
Name 3 values for display property
inline, inline-block, block, flex, grid
List all debug features you usually use.
👉 這題比較開放,考察你在開發中 如何 debug,是否有系統性思考。
瀏覽器 DevTools:
Elements 面板(檢查 DOM、CSS)
Console(console.log, console.error, console.table)
Network 面板(API 請求、Response)
Sources 面板(斷點、watch expression)
Performance / Lighthouse(效能、最佳化)
其他常用工具 / 方法:
VSCode Debugger
善用 debugger; 關鍵字
單元測試(Jest / Mocha)
API Mock / Postman
Logging 工具(Sentry, Datadog 等)
test
AMP
i18n
工作中的成就、困難
side projects 相關問題
styled-components vs CSS module
CSS Modules:就是一般的 .module.css(或 .scss)檔案,經過 bundler 編譯後,className 會自動變成區域作用域(hash 過的名稱),避免全域衝突。
styled-components:一個 CSS-in-JS 的函式庫,用 JavaScript 寫 CSS,直接綁在 React component 上,支援 props 動態改變樣式,會在 runtime 注入 style。
什麼情境該選誰?
✅ 選 CSS Modules 如果:
想要 零 runtime 開銷、最小 bundle。
團隊習慣 傳統 CSS/SCSS 寫法。
樣式需求大多 靜態,少量動態。
需要 SSR/RSC 簡單無痛。
✅ 選 styled-components 如果:
需要 props 驅動樣式(variants、條件式)。
想要 簡單做主題切換(dark/light mode)。
喜歡 元件與樣式共置,不用切檔案。
想用 polymorphic component (as 屬性)、樣式繼承 等進階功能。
useState、useCallback、useMemo
useMemo
用途:記住「值」(某個計算結果)。
重點:只有當依賴的變數改變時,才會重新計算;否則直接用快取的結果。
常見場景:昂貴計算(例如排序、過濾、複雜運算)、避免每次 render 都重建一個新物件/陣列。
const sortedList = useMemo(() => {
return list.sort((a, b) => a.value - b.value);
}, [list]);
👉 如果不用 useMemo,list.sort 每次 re-render 都會執行一次。
用途:記住「函式」。
重點:只有依賴變數改變時,才會回傳一個新的 function 參考值。
常見場景:當子元件用 React.memo 包住,但因為父元件每次 render 都產生新 function,導致子元件仍然 re-render → 用 useCallback 讓 function 的參考穩定下來。
const handleClick = useCallback(() => {
console.log(“clicked”);
}, []);
👉 不用 useCallback,每次 render 都會產生一個新的 handleClick,即使邏輯一樣。
用途:記住「元件」的 render 結果。
重點:如果 props 沒變,就不重新 render(類似 class component 的 shouldComponentUpdate)。
常見場景:某個子元件 render 成本高,且通常 props 不變。
const Child = React.memo(({ value }) => {
console.log(“render child”);
return <div>{value}</div>;
});
👉 父元件 re-render,但 value 沒變,Child 就不會再 render。
📌 總結對照
工具 記住的東西 用途 典型場景
useMemo 值 (運算結果) 避免重算 排序、過濾、避免重建物件/陣列
useCallback 函式 (function reference) 避免 function 每次變動 搭配 React.memo 子元件
React.memo 元件 (render 結果) 避免不必要 re-render 子元件 props 穩定、渲染昂貴
要記得:
useMemo / useCallback 自己不會減少 render,它們只是讓「值 / 函式」的參考穩定。
真正避免 render 的是 React.memo。
三者常常需要搭配:父元件用 useCallback 穩定傳給子元件,子元件用 React.memo 才能真正跳過 re-render。
promise.all
https://codesandbox.io/p/sandbox/frosty-james-jk72tx?file=%2Fsrc%2Findex.ts%3A56%2C9-58%2C9