콘텐츠 대표 이미지 - Entity Framework Core로 데이터베이스 마스터하기: 2025년 최신 트렌드와 실전 가이드 🚀

Entity Framework Core로 데이터베이스 마스터하기: 2025년 최신 트렌드와 실전 가이드 🚀

안녕하세요 개발자 여러분! 😎 오늘은 2025년 3월 기준 최신 Entity Framework Core(EF Core)에 대해 함께 알아볼게요. DB 다루는 게 어렵게 느껴졌던 분들, 이제 걱정 노노~! EF Core와 함께라면 데이터베이스 작업이 한결 쉬워진답니다. 실무에서 바로 써먹을 수 있는 꿀팁들 가득 준비했으니 끝까지 함께해요!

🌟 Entity Framework Core란 뭘까요?

Entity Framework Core는 마이크로소프트에서 개발한 오픈소스 ORM(Object-Relational Mapping) 프레임워크예요. 쉽게 말하면, 우리가 C# 객체로 작업하면 EF Core가 알아서 SQL 쿼리로 변환해주는 마법같은 도구랍니다! 😲

2025년 현재 EF Core 8.0이 안정화 단계에 있고, 곧 8.1 버전이 출시될 예정이에요. 최신 버전에서는 성능 개선과 함께 다양한 데이터베이스 지원이 강화되었답니다.

✨ EF Core의 주요 특징

  1. LINQ를 사용한 쿼리 작성 가능 (SQL 몰라도 OK!)
  2. 다양한 데이터베이스 지원 (SQL Server, PostgreSQL, MySQL 등)
  3. 코드 우선(Code First) 또는 데이터베이스 우선(Database First) 접근 방식
  4. 자동 마이그레이션 기능으로 DB 스키마 관리 용이
  5. 강력한 변경 추적 시스템
Entity Framework Core 작동 방식 C# 객체 public class User { public int Id { get; set; } public string Name { get; set; } } EF Core 데이터베이스 CREATE TABLE Users ( Id INT PRIMARY KEY, Name NVARCHAR(100) )

위 그림에서 볼 수 있듯이, EF Core는 C# 객체와 데이터베이스 사이의 다리 역할을 해줘요. 우리는 C# 코드만 작성하면 되고, 나머지는 EF Core가 알아서 처리한답니다! 진짜 개발자의 삶의 질이 확 올라가는 느낌이죠? ㅋㅋㅋ

🚀 시작하기: EF Core 설정 방법

먼저 EF Core를 프로젝트에 추가해볼까요? 2025년 기준으로 NuGet 패키지 관리자를 통해 쉽게 설치할 수 있어요.

📦 필요한 패키지 설치하기

dotnet add package Microsoft.EntityFrameworkCore --version 8.0.0
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 8.0.0
dotnet add package Microsoft.EntityFrameworkCore.Tools --version 8.0.0

SQL Server 말고 다른 DB를 쓰고 싶다면? 걱정 마세요! 2025년 현재 EF Core는 다양한 데이터베이스 제공자를 지원하고 있어요:

  1. PostgreSQL: Npgsql.EntityFrameworkCore.PostgreSQL
  2. MySQL: Pomelo.EntityFrameworkCore.MySql
  3. SQLite: Microsoft.EntityFrameworkCore.Sqlite
  4. Oracle: Oracle.EntityFrameworkCore
  5. Cosmos DB: Microsoft.EntityFrameworkCore.Cosmos

패키지 설치가 끝났다면, 이제 DbContext 클래스를 만들어볼까요? 이 클래스는 EF Core에서 가장 중요한 클래스로, 데이터베이스와의 모든 상호작용을 담당해요.

🔄 DbContext 클래스 만들기

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

// 엔티티 클래스 정의
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

// DbContext 클래스 정의
public class ShopContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;");
    }
}

짜잔~ 이렇게 기본 설정이 끝났어요! 😄 이제 EF Core를 사용해서 데이터베이스 작업을 시작할 수 있답니다.

