← ALL ARTICLES
11 Oct 2026/BLOG

2:30 sáng hoàn thành ứng dụng React Native. 9:00 sáng, người dùng thật bắt đầu sử dụng.

Điều khó nhất là đưa một sản phẩm từ ý tưởng đến trạng thái có thể sử dụng trong thời gian rất ngắn, sau đó đặt nó trước những người dùng thật và chịu trách nhiệm với những gì mình đã xây dựng.

7 ngày phát triển. React Native, Express.js và Linux cloud server. Một đêm gần như không ngủ — và khoảng thời gian hồi hộp nhất không phải lúc viết code, mà là khi đưa sản phẩm lên production.

Có những dự án mà thử thách lớn nhất không nằm ở một thuật toán phức tạp hay một công nghệ mới.

Thử thách thực sự là đưa một sản phẩm từ yêu cầu ban đầu đến trạng thái có thể sử dụng trong thời gian ngắn, kết nối các thành phần thành một hệ thống hoàn chỉnh và triển khai để người dùng thật bắt đầu sử dụng.

Tôi đã trải qua điều đó khi phát triển một ứng dụng React Native trong 7 ngày. 2:30 sáng, ứng dụng hoàn thành phần việc cần thiết để phát hành. Đến 9:00 sáng cùng ngày, người dùng đã có thể bắt đầu sử dụng sản phẩm.

Stack công nghệ của dự án gồm React Native ở phía mobile, Express.js ở phía backend và Linux cloud server của Mắt Bão cho môi trường triển khai.

Bài viết này là ghi chép về quá trình phát triển, một số quyết định kỹ thuật và cảm giác khi chuyển từ môi trường lập trình sang môi trường production.

1. Bảy ngày để xây dựng một sản phẩm hoàn chỉnh

Bảy ngày không phải là khoảng thời gian dài khi phải xử lý đồng thời giao diện mobile, logic nghiệp vụ, tích hợp API, kiểm thử và triển khai.

Điều quan trọng không chỉ là viết code nhanh, mà còn phải biết nên tập trung vào đâu.

Tôi ưu tiên những luồng nghiệp vụ cốt lõi trước, sau đó kết nối chúng thành một quy trình sử dụng xuyên suốt. Thay vì đánh giá từng màn hình riêng lẻ, tôi nhìn ứng dụng như một sản phẩm có nhiều thành phần phụ thuộc lẫn nhau.

Một màn hình có thể hiển thị đúng nhưng vẫn chưa đảm bảo tính năng hoạt động chính xác. Dữ liệu cần được lấy từ API, trạng thái giao diện phải được cập nhật phù hợp, và ứng dụng cần xử lý được những tình huống như chờ phản hồi, dữ liệu rỗng hoặc yêu cầu thất bại.

Với deadline ngắn, tôi phải liên tục cân nhắc ba yếu tố:

  • Phạm vi: Chức năng nào thực sự cần thiết để đưa sản phẩm vào sử dụng?
  • Tính đúng đắn: Luồng nghiệp vụ nào cần được kiểm tra kỹ trước khi phát hành?
  • Khả năng vận hành: Nếu có sự cố sau triển khai, cần kiểm tra ở đâu và xử lý như thế nào?

Đây là cách tôi tiếp cận dự án: không chỉ hoàn thành phần code, mà hướng đến một sản phẩm có thể đi qua toàn bộ luồng từ giao diện mobile đến backend và môi trường máy chủ.

2. Stack kỹ thuật: React Native, Express.js và Linux

React Native — xây dựng ứng dụng mobile

React Native cho phép phát triển ứng dụng mobile bằng JavaScript hoặc TypeScript, đồng thời xây dựng giao diện thông qua các component và cơ chế quản lý trạng thái quen thuộc với hệ sinh thái React.

Một số thành phần nền tảng đáng chú ý gồm:

  • Component và props: Chia giao diện thành các đơn vị có thể tái sử dụng, truyền dữ liệu giữa các thành phần.
  • State và hooks: Quản lý trạng thái giao diện, xử lý tương tác và đồng bộ dữ liệu với vòng đời của component.
  • Navigation: Tổ chức các màn hình, luồng điều hướng và dữ liệu được truyền giữa các màn hình.
  • API integration: Gửi request đến backend, xử lý response và cập nhật giao diện theo kết quả.
  • Loading và error states: Thể hiện rõ trạng thái chờ, dữ liệu rỗng và lỗi thay vì để người dùng rơi vào một giao diện không có phản hồi.

