পাঠ ০৩ · ৫৮-এর মধ্যে · মডিউল ১
Home / Courses / Full-Stack Web Frameworks / তিনটি স্তর

ফ্রন্ট-এন্ড বনাম ব্যাক-এন্ড বনাম ডেটাবেস — তিনটি স্তর

Front-end vs back-end vs database — the three layers
৮ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ফ্রন্ট-এন্ড, ব্যাক-এন্ড ও ডেটাবেস আসলে কোথায় (কোন মেশিনে/প্রসেসে) চলে
  • প্রতিটি স্তর কী করতে পারে এবং কী করতে পারে না -- বিশেষত ফ্রন্ট-এন্ডের সীমাবদ্ধতা
  • কেন "ফ্রন্ট-এন্ড সরাসরি ডেটাবেস স্পর্শ করা" একটি বিপজ্জনক এন্টি-প্যাটার্ন
  • Python দিয়ে দুটো কল চেইন সিমুলেট করে এন্টি-প্যাটার্ন বনাম সঠিক প্যাটার্নের বাস্তব পার্থক্য যাচাই করা

১ · তিনটি স্তর আসলে কোথায় চলে

L01-এ আমরা তিনটি স্তরের একটি সংক্ষিপ্ত পরিচয় পেয়েছি। এখন প্রশ্নটা আরও নির্দিষ্টভাবে দেখা যাক -- থ্রি-টায়ার আর্কিটেকচারThree-Tier Architectureএকটি অ্যাপ্লিকেশনকে তিনটি পৃথক স্তরে ভাগ করার প্যাটার্ন -- প্রেজেন্টেশন (ফ্রন্ট-এন্ড), লজিক (ব্যাক-এন্ড), ও ডেটা (ডেটাবেস) -- যাতে প্রতিটি স্তর স্বাধীনভাবে পরিবর্তন বা স্কেল করা যায়।-এ প্রতিটি স্তর আসলে কোন মেশিন বা প্রসেসে চলে?

  • ফ্রন্ট-এন্ড ব্যবহারকারীর নিজের ডিভাইসে -- তার ব্রাউজারে -- চলে। এই কোড (HTML/CSS/JavaScript) সার্ভার থেকে ডাউনলোড হয়ে ব্যবহারকারীর মেশিনে এক্সিকিউট হয়, তাই এটি একটি অবিশ্বস্ত পরিবেশ -- যেকেউ ব্রাউজারের ডেভেলপার টুলস খুলে সোর্স কোড দেখতে বা পরিবর্তন করতে পারে।
  • ব্যাক-এন্ড একটি সার্ভারে চলে -- সাধারণত একটি ডেটা সেন্টার বা ক্লাউড ইনস্ট্যান্সে, যা ডেভেলপারের নিয়ন্ত্রণে থাকে, ব্যবহারকারীর নয়। এটি একটি বিশ্বস্ত পরিবেশ -- এখানে গোপন কী, ক্রেডেনশিয়াল, ও ব্যবসায়িক লজিক নিরাপদে রাখা যায়।
  • ডেটাবেস সাধারণত একটি পৃথক সার্ভারে (বা ম্যানেজড ডেটাবেস সার্ভিসে) চলে, যা শুধুমাত্র ব্যাক-এন্ড থেকেই সংযোগযোগ্য -- সরাসরি ইন্টারনেট থেকে নয়। ডেটাবেস স্তরে ডেটা কীভাবে টেবিলে সংরক্ষিত ও কোয়েরি করা হয় তার খুঁটিনাটি এই কোর্সের ORM মডিউলে (M7) ও সহোদর ../dbms-sql/ কোর্সে কভার করা হয়েছে -- এখানে আমরা শুধু এই স্তরটি কোথায় বসে ও কী দায়িত্ব পালন করে তা নিয়ে আলোচনা করছি।
ফ্রন্ট-এন্ড ব্রাউজারে চলে ব্যাক-এন্ড / API সার্ভারে চলে, ভ্যালিডেট করে ডেটাবেস পৃথক DB সার্ভারে চলে ✕ ফ্রন্ট-এন্ড থেকে ডেটাবেসে সরাসরি কোনো পথ নেই -- সবসময় API-এর মধ্য দিয়ে যেতে হয়
ফ্রন্ট-এন্ড কখনো সরাসরি ডেটাবেসের সাথে কথা বলে না -- ব্যাক-এন্ড/API স্তর সবসময় মাঝে থেকে ভ্যালিডেশন, অথোরাইজেশন ও বিজনেস লজিক প্রয়োগ করে।

২ · প্রতিটি স্তর কী করতে পারে, কী পারে না

"কোথায় চলে" জানার পর এখন দেখা যাক এই অবস্থানের কারণে প্রতিটি স্তরের বাস্তব ক্ষমতা ও সীমাবদ্ধতা কী।