💡 꿀팁: 실무에서는 연결 문자열을 하드코딩하지 말고, appsettings.json이나 환경 변수에 저장하는 것이 좋아요! 특히 재능넷 같은 플랫폼을 개발할 때는 보안에 신경 써야 하니까요.

🏗️ 코드 우선(Code First) 접근 방식

EF Core에서 가장 인기 있는 방식은 코드 우선(Code First) 접근법이에요. C# 클래스를 먼저 정의하고, 이를 기반으로 데이터베이스를 생성하는 방식이죠. 2025년에는 이 방식이 더욱 강화되어 복잡한 관계도 쉽게 표현할 수 있게 되었어요!

🧩 엔티티 클래스 정의하기

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime BirthDate { get; set; }
    
    // 관계 설정: 한 저자는 여러 책을 가질 수 있음
    public List<Book> Books { get; set; }
}

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime PublishedDate { get; set; }
    public decimal Price { get; set; }
    
    // 관계 설정: 한 책은 한 명의 저자를 가짐
    public int AuthorId { get; set; }
    public Author Author { get; set; }
}

이제 DbContext에 이 엔티티들을 추가하고, 관계를 설정해볼게요:

public class LibraryContext : DbContext
{
    public DbSet<Author> Authors { get; set; }
    public DbSet<Book> Books { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("연결 문자열");
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Fluent API를 사용한 관계 설정
        modelBuilder.Entity<Book>()
            .HasOne(b => b.Author)
            .WithMany(a => a.Books)
            .HasForeignKey(b => b.AuthorId);
    }
}

이렇게 모델을 정의했다면, 이제 마이그레이션을 통해 실제 데이터베이스에 반영해볼까요?

🔄 마이그레이션 생성 및 적용

// 마이그레이션 생성 (Package Manager Console에서)
Add-Migration InitialCreate

// 또는 .NET CLI 사용
dotnet ef migrations add InitialCreate

// 데이터베이스에 변경사항 적용
Update-Database

// 또는 .NET CLI 사용
dotnet ef database update
코드 우선(Code First) 워크플로우 1. C# 클래스 정의 public class Author { public int Id { get; set; } public string Name { get; set; } ... } 2. DbContext 설정 public class MyContext : DbContext { public DbSet<Author> Authors { get; set; } } 3. 마이그레이션 생성 Add-Migration InitialCreate 마이그레이션 파일 생성 4. DB 업데이트 Update-Database CREATE TABLE Authors ( Id INT PRIMARY KEY, Name NVARCHAR(100) )

와우! 이제 데이터베이스가 자동으로 생성되었어요. 😲 C# 코드만 작성했는데 테이블, 관계, 제약조건까지 모두 설정되었답니다. 이게 바로 EF Core의 매력이죠! ㅋㅋㅋ

💡 프로팁: 실제 프로젝트에서는 마이그레이션을 버전 관리 시스템(Git 등)에 포함하는 것이 좋아요. 팀원들과 함께 작업할 때 데이터베이스 스키마 변경을 쉽게 공유할 수 있답니다!

💾 데이터베이스 CRUD 작업

이제 EF Core를 사용해서 기본적인 CRUD(Create, Read, Update, Delete) 작업을 해볼게요. 2025년 EF Core는 더욱 직관적인 API를 제공하고 있어서 정말 쉽게 데이터를 다룰 수 있답니다!

✨ 데이터 추가하기 (Create)

using (var context = new LibraryContext())
{
    // 새 저자 추가
    var author = new Author
    {
        Name = "J.K. Rowling",
        BirthDate = new DateTime(1965, 7, 31)
    };
    
    context.Authors.Add(author);
    context.SaveChanges(); // 변경사항을 DB에 저장
    
    // 저자의 책 추가
    var book = new Book
    {
        Title = "Harry Potter and the Philosopher's Stone",
        PublishedDate = new DateTime(1997, 6, 26),
        Price = 19.99m,
        AuthorId = author.Id // 자동으로 생성된 ID 사용
    };
    
    context.Books.Add(book);
    context.SaveChanges();
    
    Console.WriteLine($"저자 ID: {author.Id}, 책 ID: {book.Id}");
}