Một điểm quan trọng khi xây dựng ứng dụng React Native là không nên chỉ tập trung vào việc giao diện hiển thị đúng. Trạng thái ứng dụng cũng cần được quản lý nhất quán.

Ví dụ, khi người dùng gửi một yêu cầu lên API, ứng dụng cần phản ánh được quá trình xử lý. Nếu request thất bại, giao diện phải có cách thông báo hoặc cho phép thử lại phù hợp. Nếu dữ liệu được cập nhật, những màn hình liên quan cần phản ánh trạng thái mới một cách hợp lý.

Đây là những vấn đề nhỏ khi nhìn riêng lẻ, nhưng chúng ảnh hưởng trực tiếp đến trải nghiệm sử dụng thực tế.

Ngoài ra, React Native không đồng nghĩa với việc mọi khác biệt giữa Android và iOS tự động biến mất. Quyền truy cập thiết bị, cấu hình build, hành vi bàn phím, vùng an toàn của màn hình và các khác biệt theo nền tảng vẫn cần được kiểm tra trong phạm vi ứng dụng hỗ trợ.

Express.js — xử lý nghiệp vụ phía backend

Phía mobile cần một backend để trao đổi dữ liệu và thực thi các nghiệp vụ không nên phụ thuộc vào ứng dụng trên thiết bị người dùng.

Express.js đảm nhiệm vai trò xây dựng API, tiếp nhận request từ ứng dụng React Native, xử lý logic phía server và trả kết quả về client.

Trong mô hình này, hai phía có trách nhiệm khác nhau:

  • React Native chịu trách nhiệm về giao diện, tương tác và trải nghiệm người dùng.
  • Express.js xử lý các yêu cầu nghiệp vụ phía server, xác thực và phân quyền theo thiết kế, kiểm tra dữ liệu đầu vào và giao tiếp với các thành phần backend cần thiết.
  • API đóng vai trò hợp đồng giao tiếp giữa mobile và server.

Sự phân tách này giúp ứng dụng mobile không phải tự xử lý toàn bộ nghiệp vụ. Những quy tắc quan trọng cần được kiểm tra ở phía server, bởi dữ liệu gửi từ thiết bị người dùng không thể mặc nhiên được xem là đáng tin cậy.

Một điểm cần lưu ý là xử lý lỗi cũng phải được thiết kế xuyên suốt. Backend cần trả về phản hồi có cấu trúc phù hợp; ứng dụng mobile cần diễn giải phản hồi đó thành trạng thái mà người dùng có thể hiểu được.

Khi có sự cố, việc phân biệt lỗi phía client, lỗi API và lỗi hạ tầng sẽ giúp quá trình tìm nguyên nhân rõ ràng hơn.

Linux cloud server — nơi ứng dụng backend vận hành

Một ứng dụng mobile không chỉ bao gồm phần mềm được cài trên điện thoại. Nếu sử dụng backend, hệ thống còn phụ thuộc vào máy chủ, cấu hình mạng và khả năng duy trì dịch vụ.

Trong dự án này, môi trường triển khai backend là Linux cloud server của Mắt Bão.

Ở góc độ vận hành, việc đưa Express.js lên máy chủ không đơn giản chỉ là sao chép source code và chạy ứng dụng. Cần quan tâm đến cách tiến trình được khởi chạy, cách ứng dụng tiếp nhận request, cấu hình môi trường, cổng dịch vụ và khả năng kiểm tra khi phát sinh lỗi.

Một số kiến thức nền tảng có ý nghĩa trực tiếp trong quá trình này:

  • Process management: Ứng dụng backend cần tiếp tục hoạt động sau khi kết thúc phiên SSH và có cơ chế khởi động lại phù hợp khi tiến trình gặp sự cố.
  • Network và firewall: Cần xác định cổng nào được phép truy cập từ bên ngoài, cổng nào chỉ nên phục vụ nội bộ.
  • Reverse proxy và HTTPS: Nginx có thể đứng trước Express.js để tiếp nhận kết nối HTTP/HTTPS và chuyển tiếp request đến ứng dụng backend.
  • Environment variables: Các cấu hình theo môi trường cần được tách khỏi source code; thông tin bí mật không nên đưa vào repository.
  • Logs và troubleshooting: Log của ứng dụng, trạng thái tiến trình và kết nối mạng là những đầu mối quan trọng khi cần tìm nguyên nhân sự cố.

