ফ্রন্ট-এন্ড বনাম ব্যাক-এন্ড বনাম ডেটাবেস — তিনটি স্তর
এই পাঠে যা শিখবেন
- ফ্রন্ট-এন্ড, ব্যাক-এন্ড ও ডেটাবেস আসলে কোথায় (কোন মেশিনে/প্রসেসে) চলে
- প্রতিটি স্তর কী করতে পারে এবং কী করতে পারে না -- বিশেষত ফ্রন্ট-এন্ডের সীমাবদ্ধতা
- কেন "ফ্রন্ট-এন্ড সরাসরি ডেটাবেস স্পর্শ করা" একটি বিপজ্জনক এন্টি-প্যাটার্ন
- Python দিয়ে দুটো কল চেইন সিমুলেট করে এন্টি-প্যাটার্ন বনাম সঠিক প্যাটার্নের বাস্তব পার্থক্য যাচাই করা
১ · তিনটি স্তর আসলে কোথায় চলে
L01-এ আমরা তিনটি স্তরের একটি সংক্ষিপ্ত পরিচয় পেয়েছি। এখন প্রশ্নটা আরও নির্দিষ্টভাবে দেখা যাক -- থ্রি-টায়ার আর্কিটেকচারThree-Tier Architectureএকটি অ্যাপ্লিকেশনকে তিনটি পৃথক স্তরে ভাগ করার প্যাটার্ন -- প্রেজেন্টেশন (ফ্রন্ট-এন্ড), লজিক (ব্যাক-এন্ড), ও ডেটা (ডেটাবেস) -- যাতে প্রতিটি স্তর স্বাধীনভাবে পরিবর্তন বা স্কেল করা যায়।-এ প্রতিটি স্তর আসলে কোন মেশিন বা প্রসেসে চলে?
- ফ্রন্ট-এন্ড ব্যবহারকারীর নিজের ডিভাইসে -- তার ব্রাউজারে -- চলে। এই কোড (HTML/CSS/JavaScript) সার্ভার থেকে ডাউনলোড হয়ে ব্যবহারকারীর মেশিনে এক্সিকিউট হয়, তাই এটি একটি অবিশ্বস্ত পরিবেশ -- যেকেউ ব্রাউজারের ডেভেলপার টুলস খুলে সোর্স কোড দেখতে বা পরিবর্তন করতে পারে।
- ব্যাক-এন্ড একটি সার্ভারে চলে -- সাধারণত একটি ডেটা সেন্টার বা ক্লাউড ইনস্ট্যান্সে, যা ডেভেলপারের নিয়ন্ত্রণে থাকে, ব্যবহারকারীর নয়। এটি একটি বিশ্বস্ত পরিবেশ -- এখানে গোপন কী, ক্রেডেনশিয়াল, ও ব্যবসায়িক লজিক নিরাপদে রাখা যায়।
- ডেটাবেস সাধারণত একটি পৃথক সার্ভারে (বা ম্যানেজড ডেটাবেস সার্ভিসে) চলে, যা শুধুমাত্র
ব্যাক-এন্ড থেকেই সংযোগযোগ্য -- সরাসরি ইন্টারনেট থেকে নয়। ডেটাবেস স্তরে ডেটা কীভাবে টেবিলে সংরক্ষিত ও
কোয়েরি করা হয় তার খুঁটিনাটি এই কোর্সের ORM মডিউলে (M7) ও সহোদর
../dbms-sql/কোর্সে কভার করা হয়েছে -- এখানে আমরা শুধু এই স্তরটি কোথায় বসে ও কী দায়িত্ব পালন করে তা নিয়ে আলোচনা করছি।
২ · প্রতিটি স্তর কী করতে পারে, কী পারে না
"কোথায় চলে" জানার পর এখন দেখা যাক এই অবস্থানের কারণে প্রতিটি স্তরের বাস্তব ক্ষমতা ও সীমাবদ্ধতা কী।
পারে: UI রেন্ডার, ইনপুট নেওয়া, API কল করা।
পারে না: ডেটাবেসে সরাসরি কানেক্ট করা, গোপন কী নিরাপদে রাখা (কোড ইন্সপেক্টেবল), বিশ্বাসযোগ্য ভ্যালিডেশন করা।
পারে: বিজনেস লজিক চালানো, ডেটাবেসে নিরাপদে কানেক্ট করা, ইনপুট ভ্যালিডেট/অথরাইজ করা।
পারে না: ব্যবহারকারীর জন্য UI সরাসরি রেন্ডার করা -- শুধু ডেটা/রেসপন্স ফেরত পাঠাতে পারে।
পারে: ডেটা সংরক্ষণ, কনস্ট্রেইন্ট/ইনডেক্স দিয়ে ইন্টিগ্রিটি নিশ্চিত করা, কোয়েরি করা।
পারে না: নিজে থেকে বিজনেস লজিক বা "কে অনুমতিপ্রাপ্ত" সিদ্ধান্ত নেওয়া -- এটা ব্যাক-এন্ডের দায়িত্ব।
৩ · কেন সরাসরি ডেটাবেস স্পর্শ করা বিপজ্জনক
যদি ফ্রন্ট-এন্ড কোনোভাবে সরাসরি ডেটাবেসে ডেটা লিখতে পারত (যেমন ডেটাবেসের ক্রেডেনশিয়াল ফ্রন্ট-এন্ড কোডে এমবেড করে), তাহলে API স্তরের ভ্যালিডেশন ও অথোরাইজেশন সম্পূর্ণ বাদ পড়ে যেত -- যেকেউ, যেকোনো মান, সরাসরি ডেটাবেসে পাঠাতে পারত। নিচের কোড সেলে এই ঝুঁকি বাস্তব Python কোড দিয়ে দেখানো হয়েছে।
৪ · কোড সেল -- এন্টি-প্যাটার্ন বনাম সঠিক প্যাটার্ন
দুটো কল চেইন সিমুলেট করা হয়েছে -- একই ঋণাত্মক (invalid) ব্যালেন্স আপডেট পাঠানো হচ্ছে দুইভাবে: প্রথমে
সরাসরি frontend_direct_update() থেকে ডেটাবেসে (এন্টি-প্যাটার্ন), তারপর
frontend_calls_api() থেকে API হয়ে ডেটাবেসে (সঠিক প্যাটার্ন)। প্রতিটি কল call_log-এ
রেকর্ড হয়, যাতে কল চেইনের প্রতিটি হপ দেখা যায়।
# "ডেটাবেস" -- একটি ইন-মেমরি টেবিল, সত্যিকারের DB-র বদলে
database = {
1: {"id": 1, "name": "Rina", "balance": 500},
}
call_log = []
def db_update_balance(user_id, new_balance):
call_log.append("DATABASE.update_balance")
database[user_id]["balance"] = new_balance
return database[user_id]
# --- এন্টি-প্যাটার্ন: ফ্রন্ট-এন্ড সরাসরি ডেটাবেস ফাংশন কল করছে ---
def frontend_direct_update(user_id, new_balance):
call_log.append("FRONTEND.direct_update")
# কোনো ভ্যালিডেশন নেই -- সরাসরি db_update_balance কল হচ্ছে
return db_update_balance(user_id, new_balance)
# --- সঠিক প্যাটার্ন: ফ্রন্ট-এন্ড -> API -> ডেটাবেস ---
def api_update_balance(user_id, new_balance):
call_log.append("API.update_balance")
if new_balance < 0:
print(" API ভ্যালিডেশন ব্যর্থ -- ঋণাত্মক ব্যালেন্স প্রত্যাখ্যান, DB-তে পৌঁছায়নি")
return None
return db_update_balance(user_id, new_balance)
def frontend_calls_api(user_id, new_balance):
call_log.append("FRONTEND.calls_api")
return api_update_balance(user_id, new_balance)
print("--- দৃশ্য ১: এন্টি-প্যাটার্ন (ফ্রন্ট-এন্ড সরাসরি ডেটাবেস স্পর্শ করছে) ---")
call_log.clear()
frontend_direct_update(1, -999)
print("কল চেইন:", " -> ".join(call_log))
print(f"মোট হপ: {len(call_log)}")
print(f"ডেটাবেসে সংরক্ষিত ব্যালেন্স: {database[1]['balance']} (কোনো ভ্যালিডেশন হয়নি -- ঋণাত্মক মান ঢুকে গেছে!)")
print("\n--- দৃশ্য ২: সঠিক প্যাটার্ন, একই ঋণাত্মক ইনপুট দিয়ে ---")
database[1]["balance"] = 500 # রিসেট
call_log.clear()
frontend_calls_api(1, -999)
print("কল চেইন:", " -> ".join(call_log))
print(f"মোট হপ: {len(call_log)}")
print(f"ডেটাবেসে সংরক্ষিত ব্যালেন্স: {database[1]['balance']} (ভ্যালিডেশন লেয়ার নেগেটিভ মান আটকে দিয়েছে, DB অপরিবর্তিত)")
print("\n--- দৃশ্য ৩: সঠিক প্যাটার্ন, বৈধ ইনপুট দিয়ে ---")
call_log.clear()
frontend_calls_api(1, 750)
print("কল চেইন:", " -> ".join(call_log))
print(f"মোট হপ: {len(call_log)}")
print(f"ডেটাবেসে সংরক্ষিত ব্যালেন্স: {database[1]['balance']}")
ফ্রন্ট-এন্ড, ব্যাক-এন্ড ও ডেটাবেস আলাদা পরিবেশে চলে বলেই তাদের দায়িত্বও আলাদা -- ফ্রন্ট-এন্ড অবিশ্বস্ত, তাই তার কাছে সংবেদনশীল সিদ্ধান্তের ক্ষমতা দেওয়া যায় না। ব্যাক-এন্ড/API স্তর সবসময় ফ্রন্ট-এন্ড ও ডেটাবেসের মাঝে দাঁড়িয়ে ভ্যালিডেশন ও অথোরাইজেশনের গেটকিপার হিসেবে কাজ করে। এই তিন-স্তর বিভাজনই M2-এর MVC/MVVM ও M6-এর REST API ডিজাইনের ভিত্তি তৈরি করে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন -- তারপর "→ উত্তর" চাপুন।
প্র ০১ একটি মোবাইল অ্যাপ যদি সরাসরি একটি ক্লাউড ডেটাবেস SDK ব্যবহার করে (যেমন কিছু "Backend-as-a-Service" প্রোডাক্টে হয়), তাহলে কি এই পাঠের নিয়ম ভাঙা হচ্ছে?
সরাসরি দেখতে "এন্টি-প্যাটার্ন" মনে হলেও, ভালো Backend-as-a-Service প্রোডাক্টগুলো (যেমন Firebase) আসলে ডেটাবেসের সামনে সার্ভার-সাইড সিকিউরিটি রুলস নামের একটি ভ্যালিডেশন/অথোরাইজেশন স্তর রাখে, যা কার্যত API স্তরের কাজই করে -- শুধু কোড আলাদাভাবে না লিখে ডিক্লারেটিভ নিয়ম হিসেবে লেখা হয়। অর্থাৎ "ফ্রন্ট-এন্ড → ভ্যালিডেশন লেয়ার → ডেটা" কাঠামোটা এখনো বজায় থাকে, শুধু ভ্যালিডেশন লেয়ারটা ভিন্নভাবে বাস্তবায়িত হয়।
প্র ০২
উপরের কোডে api_update_balance ঋণাত্মক মান প্রত্যাখ্যান করলেও call_log-এ এন্ট্রি যোগ হয় কেন -- সেটা কি ব্যর্থ কল নয়?
call_log-এ এন্ট্রি যোগ হয় কারণ api_update_balance ফাংশনটি সত্যিই কল হয়েছে ও
চালু হয়েছে -- এটি রিকোয়েস্ট গ্রহণ করেছে এবং সিদ্ধান্ত নিয়েছে (প্রত্যাখ্যান করার সিদ্ধান্ত)। "ব্যর্থ" মানে
এই নয় যে ফাংশনটি কল হয়নি -- বরং এর মানে ফাংশনটি সঠিকভাবে তার কাজ (ভ্যালিডেট করা) করেছে এবং পরের হপে
(db_update_balance) না গিয়ে থেমে গেছে। এই থেমে যাওয়াটাই দেখায় ভ্যালিডেশন লেয়ার কাজ করছে।
প্র ০৩ ফ্রন্ট-এন্ড কি কখনোই ডেটাবেসের সাথে সরাসরি কোনো সম্পর্ক রাখতে পারে না?
ফ্রন্ট-এন্ড ডেটাবেস *থেকে আসা ডেটা* দেখতে পারে (যেমন API রেসপন্সের মাধ্যমে), কিন্তু কখনোই সরাসরি ডেটাবেস *কানেকশন* বা *ক্রেডেনশিয়াল* রাখতে পারে না। "ডেটা দেখা" ও "ডেটাবেসে সরাসরি কানেক্ট করা"-র মধ্যে পার্থক্যটাই এই পাঠের মূল বিষয় -- API সবসময় মাঝে থেকে কী দেখানো যাবে ও কী পরিবর্তন করা যাবে তা নিয়ন্ত্রণ করে।
অনুশীলন
-
চিন্তা করুন: একটি ই-কমার্স সাইটে "প্রোডাক্টের দাম" ফ্রন্ট-এন্ড থেকে সরাসরি ডেটাবেসে
পাঠানো হলে (এন্টি-প্যাটার্নে) কী ধরনের বাস্তব ক্ষতি হতে পারে?
যদি ফ্রন্ট-এন্ড সরাসরি "এই প্রোডাক্টের দাম X টাকা" ডেটাবেসে লিখতে পারত, তাহলে যেকোনো ব্যবহারকারী ব্রাউজারের ডেভেলপার টুলস দিয়ে সেই রিকোয়েস্ট পরিবর্তন করে দাম ১ টাকা করে দিতে পারত -- একটি সরাসরি আর্থিক ক্ষতি। সঠিক প্যাটার্নে API স্তর যাচাই করে অনুরোধকারীর আসলেই দাম পরিবর্তনের অনুমতি (অ্যাডমিন রোল) আছে কি না, এবং শুধু অনুমোদিত ব্যবহারকারীর অনুরোধই ডেটাবেস পর্যন্ত পৌঁছায়।
-
পরীক্ষা করুন: উপরের কোড সেলে
api_update_balance-এ আরেকটি ভ্যালিডেশন যোগ করুন --new_balance১,০০,০০০-এর বেশি হলেও প্রত্যাখ্যান করুন (একটি সন্দেহজনকভাবে বড় মান হিসেবে ধরে), তারপর দৃশ্য ৩-এ750-এর বদলে500000দিয়ে চালিয়ে দেখুন এটি এখন আটকানো হয় কি না।if new_balance > 100000: ... return Noneশর্তটি যোগ করার পরfrontend_calls_api(1, 500000)কল করলেapi_update_balanceএই নতুন শর্তে আটকে যাবে এবংdb_update_balanceপর্যন্ত পৌঁছাবে না --call_log-এ শুধুFRONTEND.calls_apiওAPI.update_balanceথাকবে (২টি হপ), ডেটাবেসের ব্যালেন্স অপরিবর্তিত থাকবে। এটাই দেখায় API স্তরে যত বেশি ভ্যালিডেশন নিয়ম যোগ করা হয়, ডেটাবেস তত বেশি সুরক্ষিত থাকে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৮টি পাঠ আর্কিটেকচার প্যাটার্ন, ফ্রন্ট-এন্ড/ব্যাক-এন্ড ফ্রেমওয়ার্ক ফান্ডামেন্টাল, স্টেট ম্যানেজমেন্ট, REST API, ORM, অথেন্টিকেশন, রেন্ডারিং স্ট্র্যাটেজি ও ডিপ্লয়মেন্ট -- বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
- Database Management Systems কোর্স সহোদর কোর্স ডেটাবেস স্তরে সরাসরি কীভাবে ডেটা সংরক্ষণ ও কোয়েরি করা হয় তার ভিত্তি সেই কোর্সে তৈরি হয়েছে; এই কোর্স সেটার উপর API স্তর যোগ করে দেখায় কীভাবে সেই স্তরে নিরাপদে পৌঁছাতে হয়।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics ও Full-Stack Web Frameworks -- সব এক জায়গায়।