ফ্রন্ট-এন্ড
পারে: UI রেন্ডার, ইনপুট নেওয়া, API কল করা।
পারে না: ডেটাবেসে সরাসরি কানেক্ট করা, গোপন কী নিরাপদে রাখা (কোড ইন্সপেক্টেবল), বিশ্বাসযোগ্য ভ্যালিডেশন করা।
ব্যাক-এন্ড
পারে: বিজনেস লজিক চালানো, ডেটাবেসে নিরাপদে কানেক্ট করা, ইনপুট ভ্যালিডেট/অথরাইজ করা।
পারে না: ব্যবহারকারীর জন্য UI সরাসরি রেন্ডার করা -- শুধু ডেটা/রেসপন্স ফেরত পাঠাতে পারে।
ডেটাবেস
পারে: ডেটা সংরক্ষণ, কনস্ট্রেইন্ট/ইনডেক্স দিয়ে ইন্টিগ্রিটি নিশ্চিত করা, কোয়েরি করা।
পারে না: নিজে থেকে বিজনেস লজিক বা "কে অনুমতিপ্রাপ্ত" সিদ্ধান্ত নেওয়া -- এটা ব্যাক-এন্ডের দায়িত্ব।
লক্ষ্য করুন ফ্রন্ট-এন্ডের ক্লায়েন্ট-সাইড ভ্যালিডেশন (যেমন "এই ইনপুট বক্স খালি রাখা যাবে না") শুধুমাত্র UX-এর জন্য উপকারী -- এটি নিরাপত্তা নয়। কেউ ব্রাউজারের ডেভেলপার টুলস দিয়ে সরাসরি একটি ভুল রিকোয়েস্ট পাঠাতে পারে, ফ্রন্ট-এন্ডের ভ্যালিডেশন সম্পূর্ণ বাইপাস করে। তাই প্রতিটি ভ্যালিডেশন ব্যাক-এন্ডেও আবার করতে হয় -- ব্যাক-এন্ডই একমাত্র বিশ্বাসযোগ্য জায়গা।

৩ · কেন সরাসরি ডেটাবেস স্পর্শ করা বিপজ্জনক

যদি ফ্রন্ট-এন্ড কোনোভাবে সরাসরি ডেটাবেসে ডেটা লিখতে পারত (যেমন ডেটাবেসের ক্রেডেনশিয়াল ফ্রন্ট-এন্ড কোডে এমবেড করে), তাহলে API স্তরের ভ্যালিডেশন ও অথোরাইজেশন সম্পূর্ণ বাদ পড়ে যেত -- যেকেউ, যেকোনো মান, সরাসরি ডেটাবেসে পাঠাতে পারত। নিচের কোড সেলে এই ঝুঁকি বাস্তব Python কোড দিয়ে দেখানো হয়েছে।

৪ · কোড সেল -- এন্টি-প্যাটার্ন বনাম সঠিক প্যাটার্ন

দুটো কল চেইন সিমুলেট করা হয়েছে -- একই ঋণাত্মক (invalid) ব্যালেন্স আপডেট পাঠানো হচ্ছে দুইভাবে: প্রথমে সরাসরি frontend_direct_update() থেকে ডেটাবেসে (এন্টি-প্যাটার্ন), তারপর frontend_calls_api() থেকে API হয়ে ডেটাবেসে (সঠিক প্যাটার্ন)। প্রতিটি কল call_log-এ রেকর্ড হয়, যাতে কল চেইনের প্রতিটি হপ দেখা যায়।

Python
# "ডেটাবেস" -- একটি ইন-মেমরি টেবিল, সত্যিকারের 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-এর ভ্যালিডেশন, যা ডেটাবেস পর্যন্ত পৌঁছানোর আগেই অনুরোধটি আটকে দেয়। দৃশ্য ৩ দেখায় বৈধ ইনপুটে সঠিক প্যাটার্ন ঠিকই ডেটাবেস পর্যন্ত পৌঁছায় (৩টি হপ) -- সঠিক প্যাটার্ন ভুল ডেটা আটকায়, ঠিক ডেটা আটকায় না।
মূল কথা · Key takeaway

ফ্রন্ট-এন্ড, ব্যাক-এন্ড ও ডেটাবেস আলাদা পরিবেশে চলে বলেই তাদের দায়িত্বও আলাদা -- ফ্রন্ট-এন্ড অবিশ্বস্ত, তাই তার কাছে সংবেদনশীল সিদ্ধান্তের ক্ষমতা দেওয়া যায় না। ব্যাক-এন্ড/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 সবসময় মাঝে থেকে কী দেখানো যাবে ও কী পরিবর্তন করা যাবে তা নিয়ন্ত্রণ করে।

অনুশীলন

  1. চিন্তা করুন: একটি ই-কমার্স সাইটে "প্রোডাক্টের দাম" ফ্রন্ট-এন্ড থেকে সরাসরি ডেটাবেসে পাঠানো হলে (এন্টি-প্যাটার্নে) কী ধরনের বাস্তব ক্ষতি হতে পারে?

    যদি ফ্রন্ট-এন্ড সরাসরি "এই প্রোডাক্টের দাম X টাকা" ডেটাবেসে লিখতে পারত, তাহলে যেকোনো ব্যবহারকারী ব্রাউজারের ডেভেলপার টুলস দিয়ে সেই রিকোয়েস্ট পরিবর্তন করে দাম ১ টাকা করে দিতে পারত -- একটি সরাসরি আর্থিক ক্ষতি। সঠিক প্যাটার্নে API স্তর যাচাই করে অনুরোধকারীর আসলেই দাম পরিবর্তনের অনুমতি (অ্যাডমিন রোল) আছে কি না, এবং শুধু অনুমোদিত ব্যবহারকারীর অনুরোধই ডেটাবেস পর্যন্ত পৌঁছায়।

  2. পরীক্ষা করুন: উপরের কোড সেলে 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 -- সব এক জায়গায়।
আগের পাঠ
ক্লায়েন্ট-সার্ভার মডেল ও HTTP রিকোয়েস্ট-রেসপন্স সাইকেল