Đây cũng là lý do tôi coi Linux và DevOps là một phần của năng lực phát triển phần mềm end-to-end. Viết được backend là một chuyện; triển khai, quan sát và xử lý sự cố của backend trong môi trường thật lại là một phần công việc khác.

Lưu ý: Những kỹ thuật như Nginx, HTTPS, process manager và firewall là các nội dung quan trọng trong vận hành Linux server; không nên hiểu rằng tất cả đều đã được sử dụng trong dự án nếu chưa xác nhận cấu hình triển khai thực tế.

3. 2:30 sáng — hoàn thành ứng dụng, nhưng chưa hết lo

1791693610021-build-reactnav.png

2:30 sáng.

Sau bảy ngày tập trung, ứng dụng đã hoàn thành phần việc cần thiết để chuẩn bị đưa vào sử dụng.

Cảm giác đầu tiên không hẳn là vui sướng. Nó giống sự nhẹ nhõm pha lẫn một chút hoài nghi.

Mình đã hoàn thành rồi.

Nhưng liệu mọi thứ có thực sự ổn không?

Trong môi trường phát triển, tôi có thể chủ động chạy lại ứng dụng, kiểm tra request, sửa code và thử nghiệm nhiều lần. Nhưng khi chuyển sang production, hệ thống bắt đầu chịu tác động từ những điều kiện thực tế mà môi trường phát triển không phải lúc nào cũng tái hiện được.

API có thể phản hồi chậm. Cấu hình môi trường có thể không giống lúc kiểm thử. Một luồng nghiệp vụ có thể xuất hiện tình huống chưa được tính đến. Một lỗi kết nối giữa mobile và backend cũng có thể khiến chức năng không hoạt động như mong đợi.

Hoàn thành code không có nghĩa là mọi rủi ro đã biến mất.

Với một ứng dụng mobile có backend, cần nhìn nhận toàn bộ chuỗi hoạt động: ứng dụng gửi request, mạng truyền dữ liệu, server tiếp nhận, backend xử lý và response quay trở lại thiết bị. Một mắt xích có vấn đề có thể ảnh hưởng đến trải nghiệm cuối cùng.

Tôi không chỉ đang cố gắng hoàn thành một ứng dụng. Tôi đang chuẩn bị đưa sản phẩm mình xây dựng đến với người dùng thật.

4. 9:00 sáng — người dùng bắt đầu sử dụng

Khoảng cách giữa 2:30 sáng và 9:00 sáng chỉ là vài tiếng.

Nhưng về mặt tâm lý, đó là một khoảng thời gian rất khác.

Khi người dùng bắt đầu truy cập và sử dụng ứng dụng, mọi thứ không còn chỉ nằm trong editor, terminal hay môi trường kiểm thử nữa.

Sản phẩm đã bước vào môi trường thực tế.

Tôi bắt đầu nghĩ đến những câu hỏi mà trước đó có thể chưa khiến mình cảm thấy áp lực đến vậy:

  • Nếu người dùng gặp lỗi ở chức năng chính thì sao?
  • Nếu API phản hồi chậm hoặc thất bại thì sao?
  • Nếu dữ liệu đầu vào khác với những gì mình đã thử nghiệm thì sao?
  • Nếu backend dừng hoạt động, mình sẽ phát hiện và xử lý như thế nào?

Cảm giác hồi hộp lúc đó rất thật.

Tôi vừa mong người dùng sử dụng sản phẩm thuận lợi, vừa lo xuất hiện lỗi mà mình chưa lường trước. Mỗi khả năng phát sinh đều khiến mình nghĩ đến việc cần kiểm tra ở đâu, dấu hiệu nào có thể giúp xác định nguyên nhân và nên bắt đầu xử lý từ bước nào.

Đó là cảm giác khác hẳn khi nhìn thấy ứng dụng chạy thành công trên máy cá nhân.

Khi người dùng thật bắt đầu sử dụng, chất lượng phần mềm không còn chỉ là điều developer tự đánh giá. Nó trở thành trải nghiệm mà người dùng trực tiếp nhận được.

5. Những điều tôi rút ra từ lần triển khai

Hoàn thành nhanh không đồng nghĩa với được phép bỏ qua chất lượng

Deadline ngắn buộc tôi phải ưu tiên. Không phải mọi tính năng đều cần được hoàn thiện đến cùng một mức độ ngay từ phiên bản đầu tiên. Nhưng các luồng nghiệp vụ quan trọng, tính đúng đắn của dữ liệu và những vấn đề có thể ảnh hưởng trực tiếp đến người dùng vẫn cần được chú trọng.