데이터를 추가했으니, 이제 조회해볼까요?

🔍 데이터 조회하기 (Read)

using (var context = new LibraryContext())
{
    // 모든 저자 조회
    var allAuthors = context.Authors.ToList();
    Console.WriteLine($"총 저자 수: {allAuthors.Count}");
    
    // 특정 저자 조회
    var rowling = context.Authors
        .FirstOrDefault(a => a.Name.Contains("Rowling"));
    
    if (rowling != null)
    {
        Console.WriteLine($"찾은 저자: {rowling.Name}");
        
        // 저자의 모든 책 조회 (Include로 관련 데이터 로드)
        var authorWithBooks = context.Authors
            .Include(a => a.Books)
            .FirstOrDefault(a => a.Id == rowling.Id);
        
        Console.WriteLine($"{authorWithBooks.Name}의 책 목록:");
        foreach (var book in authorWithBooks.Books)
        {
            Console.WriteLine($" - {book.Title} (${book.Price})");
        }
    }
    
    // LINQ를 사용한 복잡한 쿼리
    var expensiveBooks = context.Books
        .Where(b => b.Price > 15.0m)
        .OrderByDescending(b => b.Price)
        .Select(b => new { b.Title, b.Price })
        .ToList();
    
    Console.WriteLine("15달러 이상의 책 목록:");
    foreach (var book in expensiveBooks)
    {
        Console.WriteLine($" - {book.Title} (${book.Price})");
    }
}

이제 데이터를 수정하고 삭제하는 방법도 알아볼까요?

✏️ 데이터 수정하기 (Update)

using (var context = new LibraryContext())
{
    // 수정할 책 찾기
    var bookToUpdate = context.Books
        .FirstOrDefault(b => b.Title.Contains("Harry Potter"));
    
    if (bookToUpdate != null)
    {
        // 데이터 수정
        bookToUpdate.Price = 24.99m;
        bookToUpdate.Title = "Harry Potter and the Philosopher's Stone (2025 Edition)";
        
        // 변경사항 저장
        context.SaveChanges();
        Console.WriteLine("책 정보가 업데이트되었습니다!");
    }
}

🗑️ 데이터 삭제하기 (Delete)

using (var context = new LibraryContext())
{
    // 삭제할 책 찾기
    var bookToDelete = context.Books
        .FirstOrDefault(b => b.Title.Contains("2025 Edition"));
    
    if (bookToDelete != null)
    {
        // 데이터 삭제
        context.Books.Remove(bookToDelete);
        
        // 변경사항 저장
        context.SaveChanges();
        Console.WriteLine("책이 삭제되었습니다!");
    }
}

와~ 정말 간단하죠? SQL 쿼리 하나 안 쓰고도 데이터베이스 작업을 모두 처리했어요! EF Core의 강력한 LINQ 지원 덕분에 복잡한 쿼리도 C# 코드로 쉽게 작성할 수 있답니다. 👍

⚠️ 주의사항: 대량의 데이터를 다룰 때는 성능에 주의해야 해요! Include를 너무 많이 사용하거나 불필요한 데이터를 로드하면 성능이 저하될 수 있어요. 필요한 데이터만 선택적으로 로드하는 것이 좋답니다.

🔥 고급 기능: 2025년 EF Core의 최신 트렌드

2025년 현재 EF Core는 정말 많은 고급 기능을 제공하고 있어요. 실무에서 유용하게 사용할 수 있는 몇 가지 기능을 살펴볼까요?

1. 🚀 컴파일된 쿼리 (Compiled Queries)

자주 실행되는 쿼리는 컴파일해두면 성능이 크게 향상돼요!

// 컴파일된 쿼리 정의
private static readonly Func<LibraryContext, string, IEnumerable<Book>> _getBooksByTitle =
    EF.CompileQuery((LibraryContext context, string title) =>
        context.Books.Where(b => b.Title.Contains(title)));

// 사용 방법
using (var context = new LibraryContext())
{
    var harryPotterBooks = _getBooksByTitle(context, "Harry Potter").ToList();
}

2. 🔄 동시성 제어 (Concurrency Control)

