SP, EntityFramework, Dapper, SmartSQL 을 비교하는 짧은 보고서를 작성하려고 한다.
이 보고서를 작성할 때, 각 방법의 실제 사용 코드 예시를 보여주면서 진행하고자 한다.
그렇다면 내가 준비해야 할 게 어떤 게 있는지 먼저 생각해보자.
일단 나는 select 문을 사용하되 메인 테이블과 서브 테이블을 join해서 조회하는 방식을 보여줄 것이다.
이렇게 하기 위해서는 메인 테이블과 서브 테이블의 정의가 일단 필요하다.
그리고 각 테이블에 들어가있는, 값을 보여줄 수 있게 실제 데이터가 필요하다.
user_id 를 공통적으로 가지고 있는 메인테이블 정의와 서브 테이블 정의가 필요하다.
메인 테이블 정의를 어떻게 할까?
서브 테이블 정의를 어떻게 할까?
이것에 대해서 main table 과 sub table들을 간단히 설계해달라고 부탁했다.
Customers 테이블 (고객 정보)
CREATE TABLE Customers (
CustomerID INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50),
Email VARCHAR(100),
Phone VARCHAR(15)
);
Orders 테이블 (주문 정보)
CREATE TABLE Orders (
OrderID INT PRIMARY KEY,
CustomerID INT,
OrderDate DATETIME,
TotalAmount DECIMAL(10, 2),
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);
OrderItems 테이블 (주문 항목 정보)
CREATE TABLE OrderItems (
OrderItemID INT PRIMARY KEY,
OrderID INT,
ProductName VARCHAR(100),
Quantity INT,
Price DECIMAL(10, 2),
FOREIGN KEY (OrderID) REFERENCES Orders(OrderID)
);
Products 테이블 (제품 정보)
CREATE TABLE Products (
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Price DECIMAL(10, 2)
);
예시 설명
- Customers 테이블은 고객 정보를 저장합니다.
- Orders 테이블은 각 고객의 주문 정보를 저장하고, CustomerID를 외래키로 사용하여 Customers 테이블과 연결됩니다.
- OrderItems 테이블은 주문의 각 항목을 저장하고, OrderID를 외래키로 사용하여 Orders 테이블과 연결됩니다.
- Products 테이블은 제품 정보를 저장합니다.
CREATE (새로운 고객 추가):
INSERT INTO Customers (CustomerID, FirstName, LastName, Email, Phone)
VALUES (1, 'John', 'Doe', 'john.doe@example.com', '123-456-7890');
READ (고객과 그들의 주문 정보 조회):
SELECT c.FirstName, c.LastName, o.OrderID, o.OrderDate, o.TotalAmount
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE c.CustomerID = 1;
UPDATE (고객의 전화번호 수정):
UPDATE Customers
SET Phone = '987-654-3210'
WHERE CustomerID = 1;
DELETE (고객 삭제):
DELETE FROM Customers
WHERE CustomerID = 1;
JOIN 예시 (주문 항목과 제품 정보를 결합):
SELECT oi.OrderItemID, oi.ProductName, oi.Quantity, oi.Price, p.ProductName
FROM OrderItems oi
JOIN Products p ON oi.ProductName = p.ProductName
WHERE oi.OrderID = 101;
이 테이블들을 바탕으로 데이터 매핑 방식 비교 가능함.
총 4개 테이블이 만들어졌다고 가정한다.
그렇다면 해당 테이블들에 예시 데이터가 들어가야한다고 나는 생각한다.
예시 데이터를 삽입하는 방법은 아래와 같다.
1. Customers 테이블 예시 데이터
INSERT INTO Customers (CustomerID, FirstName, LastName, Email, Phone)
VALUES
(1, 'John', 'Doe', 'john.doe@example.com', '123-456-7890'),
(2, 'Jane', 'Smith', 'jane.smith@example.com', '987-654-3210'),
(3, 'Emily', 'Johnson', 'emily.johnson@example.com', '555-123-4567');
2. Orders 테이블 예시 데이터
INSERT INTO Orders (OrderID, CustomerID, OrderDate, TotalAmount)
VALUES
(101, 1, '2025-03-01 10:00:00', 120.50),
(102, 2, '2025-03-02 11:15:00', 75.30),
(103, 3, '2025-03-03 14:30:00', 220.00);
3. OrderItems 테이블 예시 데이터
INSERT INTO OrderItems (OrderItemID, OrderID, ProductName, Quantity, Price)
VALUES
(1, 101, 'Laptop', 1, 1000.00),
(2, 101, 'Mouse', 1, 20.50),
(3, 102, 'Smartphone', 1, 650.00),
(4, 102, 'Phone Case', 1, 25.00),
(5, 103, 'Tablet', 2, 110.00);
4. Products 테이블 예시 데이터
INSERT INTO Products (ProductID, ProductName, Price)
VALUES
(1, 'Laptop', 1000.00),
(2, 'Mouse', 20.50),
(3, 'Smartphone', 650.00),
(4, 'Phone Case', 25.00),
(5, 'Tablet', 110.00);
예시 데이터 설명
- Customers 테이블에는 세 명의 고객 데이터가 있습니다.
- Orders 테이블에는 각 고객의 주문이 있으며, 각 주문은 CustomerID를 외래키로 참조하고 있습니다.
- OrderItems 테이블에는 각 주문에 대한 항목 정보가 있으며, 주문과 연관된 제품들이 포함되어 있습니다.
- Products 테이블에는 다섯 가지 제품의 가격 정보가 있습니다
그리고 이제 이걸 MSSQL 실제 서버에 집어놓고 돌려보고 싶은데,
음 일단 탭에서는 해당 작업을 시행하기 어려움.
그리고 탭 말고도 현재 엠에스에스큐엘 서버를 내가 가지려면 적어도 노트북 환경이 되어야 한다고 생각함.
그렇다면 일단 이정도로 해놓고,
예시 코드 문을 만들어볼까 하는 생각이 듦.
예시 코드문을 짜달라고 부탁한 다음에, 해당 코드문을 내가 머리로 검증하는 것은 가능하지 않을까 하는게 지금 내 생각임.
1. Stored Procedure
먼저, Stored Procedure를 사용하여 고객과 그들의 주문 정보를 조회하는 방법을 설명합니다.
Stored Procedure 정의
CREATE PROCEDURE GetCustomerOrders
@CustomerID INT
AS
BEGIN
SELECT c.FirstName, c.LastName, o.OrderID, o.OrderDate, o.TotalAmount
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE c.CustomerID = @CustomerID;
END;
Stored Procedure 호출 예시
EXEC GetCustomerOrders @CustomerID = 1;
C# 코드에서 호출 예시
string storedProcedureName = "GetCustomerOrders";
SqlCommand command = new SqlCommand(storedProcedureName, connection)
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.Int)).Value = customerId;
SqlDataReader reader = command.ExecuteReader();
2. Entity Framework (EF Core)
Entity Framework를 사용하여 동일한 쿼리를 작성하는 방법입니다. 아래 코드는 LINQ를 사용하여 데이터베이스에서 고객과 주문 정보를 조회하는 예시입니다.
모델 클래스 정의
public class Customer
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public decimal TotalAmount { get; set; }
public int CustomerID { get; set; }
public Customer Customer { get; set; }
}
DbContext 클래스
public class ApplicationDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders { get; set; }
}
쿼리 실행
var customerOrders = context.Customers
.Where(c => c.CustomerID == 1)
.Select(c => new
{
c.FirstName,
c.LastName,
Orders = c.Orders.Select(o => new
{
o.OrderID,
o.OrderDate,
o.TotalAmount
})
})
.ToList();
3. Dapper
Dapper를 사용하여 고객과 그들의 주문 정보를 조회하는 예시입니다.
Dapper 쿼리 실행
using (var connection = new SqlConnection(connectionString))
{
var query = @"
SELECT c.FirstName, c.LastName, o.OrderID, o.OrderDate, o.TotalAmount
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE c.CustomerID = @CustomerID";
var result = connection.Query<CustomerOrder>(query, new { CustomerID = 1 }).ToList();
}
CustomerOrder 클래스 정의
public class CustomerOrder
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public decimal TotalAmount { get; set; }
}
4. SmartSQL
SmartSQL은 SQL을 XML 파일에 매핑하여 SQL 쿼리를 관리합니다. SmartSQL을 사용하여 고객과 그들의 주문 정보를 조회하는 방법입니다.
SmartSQL XML 파일 정의 (예: customer_orders.xml)
<SmartSQL>
<sql id="GetCustomerOrders">
<![CDATA[
SELECT c.FirstName, c.LastName, o.OrderID, o.OrderDate, o.TotalAmount
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE c.CustomerID = @CustomerID;
]]>
</sql>
</SmartSQL>
C# 코드에서 호출 예시
using SmartSql;
var sqlId = "GetCustomerOrders";
var parameters = new { CustomerID = 1 };
var result = smartSqlExecutor.Query<CustomerOrder>(sqlId, parameters).ToList();
CustomerOrder 클래스 정의
public class CustomerOrder
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public decimal TotalAmount { get; set; }
}
결론
- Stored Procedure는 SQL 서버에서 직접 실행할 수 있는 저장된 프로시저로, 쿼리의 재사용성 및 성능을 높일 수 있습니다.
- **Entity Framework (EF Core)**는 ORM을 통해 객체지향적으로 데이터를 다룰 수 있으며, LINQ를 사용하여 쿼리를 작성합니다.
- Dapper는 성능이 뛰어난 경량 ORM으로 SQL 쿼리를 직접 작성하고
- 실행합니다.
- SmartSQL은 SQL 쿼리를 XML 파일에 매핑하여, SQL 코드와 C# 코드 간의 분리를 유지하고, 쿼리의 관리가 용이해집니다.
일단 이정도로 하고, 어떻게 해야 이걸 검증할 수 있을지 생각해보자.
일단 그냥 머리로 검증하는 걸 생각해봤는데, 그렇게 하면 시간이 너무 오래 걸릴 것 같고 한다고 해도 내가 불안해 할 것 같음.
그렇다면,
MSSQL 서버를 만들고 해서 테스트 해보고 싶긴 함.
아니면 일단 MSSQL 테이블을 만드는 도큐먼트를 보면서 검증해보는 방법도 있다.
도큐먼트를 참조하면서 검증하려고 했는데, 괜찮은 튜토리얼 도큐먼트를 마이크로소프트 공식 가이드 사이트에서 찾지 못했다.
따라서 직접 오류 받으면서 수행해야 할 것 같다.
직접 오류 뜨면서 수행하려면, 어쨋든 직접적인 SQL Server가 필요하다.
이를 수행하는 방법으로 노트북 로컬 환경에 SQL Server를 설치해서 운영하거나, AWS에 생성해서 운영하는 방식이 있다.
그런데 중요한 점은 이 두가지 방식 다 현재 태블릿으로 수행하기엔 불편함이 크다는 점이다.
가령 AWS Console로 운영하고자 시도하였으나, AWS Console 로그인 정보 자체가 기존 노트북에 있다는 걸 깨닫고,
계속해서 로그인 실패를 5-6회 가량 반복했다.
이로인해 짜증이 적립되었다. 집에 가서 하는 게 나을 것 같다.
그렇다고 집에 가서 검증한 후에 도큐먼트를 만드는 건 비효율 적인 일이라는 생각이 들었다.
도큐먼트를 먼저 캡처를 통해서 만들어 놓은 뒤에 집가서 테스트를 수행하는 것이 더 효율적이란 생각이 들었다.
그러니까 코드는 틀릴 수 있겠지만 방식 자체에 크게 틀릴 일은 없기 때문이다.
결론에 따라 현재 도큐먼트를 4가지 방식을 비교하는 걸 작성해놓았다.