Tốc độ có giá trị khi nó giúp đưa đúng sản phẩm đến người dùng sớm hơn, chứ không phải khi nó chỉ chuyển phần việc chưa hoàn thành sang giai đoạn vận hành.

Ứng dụng mobile phải được nhìn cùng backend

Một màn hình hoạt động tốt chưa chắc đồng nghĩa với một chức năng hoạt động tốt.

Để hoàn thành một luồng nghiệp vụ, ứng dụng cần xử lý trạng thái giao diện, gửi request đúng định dạng, tiếp nhận response và phản ánh kết quả phù hợp. Backend cần xử lý nghiệp vụ và dữ liệu một cách nhất quán.

Nhìn toàn bộ luồng từ mobile đến API và server giúp việc kiểm tra có hệ thống hơn, thay vì chỉ kiểm tra riêng từng thành phần.

Production là một bước chuyển về trách nhiệm

Trong quá trình phát triển, tôi có thể sửa lỗi rồi chạy lại. Khi sản phẩm đã được đưa vào sử dụng, việc xử lý lỗi còn phải tính đến ảnh hưởng đối với người dùng, dữ liệu và tính liên tục của dịch vụ.

Một engineer cần quan tâm đến việc triển khai thành công, nhưng cũng phải suy nghĩ về cách phát hiện lỗi, xác định nguyên nhân và đưa hệ thống trở lại trạng thái ổn định.

Đó là lý do tôi ngày càng coi trọng quy trình triển khai rõ ràng, log đủ hữu ích, kiểm tra các luồng quan trọng và phương án khôi phục khi cần thiết.

Không thể thay thế khả năng quan sát bằng sự lo lắng

Cảm giác sợ lỗi không phải điều cần che giấu. Nó nhắc mình rằng luôn có khoảng cách giữa những gì đã kiểm thử và những gì có thể xảy ra trong thực tế.

Tuy nhiên, không thể vận hành một hệ thống chỉ bằng việc liên tục nhìn vào màn hình để chờ lỗi xuất hiện.

Cách tốt hơn là xây dựng những cơ chế giảm sự phụ thuộc vào cảm giác của con người: log có ngữ cảnh, theo dõi trạng thái dịch vụ, kiểm tra sức khỏe ứng dụng, thông báo lỗi và quy trình xử lý sự cố rõ ràng.

Mục tiêu không phải là tin rằng hệ thống sẽ không bao giờ có lỗi.

Mục tiêu là có đủ khả năng để phát hiện, hiểu và xử lý lỗi khi nó xảy ra.

6. Từ viết code đến xây dựng và vận hành sản phẩm

Trải nghiệm này giúp tôi nhìn rõ hơn một điều: năng lực xây dựng phần mềm không kết thúc khi tính năng cuối cùng được hoàn thành.

Một sản phẩm có thể sử dụng được cần nhiều thành phần phối hợp với nhau. Ứng dụng React Native cung cấp trải nghiệm trên thiết bị. Express.js xử lý các yêu cầu phía backend. Linux cloud server cung cấp môi trường để dịch vụ vận hành. API kết nối các thành phần thành một luồng sử dụng hoàn chỉnh.

Mỗi lớp đều có vấn đề kỹ thuật riêng, nhưng người dùng chỉ nhìn thấy kết quả cuối cùng.

Tôi vẫn thích cảm giác xây dựng một sản phẩm từ đầu. Nhưng điều khiến trải nghiệm này đáng nhớ không chỉ là việc hoàn thành ứng dụng React Native trong bảy ngày.

Đó còn là khoảnh khắc chuyển từ câu hỏi “Mình đã code xong chưa?” sang câu hỏi “Sản phẩm này đã sẵn sàng để người khác sử dụng chưa, và mình sẽ xử lý thế nào nếu có sự cố?”

Hai câu hỏi nghe gần giống nhau, nhưng đại diện cho hai cách nhìn rất khác về công việc kỹ thuật.

Với tôi, mục tiêu không chỉ là viết code nhanh hơn. Đó còn là xây dựng các thành phần có thể phối hợp với nhau, triển khai chúng vào môi trường thực tế và từng bước nâng cao khả năng vận hành một cách có trách nhiệm.


Trần Nguyễn Thanh Hậu
Software Engineer · Fullstack JavaScript · React Native · Linux & DevOps

Ghi chép về kỹ thuật phần mềm, quá trình xây dựng sản phẩm và những bài học từ môi trường thực tế tại thanhhau.dev.