여러 사용자가 동시에 같은 데이터를 수정할 때 발생할 수 있는 문제를 해결해줘요.

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    
    [ConcurrencyCheck] // 동시성 검사를 위한 속성
    public byte[] RowVersion { get; set; }
}

// 모델 구성에서 설정
modelBuilder.Entity<Book>()
    .Property(b => b.RowVersion)
    .IsRowVersion();

3. 🔍 글로벌 쿼리 필터 (Global Query Filters)

특정 조건을 모든 쿼리에 자동으로 적용할 수 있어요. 예를 들어, 삭제된 데이터를 자동으로 제외하는 기능이죠!

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public bool IsDeleted { get; set; }
}

// DbContext에서 글로벌 필터 설정
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>().HasQueryFilter(b => !b.IsDeleted);
}

4. 🔄 자동 변경 감지 (Change Tracking)

EF Core는 엔티티의 변경 사항을 자동으로 추적해요. 하지만 대량의 데이터를 처리할 때는 이 기능을 비활성화하는 것이 좋을 수 있어요.

// 읽기 전용 쿼리 (변경 감지 비활성화)
using (var context = new LibraryContext())
{
    var books = context.Books
        .AsNoTracking() // 변경 감지 비활성화
        .ToList();
}

5. 🔄 배치 작업 (Bulk Operations)

2025년 EF Core는 배치 작업을 더 효율적으로 처리할 수 있는 기능을 제공해요.

// 여러 엔티티 한 번에 추가
context.Books.AddRange(book1, book2, book3);

// 여러 엔티티 한 번에 삭제
context.Books.RemoveRange(book1, book2, book3);

// 변경사항 저장
context.SaveChanges();

이런 고급 기능들을 활용하면 더 효율적이고 안정적인 애플리케이션을 개발할 수 있어요. 특히 재능넷 같은 대규모 플랫폼을 개발할 때 이런 기능들이 정말 유용하답니다! 😊

💯 EF Core 모범 사례 및 성능 최적화 팁

EF Core를 효율적으로 사용하기 위한 몇 가지 꿀팁을 알려드릴게요! 2025년 현재 많은 개발자들이 이런 방법으로 성능을 크게 개선하고 있답니다.

1. 🚀 적절한 인덱스 설정하기

자주 검색하는 필드에 인덱스를 설정하면 쿼리 성능이 크게 향상돼요!

modelBuilder.Entity<Book>()
    .HasIndex(b => b.Title);

2. 🔍 필요한 데이터만 로드하기

Select를 사용해 필요한 속성만 가져오면 성능이 향상돼요.

var bookTitles = context.Books
    .Select(b => new { b.Id, b.Title })
    .ToList();

3. 📊 페이징 사용하기

대량의 데이터를 한 번에 로드하지 말고, 페이징을 사용하세요!

var pageNumber = 1;
var pageSize = 10;
var books = context.Books
    .Skip((pageNumber - 1) * pageSize)
    .Take(pageSize)
    .ToList();

4. 🔄 적절한 로딩 전략 선택하기

상황에 따라 즉시 로딩(Eager Loading)과 지연 로딩(Lazy Loading) 중 적절한 방식을 선택하세요.

// 즉시 로딩 (Eager Loading)
var authorsWithBooks = context.Authors
    .Include(a => a.Books)
    .ToList();

// 지연 로딩 (Lazy Loading)
// 먼저 지연 로딩 활성화 패키지 설치 필요
// Microsoft.EntityFrameworkCore.Proxies
optionsBuilder
    .UseLazyLoadingProxies()
    .UseSqlServer(connectionString);

5. 💾 트랜잭션 관리하기

여러 작업을 하나의 트랜잭션으로 묶어 데이터 일관성을 유지하세요.

using (var transaction = context.Database.BeginTransaction())
{
    try
    {
        // 여러 데이터베이스 작업 수행
        context.Authors.Add(author);
        context.SaveChanges();
        
        context.Books.Add(book);
        context.SaveChanges();
        
        // 모든 작업이 성공하면 트랜잭션 커밋
        transaction.Commit();
    }
    catch (Exception)
    {
        // 오류 발생 시 롤백
        transaction.Rollback();
        throw;
    }
}

