Từ N+1 đến Persistence Context, thử thách 5 tuần về JPA tự mình tái hiện – Khóa 2
Đây là thử thách thực hành kéo dài 5 tuần, trong đó tái hiện persistence context và N+1 với cùng một điều kiện, so sánh chúng qua nhật ký SQL và lưu lại thành một GitHub PR mỗi tuần.
🚀 Từng làm việc tại Toss, tốt nghiệp POSTECH | Nhà phát triển Backend hiện tại (+9 năm) 🎥 YouTuber 20.000 sub | Sáng tạo nội dung lập trình 📚 Giảng viên Inflearn | Tổng số học viên 18.000+ 👥 Đang vận hành cộng đồng tuyển dụng lập trình viên (8.000+) 🧩 Contributor cho nhiều dự án mã nguồn mở (Gradle, Spring AI, v.v.) 📝 Kinh nghiệm vượt qua 38 vòng hồ sơ và hơn 100 lần chỉnh sửa CV trên Kmong (Đánh giá 5.0 sao)
Truyền tải những thông tin thực tế sống động từ ngành công nghiệp một cách dễ hiểu và có tính diễn dịch.
Thử thách JPA 5 tuần · Miễn phí · 100 người đăng ký đầu tiên
THỬ THÁCH DINGCO · 5 TUẦN
JPA vốn luôn được tin dùng, sẽ được kiểm chứng tận mắt trong 5 tuần.
Tái hiện context bền vững và N+1 trong cùng một điều kiện, so sánh qua nhật ký SQL và ghi lại thành một PR mỗi tuần. Sau 5 tuần, bạn sẽ có hồ sơ thí nghiệm được giải thích bằng số lượng truy vấn và ADR về ánh xạ.
Miễn phí · 100 người đăng ký đầu tiên
Được tạo ra bởi Dingcodingco, với hơn 18.000 học viên tích lũy trên Inflearn, mức độ hài lòng trung bình 4,9 và kinh nghiệm đỗ vào 38 công ty.
Thử thách này không cung cấp bài giảng hay giáo trình. Đây là một lộ trình thực hành, trong đó bạn chứng minh những gì đã biết hoặc tự học được thông qua các bài toán thực tế và PR trên GitHub. Chuẩn bị trước khi bắt đầu · Cần có kinh nghiệm sử dụng entity và Repository trong dự án Spring Boot.
Đây là lộ trình thực hành kéo dài 5 tuần, nơi bạn chứng minh những khái niệm đã học bằng mã nguồn, thí nghiệm và phần giải thích.
NHỮNG GÌ BẠN HOÀN THÀNH’wini
Những gì bạn nhận được sau khi hoàn thành
Bộ kiểm thử xác minh Persistence Context và vòng đời đối tượng
Số lượng SQL trước và sau khi cải thiện N+1 cùng API truy vấn động
20 câu trả lời phỏng vấn JPA kết nối ADR về mapping với log thực tế
BEFORE
Ngay cả khi truy vấn khác với dự kiến, vẫn cho rằng đó là đặc tính của framework và bỏ qua.
AFTER
Cố định trạng thái persistence và số lượng SQL bằng các bài kiểm thử, đồng thời giải thích chi phí của chiến lược mapping và truy vấn.
QUY TRÌNH LÀM VIỆC THỰC TẾ
Từ lúc đăng ký đến khi review, theo đúng thứ tự trên màn hình thực tế
Không cần sao chép và nộp địa chỉ GitHub. Trang chủ Dingco hỗ trợ xuyên suốt từ việc chuẩn bị kho lưu trữ cá nhân, tạo nhánh nhiệm vụ và PR, cho đến kiểm tra đánh giá chi tiết.
1GitHub trước, Discord sau cùngSau khi đăng nhập Kakao và hoàn tất bài chẩn đoán ban đầu, hệ thống sẽ chuẩn bị kho lưu trữ private cá nhân, còn vai trò Discord và kênh theo khóa sẽ được kết nối sau cùng.2Thực hiện nhiệm vụ trong kho lưu trữ private của tôiTrang web sẽ tiếp nối việc tạo branch và PR cho “Thí nghiệm 4 chức năng của persistence context và câu trả lời có căn cứ”. Bạn không cần sao chép rồi dán địa chỉ PR.3Xác nhận 91 điểm và các căn cứ cụ thểBạn có thể xem những điểm làm tốt và điểm cần cải thiện từ quá trình kiểm tra tự động và đánh giá AI trong phần đánh giá chi tiết trên Dingco và các bình luận PR trên GitHub, sau đó chỉnh sửa chính PR đó.4Kênh vận hành thử thách JPA khóa 2Không đăng các bài đánh giá chi tiết cá nhân lên Discord, chỉ chia sẻ bản tóm tắt hằng tuần và thông báo vận hành.
Màn hình trên là ví dụ được tạo dựa trên UI vận hành thực tế cùng các quy tắc của kho lưu trữ và kênh. Tên kho lưu trữ, số khóa và điểm đánh giá sẽ thay đổi tùy theo người tham gia và khóa học.
LỘ TRÌNH 5 TUẦN
Nhiệm vụ theo từng tuần: biến những điều đã biết thành sản phẩm thực tế
Mỗi tuần, bạn nộp vào một PR duy nhất phần triển khai·thực nghiệm, kiểm thử·log, lý do lựa chọn và câu trả lời cho các câu hỏi. Câu hỏi không phải là bài tập yêu cầu đưa ra riêng những câu trả lời đã học thuộc, mà được giải đáp bằng chính đoạn mã vừa tạo và các bằng chứng thu thập được.
W1
Nỗi khổ của JDBC và ngữ cảnh bền vững (Persistence Context)
So sánh JDBC và JPA, đồng thời kiểm chứng bằng log về bộ nhớ đệm cấp 1, tính đồng nhất, cơ chế phát hiện thay đổi và việc trì hoãn ghi.
PR tích hợp hàng tuầnThực nghiệm 4 chức năng chính của ngữ cảnh bền vững và câu trả lời dựa trên bằng chứng
Tái hiện lần lượt bộ nhớ đệm cấp một, tính đồng nhất, cơ chế phát hiện thay đổi và việc trì hoãn ghi trong cùng một giao dịch.
Trong mỗi thí nghiệm, ghi lại SQL dự kiến, SQL thực tế và thời điểm phát sinh.
So sánh với việc tự chịu trách nhiệm quản lý trạng thái khi xử lý cùng yêu cầu bằng JDBC.
Bằng chứng nộp bài · kiểm thử xác minh theo từng chức năng · nhật ký SQL thể hiện thứ tự thực thi · giải thích so với JDBC · câu trả lời cho các câu hỏi dựa trên căn cứ 1–4
함께 답할 근거형 질문 4개
Tại sao bộ nhớ đệm cấp một không phải là bộ nhớ đệm toàn cục của ứng dụng?
Tính đồng nhất của các entity có cùng mã định danh được đảm bảo trong phạm vi nào và bạn đã xác nhận điều đó như thế nào?
Cơ chế phát hiện thay đổi so sánh những thông tin nào tại thời điểm nào để tạo ra UPDATE?
Bạn đã chứng minh bằng log như thế nào về thời điểm cơ chế trì hoãn ghi thực sự thay đổi thứ tự thực thi SQL?
W2
Ánh xạ thực thể và vòng đời
Thử nghiệm chiến lược tạo khóa, flush, cùng các bẫy của detached và save/merge.
PR tích hợp hằng tuầnTái hiện các bẫy về định danh và save, cùng câu trả lời dựa trên bằng chứng
Lưu riêng thực thể mới và thực thể ở trạng thái detached, sau đó so sánh luồng persist và merge.
Ghi lại các trường hợp thời điểm phát sinh INSERT thay đổi tùy theo chiến lược định danh hoặc việc có tự gán hay không.
merge가 반환한 đối tượng과 전달한 đối tượng을 혼동했을 때 발생하는 회귀 테스트를 작성합니다.
Bằng chứng đã nộp · Mã ánh xạ entity · Nhật ký so sánh truy vấn persist·merge · Kiểm thử hồi quy save·merge · Câu trả lời cho các câu hỏi dựa trên căn cứ 1~4
함께 답할 근거형 질문 4개
Spring Data JPA lựa chọn persist và merge dựa trên tiêu chí nào khi gọi save?
Tại sao việc tiếp tục sử dụng đối tượng đã truyền vào `merge` lại nguy hiểm?
Chiến lược IDENTITY và SEQUENCE có thể tạo ra sự khác biệt nào về thời điểm INSERT?
Vì sao cần phân biệt `flush` và `commit` mới có thể giải thích chính xác nhật ký này?
W3
Quan hệ liên kết và tải lười (lazy loading)
Áp dụng an toàn bên sở hữu mối quan hệ, proxy, LAZY, cascade và orphan removal.
PR tích hợp hằng tuầnXác minh mối quan hệ và ranh giới xóa, cùng câu trả lời có căn cứ
Xác định bên sở hữu mối quan hệ User–Todo và nếu sử dụng quan hệ hai chiều, hãy viết các phương thức tiện ích để đồng bộ trạng thái của cả hai đối tượng.
So sánh SQL trước và sau khi truy cập quan hệ LAZY, đồng thời ghi lại thời điểm khởi tạo proxy.
cascade và phạm vi xóa của orphanRemoval được kiểm chứng bằng các bài kiểm thử riêng biệt.
Bằng chứng nộp bài · mã ánh xạ miền · nhật ký SQL trước và sau khi tải · bài kiểm thử phạm vi xóa · câu trả lời cho các câu hỏi dựa trên căn cứ 1–4
함께 답할 근거형 질문 4개
Tại sao cần có phía sở hữu mối quan hệ thực sự quản lý khóa ngoại?
Tại sao N+1 vẫn có thể xảy ra dù đã khai báo LAZY?
Trong những tình huống nào kết quả của cascade REMOVE và orphanRemoval khác nhau?
Tại sao phương thức tiện ích cho mối quan hệ liên kết lại cần thiết cho trạng thái đối tượng chứ không phải cơ sở dữ liệu?
W4
So sánh ánh xạ kế thừa và mở rộng tùy chọn
So sánh cùng một miền thanh toán bằng SINGLE_TABLE và JOINED, đồng thời mở rộng value type và khóa phức hợp thành các bài tập tùy chọn.
PR tổng hợp hằng tuầnADR về quyết định ánh xạ miền và câu trả lời có căn cứ
Triển khai cùng một miền thanh toán dưới dạng mô hình tái hiện tối thiểu cho hai chiến lược kế thừa SINGLE_TABLE và JOINED.
Với cùng dữ liệu H2 và điều kiện truy vấn, hãy so sánh và đo lường lược đồ được tạo, SQL truy vấn đa hình và chi phí thay đổi, đồng thời nêu rõ phạm vi đo lường.
Ghi lại lý do chọn chiến lược và loại bỏ chiến lược trong ADR.
Giá trị kiểu bất biến hoặc hợp đồng khóa phức hợp có thể được chọn làm bài tập tùy chọn để thử nghiệm.
Bằng chứng nộp · mô hình tái hiện tối thiểu SINGLE_TABLE·JOINED · so sánh lược đồ H2 và SQL truy vấn đa hình · ADR cuối cùng · câu trả lời cho các câu hỏi dựa trên căn cứ 1~4
함께 답할 근거형 질문 4개
Khi lựa chọn chiến lược ánh xạ kế thừa, bạn đã so sánh hiệu năng truy vấn và việc chuẩn hóa lược đồ như thế nào?
Trong mô hình lần này, bạn đã kiểm tra chi phí cột nullable của SINGLE_TABLE và chi phí phép JOIN của JOINED như thế nào?
SQL truy vấn đa hình khác nhau như thế nào giữa hai chiến lược, và có thể khái quát hóa kết quả thử nghiệm trên H2 đến mức nào?
Trong hai phương án ánh xạ, những yêu cầu nào sẽ khiến phương án đã bị loại bỏ trở nên phù hợp hơn?
W5
Truy vấn động và N+1
Trong truy vấn điều kiện động, tái hiện vấn đề N+1 và so sánh số lượng truy vấn cũng như tính nhất quán của kết quả với cùng một điều kiện.
PR tích hợp hàng tuầnAPI truy vấn động không có N+1 và câu trả lời có căn cứ
Triển khai API truy vấn Todo kết hợp từ hai hoặc nhiều điều kiện lựa chọn bằng các kiểu Q được tạo và QueryDSL.
Với cùng dữ liệu và điều kiện truy vấn có chứa các entity liên kết khác nhau, hãy tái hiện vấn đề N+1 và so sánh số lượng truy vấn trước và sau khi cải thiện bằng công cụ quan sát SQL được cung cấp.
Chọn QueryDSL fetch join hoặc DTO projection để viết các bài kiểm thử hồi quy về tính nhất quán của kết quả, đồng thời giải thích chi phí liên quan đến phân trang, bản ghi trùng lặp và mức độ kết hợp.
Có thể kiểm thử riêng như một bài tập tùy chọn về tính nhất quán của ngữ cảnh bền vững sau fetch join collection, phân trang hoặc các thao tác hàng loạt.
Bằng chứng nộp · API truy vấn động QueryDSL · Số lượng SQL trước và sau khi cải thiện với cùng điều kiện · Kiểm thử hồi quy tính nhất quán của kết quả truy vấn · Câu trả lời cho các câu hỏi dựa trên căn cứ 1–4
함께 답할 근거형 질문 4개
N+1 xảy ra với LAZY hay EAGER, và nguyên nhân cốt lõi là gì?
Tại sao phương thức tối ưu hóa truy vấn được chọn lại phù hợp với yêu cầu hiện tại hơn các phương án thay thế khác?
QueryDSL에서 조건을 조합할 때 null·빈 값의 경계를 어떤 규칙과 테스트로 확정했나요?
Bạn đã kiểm soát thứ tự như thế nào để cache cấp một và thao tác INSERT fixture không làm sai lệch việc đo số lượng truy vấn?
CHU TRÌNH HÀNG TUẦN
Hoàn thành bài thực hành của một tuần trong một PR duy nhất.
Xác nhận bài toán thực tế theo từng tuần
Thực hiện nhiệm vụ trên nhánh cá nhân
Mã nguồn, bài kiểm thử và phần giải thích được nộp qua PR
Kiểm tra tự động và xem xét AI
Chỉnh sửa PR đó và tự động hợp nhất
Xác nhận PR đã đạt và phần giải thích chính thức
Phản ánh các đánh giá đồng nghiệp tích lũy và hồ sơ học tập của crew
Chỉ sử dụng GitHub PR để nộp bài. Tự động kiểm tra mã thử nghiệm, nhật ký SQL và ADR trong cùng một PR, đồng thời lưu lại lịch sử chỉnh sửa. Tự động xác nhận xem các bằng chứng cần thiết có nằm trong PR hay không.
MỨC ĐỘ GẮN KẾT CỦA CREW
Chỉ trò chuyện trong 20 phút về một câu nói ngắn về nhiệm vụ.
Từ tuần thứ 2, hãy để lại một lời nhắn trong PR, và các thành viên chỉ chia sẻ những điểm bị vướng mắc cùng các cách tiếp cận khác.
Từ tuần 2, một lời cho mỗi nhiệm vụ Khi nộp PR, hãy ghi lại điểm vướng mắc trong 10–300 ký tự.
20 phút vào thời gian do nhóm quy định Mặc định là thứ Ba lúc 21:15, chỉ chia sẻ những điểm bị vướng và các cách tiếp cận khác.
Trưởng nhóm tổng kết trong 1–30 ký tự Từ tuần 2, hoàn thành sẽ được cộng +5 điểm cho crew, độc lập với việc hoàn thành cá nhân.
Hoạt động thưởng của đội Người tham gia không cần viết bài riêng ngoài một câu về nhiệm vụ. Điểm +5 của crew được tính riêng với việc hoàn thành cá nhân.
BUỔI LIVE
Một lần trực tiếp, cùng thống nhất cách tiến hành
Trong thời gian diễn ra thử thách, sẽ có một buổi live session. Chúng ta sẽ cùng thống nhất tiêu chí hoàn thành và trực tiếp kiểm tra cách bài nộp được hiển thị trên màn hình.
Hướng dẫn cách thức tiến hành trong 5 tuần và tiêu chí hoàn thành khóa học
Trong buổi kickoff thứ Hai, hướng dẫn chuẩn bị nhánh cho nhiệm vụ đầu tiên và demo cách gửi PR lên GitHub sau khi bắt đầu vào thứ Tư
Hỏi đáp trực tiếp real-time
Liên kết tham gia sẽ được đăng trong thông báo trên Discord trước khi bắt đầu. Ngay cả khi không thể tham gia buổi phát trực tiếp, bạn vẫn có thể xem tiêu chí hoàn thành và cách nộp bài trên trang chủ Dingco và thông báo trên Discord.
THỎA THUẬN THỬ THÁCH
Mỗi người tự học khái niệm, cùng nhau thực hành và nhận phản hồi
Thử thách này không cung cấp bài giảng, giáo trình, Notion hay tài liệu bổ sung. Bạn sẽ áp dụng những gì đã biết hoặc tự học vào các vấn đề thực tế và chứng minh bằng PR trên GitHub.
Thử thách cung cấp
Bài toán thực tế theo từng tuần · Kho lưu trữ thực hành private cá nhân · Tiêu chí đạt rõ ràng · Kiểm tra tự động và đánh giá bằng AI · So sánh với đồng nghiệp và ghi nhận hoàn thành chặng đường
Người tham gia cần chuẩn bị
Các khái niệm cơ bản trong lĩnh vực tương ứng · Kinh nghiệm với Git và GitHub PR · Thời gian để thực hiện mỗi tuần · Thái độ chủ động tự bổ sung những khái niệm còn thiếu
Học trước tùy chọn · Mua riêng · 9 giờ 39 phút
[Lv2] Chinh phục toàn diện JPA cùng lập trình viên đang làm việc thực tế - Từ ngữ cảnh bền vững đến các mẫu hình thực tiễn
Khóa học và tài liệu này không nằm trong thử thách, việc học cũng không bắt buộc. Chỉ chọn khi bạn còn thiếu kiến thức ở một lĩnh vực nào đó trong bài đánh giá đầu vào hoặc cần củng cố khái niệm.
Bất kể có đăng ký trên Inflearn hay không, hãy kiểm tra trạng thái tuyển sinh của khóa hiện tại bằng nút “Kiểm tra tuyển sinh·tham gia” ở trên. Khi đăng nhập bằng Kakao trên Dingco, bạn sẽ được giữ chỗ; sau khi hoàn tất tất cả các kết nối, bạn đã sẵn sàng tham gia.
Trên trang kiểm tra tuyển sinh và tham gia Dingco, hãy chọn khóa hiện tại; khi đăng nhập bằng Kakao, tư cách thành viên thử thách sẽ được tạo ngay và bạn sẽ giữ được chỗ.
Sau khi vượt qua bài đánh giá đầu vào theo từng khóa, bước kết nối GitHub sẽ được mở.
Nếu kết nối GitHub trước, việc kiểm tra quyền tổ chức và chuẩn bị kho lưu trữ private dùng cho thử nghiệm JPA sẽ được tự động lên lịch.
Khi kết nối Discord, quyền truy cập vào danh mục riêng dành cho thử thách JPA cùng các kênh thông báo, tài liệu tham khảo, câu hỏi và thảo luận tự do sẽ được thiết lập.
Tạo nhánh submit/<nhiệm vụ> trên trang web, push mã thử nghiệm và log SQL, sau đó gửi PR chỉ với một lần nhấn nút.
Các commit mới nhất vượt qua kiểm tra tự động và đánh giá AI sẽ được Dingco tự động hợp nhất, sau đó cùng nhau ăn mừng trong kênh tự do. Trong Discord của crew, mọi người cùng chia sẻ câu hỏi và tiến độ; các bài review chính thức sẽ ưu tiên mở PR đã vượt qua của cùng crew, nếu không có thì tiếp tục với PR của crew khác cùng khóa. Bảng điểm sẽ được cập nhật tạm thời hằng tuần và được xác nhận cuối cùng sau khi đóng đợt review tích lũy cuối cùng.
Quyền đọc của những người cùng khóa Kho lưu trữ cá nhân được duy trì ở chế độ riêng tư và những người tham gia cùng khóa chỉ có thể tham khảo ở chế độ chỉ đọc sau khi kết quả theo tuần được công khai. Quyền ghi chỉ được cấp cho kho lưu trữ của chính người đó. Mỗi crew thường có 5–6 người và danh sách thành viên sẽ được ẩn cho đến trước thời điểm công khai. Bảng điểm chi tiết sẽ không được công khai; sau khi điểm cuối cùng được chốt, chỉ những crew chiến thắng đã đồng ý mới được giới thiệu trong Hall of Fame, cùng huy hiệu GitHub và tên công khai. Đăng ký tham gia sẽ kết thúc vào 19:00 thứ Tư của tuần bắt đầu. Với các track có bài chẩn đoán trước, người tham gia phải vượt qua bài này trước cùng thời điểm; danh sách crew và kênh Discord riêng sẽ được công khai lúc 20:00. Buổi bắt đầu chính thức và thời điểm công khai nhiệm vụ tuần 1 đều diễn ra lúc 21:00 cùng ngày; sau đó, nhiệm vụ mới sẽ được mở vào 21:00 thứ Tư hằng tuần và hạn nộp là 21:00 thứ Ba tuần kế tiếp. Không nhất thiết phải thực hiện review chính thức ngay trong mỗi tuần, nhưng phải hoàn thành số lượng review cần thiết dựa trên các tuần khác nhau trước 21:00 Chủ nhật sau tuần cuối cùng. Bài tập tuần 1, kho lưu trữ cá nhân và nhánh nhiệm vụ có thể được chuẩn bị trước, còn nút gửi PR sẽ tự động được kích hoạt sau khi kênh crew của bạn hoàn tất việc chuẩn bị. Những người tham gia chưa hoàn tất việc liên kết GitHub·Discord vẫn sẽ được giữ nguyên crew đã được phân công.
ĐÁNH GIÁ MỨC ĐỘ PHÙ HỢP
Phù hợp với những người này, và không phù hợp với những người này
Khuyến nghị cho những người phù hợp nhu cầu này
Những người có thể xây dựng CRUD bằng JPA nhưng lo ngại về các câu lệnh SQL không 예상 trước được
Những người muốn hệ thống hóa N+1, cascade, save/merge bằng mã tái hiện thay vì chỉ nói suông
Dành cho những người muốn rút ra các lựa chọn trong thực tế và cách giải thích khi phỏng vấn từ cùng một bằng chứng
Không khuyến khích大小规律
Hoàn toàn chưa có kinh nghiệm lưu và truy vấn entity bằng Spring Data JPA
Không khuyến khích những người chỉ muốn nhận các mẫu đáp án mà không có log SQL và bài kiểm thử hồi quy.
HOÀN THÀNH
완 thành tiêu chí hoàn thành trước khi bắt đầu.
Trong 5 tuần, nộp đầy đủ 5 PR nhiệm vụ tích hợp theo từng tuần.
Nộp review chính thức cho các PR đạt yêu cầu của 4 tuần khác nhau.
Chuẩn bị trước khi bắt đầu
Bạn cần có kinh nghiệm sử dụng entity và Repository trong dự án Spring Boot.
Mỗi tuần, bạn cần dành khoảng 5–7 giờ để tham gia thử nghiệm, so sánh log và chỉnh sửa PR.
FAQ
Thắc mắc được hỏi nhiều nhất trước khi tham gia
Đây có phải là khóa học giống với bootcamp 10 tuần hiện tại không?
Không. Thử thách này là một lộ trình riêng, hoàn thành một môn học trong 5 tuần. Chỉ khi cần một dự án dài hơn hoặc chương trình tập trung vào việc làm thì mới tiếp tục với bootcamp 10 tuần.
Có cung cấp cả bài giảng hoặc giáo trình không?
Không. Challenge cung cấp bài tập theo từng tuần, repository thực hành private, tiêu chí nộp bài và quy trình review. Các bài giảng liên quan là nội dung học trước tùy chọn có thể mua riêng, không bắt buộc phải tham gia.
Có thể nộp bài trên trang web hoặc dán liên kết không?
Kết quả nộp bài chỉ được tiếp nhận dưới dạng PR trên GitHub. Tuy nhiên, việc chuẩn bị repository, branch, PR và xem đánh giá có thể dễ dàng thực hiện thông qua các nút trên trang chủ Dinko.
Trên Discord sẽ công khai những gì?
Trên Discord, chúng tôi không đăng bài đánh giá chi tiết cho từng cá nhân mà chỉ chia sẻ bản tóm tắt hằng tuần và các thông báo vận hành. Kênh chung của thử thách JPA khóa 2 là không gian dành cho tài liệu đọc, câu hỏi, trò chuyện tự do và hướng dẫn vận hành.
GHI CHÚ CỦA NHÀ SÁNG TẠO
Thời đại AI, lập trình viên mới vào nghề nên học gì?
Bạn có thể xem trước trong video về tiêu chí thực hiện và kiểm chứng vấn đề này như thế nào.