Skip to main content

๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๋ ˆ์ด์–ด ๋ฆฌํŒฉํ„ฐ๋ง

Copilot Chat์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ์—์„œ ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ์•ˆํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋” ์‰ฝ๊ฒŒ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ณ  ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋“œ ์ฝ”๋”ฉ๋œ SQL ์ฟผ๋ฆฌ์™€ ๊ธด๋ฐ€ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ์ฝ”๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์Šค์ผ€์ผ๋งํ•˜๊ฑฐ๋‚˜ ์ „ํ™˜ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ข…์ข… ๋ฐ˜๋ณต๋˜๋Š” ๋…ผ๋ฆฌ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Copilot Chat์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํ˜ธ ์ž‘์šฉ์„ ์ถ”์ƒํ™”ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ์ค‘๋ณต์„ฑ์„ ์ค„์ด๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํŒจํ„ด์ด๋‚˜ ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๊ณ„์ธต์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ SQL ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”๋œ ๋ฒ„์ „์œผ๋กœ ๋ฆฌํŒฉํ„ฐ๋งํ•˜์—ฌ ์„ฑ๋Šฅ๊ณผ ์œ ์ง€ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ํ•ญ๋ชฉ

์ด ๋ฌธ์„œ์— ์„ค๋ช…๋œ ์‘๋‹ต์€ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. Copilot Chat ์‘๋‹ต์€ ๋น„๊ฒฐ์ •์ ์ด๋ฏ€๋กœ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋œ ์‘๋‹ต๊ณผ ๋‹ค๋ฅธ ์‘๋‹ต์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ์‹œ๋‚˜๋ฆฌ์˜ค

์ด Python ์ฝ”๋“œ๋Š” SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•˜๊ณ  ์‚ฌ์šฉ์ž ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋…ผ๋ฆฌ๋ฅผ ์ถ”์ƒํ™”ํ•˜์ง€ ๋ชปํ•˜๊ณ  SQL ์‚ฝ์ž…์— ์ทจ์•ฝํ•œ ํ•˜๋“œ ์ฝ”๋“œ๋œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import sqlite3

def get_user_by_id(user_id):
    conn = sqlite3.connect('database.db')
    cursor = conn.cursor()
    cursor.execute(f"SELECT display_name FROM users WHERE id = {user_id}")
    user = cursor.fetchone()
    conn.close()
    return user

์˜ˆ์ œ ํ”„๋กฌํ”„ํŠธ 1

๋จผ์ € Copilot์—๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ์งˆ๋ฌธ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

How can I improve this code to make it safe and easier to update and expand? List possible improvements but don't show revised code.

์˜ˆ์ œ ์‘๋‹ต 1

Copilot๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์ œ์•ˆ์„ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ถ”์ƒํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SQL ์‚ฝ์ž…์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์ปจํ…์ŠคํŠธ ๊ด€๋ฆฌ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ์ œ๋Œ€๋กœ ๋‹ซํ˜€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

์˜ˆ์ œ ํ”„๋กฌํ”„ํŠธ 2

์ฒซ ๋ฒˆ์งธ ํ”„๋กฌํ”„ํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๋‹ค ๊ตฌ์ฒด์ ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Rewrite this code to make it more scalable and easier to maintain. Use a context manager. Avoid hardcoded SQL queries and tightly coupled data access code. Instead, use a repository pattern to abstract database interactions and make the code more modular and reusable. Where possible optimize the code to improve performance. Include error trapping, and make sure the code is not vulnerable to SQL injection.

์˜ˆ์ œ ์‘๋‹ต 2

Copilot๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ๊ฐ ํŠน์ • ์šฉ๋„๋กœ ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž์˜ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•œ ์˜ˆ์ œ ์ฝ”๋“œ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ œ์•ˆ๋œ ๋ณ€๊ฒฝ ๋‚ด์šฉ์€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๊ณ  ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SQL ์‚ฝ์ž…์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

# database.py
import sqlite3

class Database:
    def __init__(self, db_path):
        self.db_path = db_path

    def __enter__(self):
        self.conn = sqlite3.connect(self.db_path)
        self.cursor = self.conn.cursor()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type or exc_val or exc_tb:
            self.conn.rollback()
        else:
            self.conn.commit()
        self.conn.close()

# user_repository.py
class UserRepository:
    def __init__(self, db):
        self.db = db

    def get_user_by_id(self, user_id):
        try:
            self.db.cursor.execute("SELECT display_name FROM users WHERE id = ?", (user_id,))
            user = self.db.cursor.fetchone()
            return user
        except sqlite3.Error as e:
            print(f"An error occurred: {e}")
            return None

# main.py
from database import Database
from user_repository import UserRepository

def get_user_by_id(user_id):
    with Database('database.db') as db:
        user_repo = UserRepository(db)
        return user_repo.get_user_by_id(user_id)

# Example usage
if __name__ == "__main__":
    user = get_user_by_id(1)
    if user:
        print(user)
    else:
        print("User not found or an error occurred.")

์ˆ˜์ •๋œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์›๋ณธ์—์„œ ๊ฐœ์„ ๋ฉ๋‹ˆ๋‹ค.

  • ์ด์ œ ์ฝ”๋“œ๋Š” ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ๋ ˆ์ด์–ด๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • Database ํด๋ž˜์Šค๋Š” SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ปจํ…์ŠคํŠธ ๊ด€๋ฆฌ์ž ํ”„๋กœํ† ์ฝœ๊ณผ __exit__ ๋ฐ __enter__ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹๊ณผ ์—ฐ๊ฒฐ ๋‹ซ๊ธฐ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด ์ œ๋Œ€๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • UserRepository ํด๋ž˜์Šค๋Š” ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ ๋…ผ๋ฆฌ๋ฅผ ์บก์Аํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฟผ๋ฆฌ ๊ฐ’์€ SQL ์‚ฝ์ž…์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™”๋ฉ๋‹ˆ๋‹ค.
  • ์ฝ˜์†”์— ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ์ธ์‡„๋˜์–ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์ฐธ๊ณ  ์ž๋ฃŒ