🌟 EF Core 사용 시 추가 팁

  1. DbContext는 짧게 사용하고 빨리 해제하세요. using 블록을 활용하면 좋아요!
  2. 대량의 데이터를 처리할 때는 AsNoTracking()을 사용해 메모리 사용량을 줄이세요.
  3. 복잡한 쿼리는 저장 프로시저를 사용하는 것이 좋을 수 있어요.
  4. 개발 중에는 로깅을 활성화해서 생성되는 SQL을 확인하세요.
  5. 프로덕션 환경에서는 성능 모니터링 도구를 사용해 병목 현상을 찾아내세요.

이런 모범 사례를 따르면 EF Core로 개발한 애플리케이션의 성능과 안정성이 크게 향상될 거예요! 특히 재능넷과 같은 사용자가 많은 플랫폼에서는 이런 최적화가 정말 중요하답니다. 😉

🌐 실전 예제: 재능넷 같은 플랫폼 개발하기

이제 배운 내용을 바탕으로 실제 프로젝트에 적용해볼까요? 재능넷과 같은 재능 공유 플랫폼을 EF Core로 구현하는 예제를 살펴보겠습니다!

📝 도메인 모델 설계

먼저 필요한 엔티티들을 정의해볼게요:

// 사용자 엔티티
public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public string PasswordHash { get; set; }
    public DateTime CreatedAt { get; set; }
    
    // 탐색 속성
    public UserProfile Profile { get; set; }
    public List<Talent> Talents { get; set; }
    public List<Order> Orders { get; set; }
}

// 사용자 프로필 엔티티
public class UserProfile
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string FullName { get; set; }
    public string Bio { get; set; }
    public string ProfileImageUrl { get; set; }
    
    // 탐색 속성
    public User User { get; set; }
}

// 재능 엔티티
public class Talent
{
    public int Id { get; set; }
    public int SellerId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
    public DateTime CreatedAt { get; set; }
    
    // 탐색 속성
    public User Seller { get; set; }
    public List<TalentImage> Images { get; set; }
    public List<Review> Reviews { get; set; }
    public List<Order> Orders { get; set; }
}

// 재능 이미지 엔티티
public class TalentImage
{
    public int Id { get; set; }
    public int TalentId { get; set; }
    public string ImageUrl { get; set; }
    
    // 탐색 속성
    public Talent Talent { get; set; }
}

// 주문 엔티티
public class Order
{
    public int Id { get; set; }
    public int BuyerId { get; set; }
    public int TalentId { get; set; }
    public decimal Amount { get; set; }
    public string Status { get; set; }
    public DateTime CreatedAt { get; set; }
    
    // 탐색 속성
    public User Buyer { get; set; }
    public Talent Talent { get; set; }
    public Review Review { get; set; }
}

// 리뷰 엔티티
public class Review
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public int Rating { get; set; }
    public string Comment { get; set; }
    public DateTime CreatedAt { get; set; }
    
    // 탐색 속성
    public Order Order { get; set; }
    public Talent Talent { get; set; }
}

🔄 DbContext 설정

이제 DbContext를 설정해볼게요:

