SQLite 는 Windows 앱에 로컬로 데이터를 저장하기 위한 안정적이고 간단한 데이터베이스 솔루션을 제공합니다. 별도의 서버 설치 및 복잡한 구성이 필요한 기존 데이터베이스 시스템과 달리 SQLite는 애플리케이션 프로세스 내에서 전적으로 실행되며 사용자의 디바이스에 있는 단일 파일에 데이터를 저장합니다.
이 자습서에서는 Microsoft의 권장 데이터 액세스 라이브러리를 사용하여 SQLite를 WinUI 애플리케이션에 통합하는 방법을 보여 줍니다. 일반적인 취약성으로부터 보호하기 위해 보안 모범 사례를 따르는 동안 데이터베이스를 설정하고, 테이블을 만들고, 기본 데이터 작업을 구현하는 방법을 알아봅니다.
수행할 작업
이 자습서에서 학습할 방법은 다음과 같습니다.
- Microsoft.Data.SQLite 라이브러리에서 SQLite를 사용하도록 Windows 앱 구성
- 로컬 데이터베이스 만들기 및 초기화
- 보안 데이터 삽입 및 검색 방법 구현
- 데이터와 상호 작용하는 간단한 사용자 인터페이스 빌드
필수 조건
이 자습서를 완료하려면 다음이 필요합니다.
- WinUI 애플리케이션 개발 워크로드를 사용한 Visual Studio 2022 이상
- C# 및 XAML에 대한 기본 숙지
- 기본 데이터베이스 개념 이해
이 방법이 제공하는 주요 개선 사항
Windows 앱에서 로컬 데이터 스토리지에 SQLite를 사용하면 다음과 같은 몇 가지 이점이 있습니다.
- 간소화된 배포: 별도의 데이터베이스 서버 설치가 필요하지 않음
- 보안 강화: 데이터는 사용자의 디바이스에서 로컬로 유지됩니다.
- 성능 향상: 직접 파일 액세스로 네트워크 대기 시간 제거
- 복잡성 감소: 단일 파일 데이터베이스는 백업 및 마이그레이션을 간소화합니다.
학습할 기술은 간단한 설정 스토리지에서 복잡한 데이터 관리 시나리오에 이르기까지 구조화된 데이터를 로컬로 저장해야 하는 모든 Windows 앱에 적용됩니다.
팁 (조언)
AI 지원을 사용하여 SQLite에서 SQL 삽입 공격을 방지할 수 있습니다.
로컬 스토리지에 대한 SQLite의 이점
✔️ SQLite는 가벼우며, 독립적입니다. 다른 종속성이 없는 코드 라이브러리입니다. 구성이 필요 없습니다.
✔️ 데이터베이스 서버가 없습니다. 클라이언트와 서버가 동일한 프로세스에서 실행됩니다.
✔️ SQLite는 공용 도메인에 기반을 두고 있어 자유롭게 사용하고 앱을 통해 배포할 수 있습니다.
✔️ SQLite는 모든 플랫폼과 아키텍처에서 작동합니다.
SQLite에 대한 자세한 내용은 여기를 참조하세요.
추상화 계층 선택
Microsoft가 빌드한 Entity Framework Core 또는 오픈 소스인 SQLite 라이브러리를 사용하는 것을 권장합니다.
Entity Framework Core
EF(Entity Framework)는 도메인별 개체를 사용하여 관계형 데이터로 작업할 수 있는 개체 관계형 매퍼입니다. 다른 .NET 앱에서 데이터를 사용하기 위해 이 프레임워크를 이미 사용한 경우 WinUI 앱에서 동일한 코드를 사용할 수 있으며 연결 문자열에 대한 적절한 변경 내용으로 작동합니다.
직접 시도해 보려면 EF Core 시작을 참조하세요.
SQLite 라이브러리
Microsoft.Data.Sqlite 라이브러리는 System.Data.Common 네임스페이스에 인터페이스를 구현합니다. Microsoft는 이러한 구현 방식을 적극적으로 유지하고 있으며, 이 방식은 저수준 기본 SQLite API와 관련된 직관적인 래퍼를 제공합니다.
이 가이드의 나머지 부분에서는 이 라이브러리의 사용 방법을 안내합니다.
Microsoft.Data.SQLite 라이브러리를 사용하도록 솔루션 설정
기본 WinUI 프로젝트로 시작한 다음 SQLite NuGet 패키지를 설치합니다. 첫 번째 WinUI 프로젝트를 만드는 방법에 대한 지침은 WinUI 앱 만들기 를 참조하세요.
지원되는 모든 Windows 버전은 SQLite를 지원하므로 앱에서 SQLite 라이브러리를 패키징할 필요가 없습니다. 그 대신, Windows와 함께 설치되는 SQLite 버전을 사용할 수 있습니다. 이는 몇 가지 측면에서 도움이 됩니다.
✔️ SQLite 바이너리를 다운로드하여 애플리케이션의 일부로 패키징할 필요가 없기 때문에 애플리케이션 크기가 줄어듭니다.
✔️ SQLite에서 SQLite의 버그와 보안 취약성을 해결하는 중요한 픽스를 게시할 때 사용자에게 새 앱 버전을 푸시할 필요가 없습니다. SQLite의 Windows 버전은 Microsoft가 SQLite.org와 함께 유지 관리합니다.
✔️ SQLite의 SDK 버전이 이미 메모리에 로드될 가능성이 높기 때문에 앱 로드 시간이 더 빨라질 수 있습니다.
DataAccess라는 프로젝트에 클래스를 추가하여 시작할 예정입니다. 데이터 액세스 논리를 다른 클라이언트 코드와 공유하려는 경우 .NET 클래스 라이브러리 프로젝트를 사용하여 데이터 액세스 코드를 포함할 수 있지만 이 예에서는 사용하지 않습니다.
솔루션을 마우스 오른쪽 버튼으로 클릭한 다음, 솔루션용 NuGet 패키지 관리를 클릭합니다.
여기서 선택할 수 있습니다. Windows에 포함된 SQLite 버전을 사용할 수도 있고, 또는 특정 SQLite 버전을 사용해야 하는 이유가 있는 경우 패키지에 SQLite 라이브러리를 포함시킬 수도 있습니다. Microsoft는 Windows에 포함된 SQLite 버전을 사용할 것입니다.
찾아보기 탭을 선택하고 Microsoft.Data.SQLite 패키지를 검색한 다음 안정적인 최신 버전을 설치합니다.
SQLite 데이터베이스에서 데이터를 추가 및 검색
수행할 단계:
1️⃣ 데이터 액세스 클래스를 준비합니다.
2️⃣ SQLite 데이터베이스를 초기화합니다.
3️⃣ SQLite 데이터베이스에 데이터를 삽입합니다.
4️⃣ SQLite 데이터베이스에서 데이터를 검색합니다.
5️⃣ 기본 사용자 인터페이스를 추가합니다.
데이터 액세스 클래스 준비
프로젝트에서 DataAccess 클래스를 열고 해당 클래스를 정적으로 만듭니다.
참고
이 예제에서는 데이터 액세스 코드를 정적 클래스에 배치하지만 디자인 선택이며 완전히 선택 사항입니다.
public static class DataAccess
{
}
이 파일의 맨 위에 다음 using 구문을 추가합니다.
using Microsoft.Data.Sqlite;
using System.Collections.Generic;
SQLite 데이터베이스 초기화
SQLite 데이터베이스를 초기화하는 DataAccess 클래스에 메서드를 추가합니다.
public async static void InitializeDatabase()
{
await ApplicationData.Current.LocalFolder
.CreateFileAsync("sqliteSample.db", CreationCollisionOption.OpenIfExists);
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
string tableCommand = "CREATE TABLE IF NOT " +
"EXISTS MyTable (Primary_Key INTEGER PRIMARY KEY, " +
"Text_Entry NVARCHAR(2048) NULL)";
var createTable = new SqliteCommand(tableCommand, db);
createTable.ExecuteReader();
}
}
참고
ApplicationData 멤버를 사용하는 위의 코드는 앱 컨테이너에서 실행되는 패키지 앱에서만 작동합니다. 다른 모든 Windows 앱은 ApplicationData 클래스를 통해 멤버에 액세스해야 합니다.
이 코드는 SQLite 데이터베이스를 만들어서 애플리케이션의 로컬 데이터 저장소에 저장합니다.
이 예에서는 데이터베이스 이름을 sqlliteSample.db로 지정했지만, 인스턴스화하는 모든 SqliteConnection 개체에서 사용하기만 한다면 어떤 이름이든 상관 없습니다. 프로덕션 애플리케이션에서 데이터베이스 파일 이름과 같은 연결 정보는 하드 코딩되지 않고 App Configuration에 저장되어야 합니다(Visual Studio Connected Services를 사용하여 Azure App Configuration 추가 참조).
프로젝트의 App.xaml.cs 파일 생성자에서 클래스의 InitializeDatabase메서드DataAccess를 호출합니다. 이렇게 하면 앱이 시작될 때마다 데이터베이스가 만들어지거나 열리게 됩니다.
public App()
{
this.InitializeComponent();
DataAccess.InitializeDatabase();
}
SQLite 데이터베이스에 데이터 삽입
SQLite 데이터베이스에 데이터를 삽입하는 DataAccess 클래스에 메서드를 추가합니다. 이 코드는 SQL 삽입 공격을 방지하기 위해 쿼리에 매개 변수를 사용합니다.
public static void AddData(string inputText)
{
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
var insertCommand = new SqliteCommand();
insertCommand.Connection = db;
// Use parameterized query to prevent SQL injection attacks
insertCommand.CommandText = "INSERT INTO MyTable VALUES (NULL, @Entry);";
insertCommand.Parameters.AddWithValue("@Entry", inputText);
insertCommand.ExecuteReader();
}
}
SQLite 데이터베이스에서 데이터 검색
SQLite 데이터베이스의 테이블에서 데이터의 모든 행을 가져오는 메서드를 추가합니다.
public static List<string> GetData()
{
var entries = new List<string>();
string dbpath = Path.Combine(ApplicationData.Current.LocalFolder.Path,
"sqliteSample.db");
using (var db = new SqliteConnection($"Filename={dbpath}"))
{
db.Open();
var selectCommand = new SqliteCommand
("SELECT Text_Entry from MyTable", db);
SqliteDataReader query = selectCommand.ExecuteReader();
while (query.Read())
{
entries.Add(query.GetString(0));
}
}
return entries;
}
Read 메서드는 반환된 데이터 행을 통과합니다. 행이 남아 있으면 true을(를) 반환하고, 그렇지 않으면 false을(를) 반환합니다.
GetString 메서드는 특정 열의 값을 문자열로 반환합니다. 원하는 데이터의 0부터 시작하는 열 서수를 나타내는 정수 값을 수락합니다. GetDataTime 및 GetBoolean 같이 유사한 메서드를 사용할 수도 있습니다. 열에 포함된 데이터 유형에 따라 메서드를 선택합니다.
이 예에서는 한 열에서 모든 항목을 선택하기 때문에 서수 매개 변수가 중요하지 않습니다. 하지만 여러 열이 쿼리에 사용되는 경우 데이터를 가져올 열을 획득하려면 서수 값을 사용해야 합니다.
기본 사용자 인터페이스 추가
프로젝트의 MainWindow.xaml 파일에서 다음 XAML을 추가합니다.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBox x:Name="Input_Box"/>
<Button Click="AddData">Add</Button>
<ListView x:Name="Output">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
이 기본 사용자 인터페이스는 SQLite 데이터베이스에 추가할 문자열을 입력하는 데 사용할 수 있는 TextBox을(를) 제공합니다. 이 UI의 Button을 SQLite 데이터베이스에서 데이터를 검색하여 ListView에 표시하는 이벤트 처리기에 연결할 것입니다.
MainWindow.xaml.cs 파일에서 다음 처리기를 추가합니다. 이 메서드를 UI에 있는 Click의 Button 이벤트와 연결합니다.
private void AddData(object sender, RoutedEventArgs e)
{
DataAccess.AddData(Input_Box.Text);
Output.ItemsSource = DataAccess.GetData();
}
또한 애플리케이션이 시작될 때 기존 데이터가 로드되는지 확인하려고 합니다.
MainWindow 생성자에 코드 줄을 추가하여 GetData()를 호출합니다.
public MainWindow()
{
this.InitializeComponent();
Output.ItemsSource = DataAccess.GetData();
}
다 되었습니다. Microsoft.Data.Sqlite를 살펴보면서 SQLite 데이터베이스로 또 무엇을 할 수 있는지 알아보세요. 아래 링크를 통해 Windows 앱에서 데이터를 활용하는 다른 방법을 알아보세요.
SQL 삽입 공격 방지
이 예제의 코드는 매개 변수가 있는 쿼리를 사용하여 SQL 삽입 공격을 방지합니다. 사용자 입력을 SQL 쿼리 문자열에 연결하지 마세요. 항상 매개 변수를 사용합니다. SQL 삽입 공격을 방지하는 방법에 대한 추가 팁은 Copilot에 요청할 수 있습니다.
다음 텍스트는 Copilot에 대한 예제 프롬프트를 보여줍니다.
Can you provide some best practices to avoid SQL injection attacks when writing SQLite queries in C# code?
부조종사에는 AI가 지원되므로 놀라움과 실수가 가능합니다. 자세한 내용은 코필로트 FAQ를 참조하세요.
관련 콘텐츠
앱을 SQL Server 데이터베이스에 직접 연결
Windows 앱에서 SQL Server 데이터베이스 사용을 참조하세요.
여러 플랫폼의 여러 앱 간에 코드 공유
데스크톱과 UWP 간에 코드 공유를 참조하세요.
Azure SQL 백엔드로 마스터 세부 정보 페이지 추가
고객 주문 데이터베이스 샘플을 참조하세요.
Windows developer