public class JaenungNetContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<Talent> Talents { get; set; }
    public DbSet<TalentImage> TalentImages { get; set; }
    public DbSet<Order> Orders { get; set; }
    public DbSet<Review> Reviews { get; set; }
    
    public JaenungNetContext(DbContextOptions<JaenungNetContext> options)
        : base(options)
    {
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 사용자와 프로필 관계 설정 (1:1)
        modelBuilder.Entity<User>()
            .HasOne(u => u.Profile)
            .WithOne(p => p.User)
            .HasForeignKey<UserProfile>(p => p.UserId);
        
        // 판매자와 재능 관계 설정 (1:N)
        modelBuilder.Entity<Talent>()
            .HasOne(t => t.Seller)
            .WithMany(u => u.Talents)
            .HasForeignKey(t => t.SellerId);
        
        // 재능과 이미지 관계 설정 (1:N)
        modelBuilder.Entity<TalentImage>()
            .HasOne(i => i.Talent)
            .WithMany(t => t.Images)
            .HasForeignKey(i => i.TalentId);
        
        // 주문 관계 설정
        modelBuilder.Entity<Order>()
            .HasOne(o => o.Buyer)
            .WithMany(u => u.Orders)
            .HasForeignKey(o => o.BuyerId);
        
        modelBuilder.Entity<Order>()
            .HasOne(o => o.Talent)
            .WithMany(t => t.Orders)
            .HasForeignKey(o => o.TalentId);
        
        // 리뷰 관계 설정
        modelBuilder.Entity<Review>()
            .HasOne(r => r.Order)
            .WithOne(o => o.Review)
            .HasForeignKey<Review>(r => r.OrderId);
        
        modelBuilder.Entity<Review>()
            .HasOne(r => r.Talent)
            .WithMany(t => t.Reviews)
            .HasForeignKey(r => r.TalentId);
        
        // 인덱스 설정
        modelBuilder.Entity<Talent>()
            .HasIndex(t => t.Category);
        
        modelBuilder.Entity<User>()
            .HasIndex(u => u.Email)
            .IsUnique();
    }
}

🚀 서비스 구현

이제 비즈니스 로직을 구현하는 서비스 클래스를 만들어볼게요:

public class TalentService
{
    private readonly JaenungNetContext _context;
    
    public TalentService(JaenungNetContext context)
    {
        _context = context;
    }
    
    // 재능 등록 메서드
    public async Task<Talent> CreateTalentAsync(Talent talent, List<string> imageUrls)
    {
        using (var transaction = await _context.Database.BeginTransactionAsync())
        {
            try
            {
                // 재능 추가
                talent.CreatedAt = DateTime.Now;
                _context.Talents.Add(talent);
                await _context.SaveChangesAsync();
                
                // 이미지 추가
                if (imageUrls != null && imageUrls.Count > 0)
                {
                    foreach (var url in imageUrls)
                    {
                        _context.TalentImages.Add(new TalentImage
                        {
                            TalentId = talent.Id,
                            ImageUrl = url
                        });
                    }
                    await _context.SaveChangesAsync();
                }
                
                // 트랜잭션 커밋
                await transaction.CommitAsync();
                
                return talent;
            }
            catch (Exception)
            {
                await transaction.RollbackAsync();
                throw;
            }
        }
    }
    
    // 카테고리별 재능 검색 메서드
    public async Task<List<Talent>> GetTalentsByCategoryAsync(string category, int page = 1, int pageSize = 10)
    {
        return await _context.Talents
            .Where(t => t.Category == category)
            .OrderByDescending(t => t.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Include(t => t.Seller)
                .ThenInclude(s => s.Profile)
            .Include(t => t.Images)
            .Include(t => t.Reviews)
            .ToListAsync();
    }
    
    // 재능 상세 조회 메서드
    public async Task<Talent> GetTalentDetailAsync(int talentId)
    {
        return await _context.Talents
            .Where(t => t.Id == talentId)
            .Include(t => t.Seller)
                .ThenInclude(s => s.Profile)
            .Include(t => t.Images)
            .Include(t => t.Reviews)
                .ThenInclude(r => r.Order)
                    .ThenInclude(o => o.Buyer)
                        .ThenInclude(b => b.Profile)
            .FirstOrDefaultAsync();
    }
}

🔍 검색 기능 구현

재능넷 같은 플랫폼에서 중요한 검색 기능을 구현해볼게요:

public class SearchService
{
    private readonly JaenungNetContext _context;
    
    public SearchService(JaenungNetContext context)
    {
        _context = context;
    }
    
    // 키워드 검색 메서드
    public async Task<List<Talent>> SearchTalentsAsync(string keyword, int page = 1, int pageSize = 10)
    {
        if (string.IsNullOrEmpty(keyword))
            return new List<Talent>();
        
        return await _context.Talents
            .Where(t => t.Title.Contains(keyword) || 
                   t.Description.Contains(keyword))
            .OrderByDescending(t => t.Reviews.Average(r => r.Rating))
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Include(t => t.Seller)
                .ThenInclude(s => s.Profile)
            .Include(t => t.Images.Take(1))
            .Select(t => new Talent
            {
                Id = t.Id,
                Title = t.Title,
                Price = t.Price,
                Category = t.Category,
                Seller = new User
                {
                    Id = t.Seller.Id,
                    Username = t.Seller.Username,
                    Profile = t.Seller.Profile
                },
                Images = t.Images.ToList(),
                Reviews = t.Reviews.ToList()
            })
            .ToListAsync();
    }
    
    // 필터링 검색 메서드
    public async Task<List<Talent>> FilterTalentsAsync(
        string category = null,
        decimal? minPrice = null,
        decimal? maxPrice = null,
        int? minRating = null,
        int page = 1,
        int pageSize = 10)
    {
        var query = _context.Talents.AsQueryable();
        
        // 카테고리 필터
        if (!string.IsNullOrEmpty(category))
            query = query.Where(t => t.Category == category);
        
        // 가격 필터
        if (minPrice.HasValue)
            query = query.Where(t => t.Price >= minPrice.Value);
        
        if (maxPrice.HasValue)
            query = query.Where(t => t.Price <= maxPrice.Value);
        
        // 평점 필터
        if (minRating.HasValue)
            query = query.Where(t => t.Reviews.Average(r => r.Rating) >= minRating.Value);
        
        return await query
            .OrderByDescending(t => t.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Include(t => t.Seller)
                .ThenInclude(s => s.Profile)
            .Include(t => t.Images.Take(1))
            .ToListAsync();
    }
}

와우! 이렇게 EF Core를 사용하면 재능넷 같은 복잡한 플랫폼도 효율적으로 구현할 수 있어요. 관계형 데이터베이스의 복잡한 관계도 쉽게 표현할 수 있고, 강력한 쿼리 기능으로 다양한 검색 기능도 구현할 수 있답니다! 😊

💡 실무 팁: 실제 재능넷과 같은 서비스를 개발할 때는 성능 최적화가 매우 중요해요. 특히 사용자가 많아질수록 데이터베이스 쿼리 최적화가 필수랍니다! EF Core의 고급 기능들을 적극 활용해보세요.

🎯 마무리: EF Core로 개발 생산성 높이기

지금까지 Entity Framework Core를 사용해 데이터베이스를 다루는 방법에 대해 알아봤어요. 2025년 현재, EF Core는 .NET 개발자에게 정말 필수적인 도구가 되었답니다! 😎

📝 요약

  1. EF Core는 C# 객체와 데이터베이스 사이의 다리 역할을 하는 ORM 프레임워크예요.
  2. 코드 우선(Code First) 접근 방식으로 C# 클래스에서 데이터베이스 스키마를 생성할 수 있어요.
  3. LINQ를 사용해 복잡한 쿼리도 C# 코드로 쉽게 작성할 수 있어요.
  4. 관계 설정, 마이그레이션, 변경 추적 등 다양한 기능을 제공해요.
  5. 성능 최적화 기법을 적용하면 대규모 애플리케이션에서도 효율적으로 사용할 수 있어요.

EF Core를 마스터하면 개발 시간을 크게 단축할 수 있고, 코드의 가독성과 유지보수성도 향상된답니다. 특히 재능넷과 같은 복잡한 데이터 관계를 가진 플랫폼을 개발할 때 EF Core의 진가가 더욱 빛나요! 🌟

여러분도 이제 EF Core를 활용해서 멋진 프로젝트를 만들어보세요! SQL 쿼리 작성에 시간을 낭비하지 말고, 비즈니스 로직 구현에 더 집중할 수 있을 거예요. 그리고 혹시 개발 관련 재능이 있다면, 재능넷에서 여러분의 지식을 공유하고 수익도 창출해보는 건 어떨까요? 😉

오늘도 코딩 즐겁게 하시고, 다음에 또 다른 개발 주제로 만나요! 안녕~ 👋

댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0