mybatis for dotnet

**๋‚ด๊ฐ€ ๋งŒ๋“ค์—ˆ์–ด์š”! ๊ฒŒ์‹œํŒ ๊ณต์ง€ ์‚ฌํ•ญ**์˜ ๋‚ด์šฉ์„ ์ˆ™์ง€ํ•˜์‹  ํ›„, ๊ธ€์„ ๊ฒŒ์‹œํ•ด์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ orm๋ณด๋‹ค sql์ด ์ง๊ด€์ ์œผ๋กœ ํŽธํ•˜๊ธฐ๋„ ํ•˜๊ณ  ์™œ ๋‹ท๋„ท์œผ๋กœ ์„œ๋น„์Šคํ•˜๊ณ ์žˆ๋Š”์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์„œ๋ฒ„๋„ ์ฅ๋˜ฅ๋งŒํ•œ๊ฑฐ ์“ฐ๋ฉด์„œ ํ†ต๊ณ„, ์—ฐ์‚ฐ ์œ„์ฃผ์˜ ์„œ๋น„์Šค๋ฅผ dotnet ef๋กœ ํ•˜๋ ค๋‹ˆ ์„ฑ๋Šฅ์ด๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ ์žก๊ธฐ ํž˜๋“ค์–ด์„œ ๋งŒ๋“ค์–ด ๋ดค์Šต๋‹ˆ๋‹ค..

12๊ฐœ์˜ ์ข‹์•„์š”

์ข‹์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ, ์‚ฌ์ƒ์ ์œผ๋กœ MyBatis์™€ ๋น„์Šทํ•œ ํฌ์ง€์…˜์˜ ์ž˜ ์•Œ๋ ค์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ Dapper๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ๋“œ์‹œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ฐธ๊ณ ํ•ด๋ณผ ๋งŒํ•œ ์‚ฌํ•ญ๋“ค์ด ๋งŽ์ด ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. :+1:

GitHub - DapperLib/Dapper: Dapper - a simple object mapper for .Net

3๊ฐœ์˜ ์ข‹์•„์š”

์ข‹๋„ค์š”!
mybatis์˜ ์žฅ์ ์€ group ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋งคํ•‘ํ•ด์ค„ ์ˆ˜ ์žˆ๊ณ  entity ์žฌ์‚ฌ์šฉ์ด ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด๋ผ ์„ ํ˜ธํ•˜๋Š” ํŽธ์ธ๋ฐ์š”.
dapper๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ•๋ ฅํ•œ orm์ธ๋ฐ sql server๋ฅผ ์“ฐ๋ฉด์„œ join์ด ๋งŽ์•„์ง€๋Š” sp๊ฐ€ ๋งŽ์•„์ง€๊ฒŒ ๋˜๋Š”๋ฐ ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ ๋งคํ•‘ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๋Š˜์–ด๋‚˜์„œ ์œ ์ง€๋ณด์ˆ˜์—๋Š” ๋‹ค์†Œ ๋ถˆํŽธํ•จ์ด ์žˆ์–ด ์ข€ ์•„์‰ฌ์šด ๊ฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ตœ๊ทผ์— smartsql์„ ๋ดค์—ˆ๋Š”๋ฐ ๋น„์Šทํ•œ ์„ฑ๊ฒฉ์˜ ์ข‹์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ค์š”. .net10์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค

4๊ฐœ์˜ ์ข‹์•„์š”

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋‹ท๋„ท 7,8,9,10 ๋ชจ๋‘ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

5๊ฐœ์˜ ์ข‹์•„์š”

๋‚ด์นœ๊น€์— Dapper, EF ๋“ฑ๊ณผ ๋ฒค์น˜๋งˆํฌ๋„ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๋ฒค์น˜ ๋งˆํฌ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์„๊นŒ์š”?

1๊ฐœ์˜ ์ข‹์•„์š”

์˜ˆ์ œํ”„๋กœ์ ํŠธ์™€ ํ•จ๊ป˜ ๋ฐด์น˜๋งˆํฌ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒค์น˜๋งˆํฌ ํ”„๋กœ์ ํŠธ๊ฐ€ ์‹คํ–‰๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ธ์ง€์š”?
๊ธ€๋กœ๋ฒŒ ์…‹์—…์ด ๊ณต๋ž€ ์•„๋‹ˆ๋ฉด ์ฃผ์„์ฒ˜๋ฆฌ๋ผโ€ฆ

๊ทธ๋ฆฌ๊ณ , ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋Š” ์ „๋ถ€ ๊ฑด๋„ˆ ๋„์‹  ๊ฑฐ ๊ฐ™์Šต๋‹ˆ๋‹ค. ^^

๊ท€์‹ ์ด ๊ณกํ•  ๋…ธ๋ฆ‡์ด๋„ค์š” ใ…‹ใ…‹ ์ฃผ๋ง ๋‚ด๋‚ด ์ž‘์—…ํ–ˆ๋˜๊ฑด๋ฐโ€ฆ

๋ฌธ์ž์—ด ๊ธฐ๋ฐ˜ orm ์˜ ํ•œ๊ณ„๋Š” ์‚ฌ์‹ค ์•„๋ž˜์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€์‘ํ•  ๋•Œ ๋„ˆ๋ฌด ๋งŽ์€ ๋…ธ๋™์„ ๊ฐ•์š”ํ•œ๋‹ค๋Š” ์ ์— ์žˆ์Šต๋‹ˆ๋‹ค.

// Dapper
    public async Task<long> CreateCompleteOrderAsync(Order order, IEnumerable<OrderItem> items, Payment payment, Shipment shipment)
    {
        await using var conn = new NpgsqlConnection(_connectionString);
        await conn.OpenAsync();
        await using var transaction = await conn.BeginTransactionAsync();

        try
        {
            var orderId = await InsertAsync(order);
            await transaction.CommitAsync();
            return orderId;
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
// Nuvatis
    public async Task<long> CreateCompleteOrderAsync(Order order, IEnumerable<OrderItem> items, Payment payment, Shipment shipment)
    {
        // ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ํ•„์š” - ๊ฐ„์†Œํ™”
        var orderId = await _mapper.InsertAsync(order);
        return orderId;
    }

๊ทธ๋Ÿฐ ์ ๋•Œ๋ฌธ์— ๋ฒค์น˜๋งˆํฌ์—์„œ๋„ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•˜๊ณ  Insert ๋กœ ๋Œ€์‹ ํ•œ ๋“ฏ ๋ณด์ž…๋‹ˆ๋‹ค.
์‚ฌ์‹ค, ์œ„ ์ฝ”๋“œ๋Š” ํ…Œ์ŠคํŠธ ์‹คํŒจ๋ผ์„œ, ๋ฒค์น˜๋งˆํฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋ฌด๋Ÿฐ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ํŒจ์Šคํ•˜๋ ค๋ฉด, ๋กœ์ง๊ณผ ์ฟผ๋ฆฌ๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•˜๊ฒŒ ์–ฝํžˆ๋Š” ์ƒํ™ฉ์„ ํ”ผํ•  ์ˆ˜๋Š” ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// Dapper
    public async Task<long> CreateCompleteOrderAsync(Order order, IEnumerable<OrderItem> items, Payment payment, Shipment shipment)
    {
        if (order.Id != default || order.OrderItems.Count != 0 || order.Shipment != null || order.Payment != null)
            throw new InvalidArguementException("์‹ ๊ทœ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹˜.");        
        
        await using var conn = new NpgsqlConnection(_connectionString);
        await conn.OpenAsync();
        await using var transaction = await conn.BeginTransactionAsync();
        
        try
        {
           // order ์ €์žฅ ํ›„ ์™ธ๋ž˜ํ‚ค ํš๋“,  
           foreach(var item in items)
           {
               if (item.Id == default)
               {
                    // Insert
               }
               else
               {
                     // Update
               }
           }
           // shipment, payment ๋™์ผ ๊ณผ์ • ๋ฐ˜๋ณต

์ด๋Ÿฐ ์ƒํ™ฉ์ด ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ์œ ์ผํ•˜์ง€๋„ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์žฌ๋ฐŒ๋Š” ์ ์€ EF Core ์˜ ๊ตฌํ˜„๋„ ์‹คํŒจ ์ฝ”๋“œ๋ฅผ ๊ธฐ๊ณ„์ ์œผ๋กœ ๋‹ต์Šตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

// EF Core
    public async Task<long> CreateCompleteOrderAsync(Order order, IEnumerable<OrderItem> items, Payment payment, Shipment shipment)
    {
        await using var transaction = await _context.Database.BeginTransactionAsync();

        try
        {
            _context.Orders.Add(order);
            await _context.SaveChangesAsync();

            await transaction.CommitAsync();
            return order.Id;
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }

์‚ฌ์‹ค, EF Core ๋Š” ChangeTracker ๊ฐ€ ๋ณต์žกํ•œ ๋กœ์ง - Insert ํ•  ๊ฒƒ๊ณผ Update ํ•  ๊ฒƒ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์„ ๋‹ค ํ•ด๊ฒฐํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์—, ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

// EF Core
    public async Task<long> CreateCompleteOrderAsync(Order order)
    {
        _context.Orders.Add(order);
        var affected = await _context.SaveChangesAsync();
        return affected > 0 ? order.Id : -1;
    }

SaveChanges(Async) ๋Š” ์•”๋ฌต์ ์œผ๋กœ Transcation ์„ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด Transaction ์„ ์ถ”๊ฐ€ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

ChangeTracker ์— ๊ธฐ๋ฐ˜ํ•œ ์œ„ ์ฝ”๋“œ๋Š” ์‚ฌ์‹ค ํ…Œ์ŠคํŠธ๊ฐ€ ํ•„์š”์—†์„ ์ •๋„๋กœ ์ •ํ™•ํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์„ฑ๋Šฅ ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋ฉด์„œ๊นŒ์ง€ EF Core๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์ด๋Ÿฐ ์ •ํ™•์„ฑ๊ณผ ์ฝ”๋”ฉ ํšจ์œจ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (Linq ์˜ ํšจ์œจ๋„ ์–ด๋งˆ์–ด๋งˆํ•˜๊ณ  DB ๊ด€๋ฆฌ๋„๊ตฌ๋„ ์—„์ฒญ๋‚˜์ฃ )

NuVatis ๊ฐ€ ์œ„์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์—๋„ ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ChangeTracker ์™€ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ์ •์ž‘ ๋น„ํšจ์œจ์ด๋ผ๊ณ  ๋น„ํŒํ•˜๋˜ EF Core ์˜ ๋˜ ๋‹ค๋ฅธ ๋ฒ„์ „์ด ๋˜๊ณ , ๋งŒ์•ฝ ๋Œ€์‘ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋ฉด ์†๊ฐ€๋ฝ ํ’ˆ์„ ๊ฐ•์š”ํ•˜๋Š” ๊ทธ์ € ๊ทธ๋Ÿฐ ๋„๊ตฌ๋กœ ์ „๋ฝํ•˜๋Š” ์•„์ด๋Ÿฌ๋‹ˆ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์•„์ด๋Ÿฌ๋‹ˆ๋Š” ์กด์ค‘ ๋ณด๋‹ค๋Š” ์„ฃ๋ถ€๋ฅธ ๋น„ํŒ์ด ๋จผ์ €์˜€๋˜ ๊ฒƒ์ด ์›์ธ์ด์ง€ ์•Š์„๊นŒํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.

1๊ฐœ์˜ ์ข‹์•„์š”

์ œ๊ฐ€ NuVatis๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋œ ์ด์œ ๋Š”,
ํ˜„ ์ง์žฅ์—์„œ ์ฒ˜์Œ ๋งก์€ ์ผ์ด ์Šฌ๋กœ์šฐ ์ฟผ๋ฆฌ๋กœ ์ธํ•œ ํƒ€์ž„์•„์›ƒ ๋ฌธ์ œ ํ•ด๊ฒฐ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ดํ›„์—๋„ ํ•œ๋™์•ˆ ์ „์ž„์ž๊ฐ€ ๊ตฌํ˜„ํ•ด๋†“์€ ํ†ต๊ณ„, ์ง€ํ‘œ ์กฐํšŒ๋ฅผ ์งฌ์งฌ์ด ์ตœ์ ํ™”ํ–ˆ๊ณ , ์กฐํšŒ ์†๋„๋Š” ์ตœ๋Œ€ 3600๋ฐฐ๊นŒ์ง€๋„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋งŒํผ์€ ์ข€์ฒ˜๋Ÿผ ํ•ด๊ฒฐ์ด ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์•„๋งˆ์กด์—์„œ 4GB ์ธ์Šคํ„ด์Šค๋ฅผ ์“ฐ๊ณ  ์žˆ๋Š”๋ฐ OOM์œผ๋กœ ์„œ๋น„์Šค๊ฐ€ ๋ฉŽ๋Š” ์ผ์ด ๋ช‡ ๋ฒˆ ๋ฐ˜๋ณต๋์Œ์—๋„ "๋ˆ ์•ˆ ์“ฐ๋Š” ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์œผ๋ผ"๋Š” ๋Œ€ํ‘œ์˜ ์˜์ง€๊ฐ€ ํ™•๊ณ ํ–ˆ๊ณ , AI๋ฅผ ํ™œ์šฉํ•ด๋„ ์ œ๊ฐ€ ์ด๋ฏธ ์ตœ์ ํ™”ํ•œ ๊ฒƒ ์ด์ƒ์˜ ํšจ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋•Œ ๋– ์˜ฌ๋ฆฐ ๊ฒƒ์ด ์ด์ „ ์ง์žฅ์—์„œ์˜ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ์ „์—๋Š” ์ž๋ฐ”์ชฝ ์ผ๋งŒ ํ–ˆ์—ˆ๊ณ  ํ›จ์”ฌ ํฌ๊ณ  ๊ฑฐ๋Œ€ํ•œ ์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•˜๋ฉด์„œ๋„ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋Š”๋ฐ ์–ธ์–ด์™€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋‹ค๋ฅด๋‹ค๊ณ ๋Š” ํ•ด๋„ ์ด ์ •๋„ ์ฐจ์ด๊ฐ€ ๋‚ ๊นŒ ์‹ถ์–ด ์ƒ๊ฐํ•˜๋‹ค ๋งˆ์ด๋ฐ”ํ‹ฐ์Šค๊ฐ€ ๋– ์˜ฌ๋ž๊ณ , ์‹ค์ œ๋กœ ๊ฐ€์žฅ ๋ถ€ํ•˜๊ฐ€ ํฐ ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ XML ๋งคํผ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ดค๋”๋‹ˆ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ 80% ์ด์ƒ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. NuVatis๋Š” ๊ทธ ๊ฒฝํ—˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์ง€์ ํ•˜์‹  ๋‚ด์šฉ์€ ๋งž์Šต๋‹ˆ๋‹ค. ๋ฒค์น˜๋งˆํฌ์˜ CreateCompleteOrderAsync ๊ตฌํ˜„์€ items, payment, shipment๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์œผ๋ฉด์„œ ์‹ค์ œ๋กœ๋Š” order ํ•˜๋‚˜๋งŒ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๊ฐ„์†Œํ™”๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฏธ์™„์„ฑ ๊ตฌํ˜„์ด๊ณ , ์ด ์ƒํƒœ์—์„œ ์ธก์ •๋œ ์ˆ˜์น˜๋Š” โ€œ์™„์ „ํ•œ ์ฃผ๋ฌธ ์ƒ์„ฑโ€ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์„ฑ๋Šฅ์ด ์•„๋‹™๋‹ˆ๋‹ค. NuVatis, Dapper ๋ชจ๋‘ ๊ฐ™์€ ๊ฒฐํ•จ์„ ๊ฐ€์ง€๋ฉฐ ํ•ด๋‹น ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ๋Š” ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

EF Core์˜ ChangeTracker๊ฐ€ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ๋ฌธ์ œ๋„ ์‹ค์ œ๋กœ ํฐ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•ด INSERT/UPDATE/DELETE๋ฅผ ์ž๋™ ํŒ๋ณ„ํ•˜๊ณ  SaveChangesAsync๊ฐ€ ์•”๋ฌต์  ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์ด๋ฅผ ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค๋Š” ๊ฒƒ์€, ๋ณต์žกํ•œ ๋„๋ฉ”์ธ ๋กœ์ง์—์„œ ๋‹จ์ˆœํ•œ ํŽธ์˜์„ฑ์„ ๋„˜์–ด ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ์ˆ˜๋‹จ์ž…๋‹ˆ๋‹ค.
NuVatis๋‚˜ Dapper์—์„œ ์ด ์ˆ˜์ค€์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ฃจ๋ ค๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ƒํƒœ ํŒ๋ณ„๊ณผ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ „๋ถ€ ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๊ณ , ๋ณต์žก๋„๊ฐ€ ๋†’์•„์งˆ์ˆ˜๋ก ๊ทธ ๋น„์šฉ์€ ์„ ํ˜•์ด ์•„๋‹ˆ๋ผ ์ง€์ˆ˜์ ์œผ๋กœ ๋Š˜์–ด๋‚˜๊ฒ ์ฃ .

"NuVatis๊ฐ€ ChangeTracker๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด EF Core์˜ ๋˜ ๋‹ค๋ฅธ ๋ฒ„์ „์ด ๋œ๋‹ค"๋Š” ์ง€์ ๋„ ์ •ํ™•ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ORM ์„ค๊ณ„ ๊ณต๊ฐ„์˜ ๊ทผ๋ณธ์ ์ธ ๋ถ„๊ธฐ์ ์ž…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ๊ณผ ํŽธ์˜์„ฑ์€ ๋™์ผํ•œ ์„ค๊ณ„์—์„œ ๋™์‹œ์— ์ตœ๋Œ€ํ™”๋  ์ˆ˜ ์—†๊ณ , ๋„๊ตฌ๋Š” ์ด ์ŠคํŽ™ํŠธ๋Ÿผ ์œ„์˜ ์–ด๋А ์ง€์ ์„ ์„ ํƒํ•  ์ˆ˜๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

NuVatis๋Š” ์ œ ๊ฐœ์ธ์ ์ธ ๊ฒฝํ—˜์—์„œ ๋‚˜์˜จ ๋„๊ตฌ์ด๋‹ค ๋ณด๋‹ˆ, ์ œ๊ฐ€ ๊ฒช์—ˆ๋˜ ๋ฌธ์ œ, ์ฆ‰ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ฝ๊ธฐ ์ค‘์‹ฌ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ์˜ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ๋‹ค๋ฃจ๋Š” ์“ฐ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์†”์งํžˆ EF Core๊ฐ€ ๋” ์ ํ•ฉํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜์ง€ ์•Š์€ ์ฑ„ ๋ฒค์น˜๋งˆํฌ๋ฅผ ๊ตฌ์„ฑํ•œ ๊ฒƒ์€ ์ œ ์‹ค์ˆ˜๊ฐ€ ๋งž์Šต๋‹ˆ๋‹ค.

์›๋ž˜๋ถ€ํ„ฐ ORM์ด ๋ณ„๋กœ ์ง๊ด€์ ์ด์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ด์™”๋˜ ๋ฐ๋‹ค ์‹ค๋ฌด ๊ฒฝํ—˜๊นŒ์ง€ ๊ฒน์น˜๋ฉด์„œ EF Core์— ๋Œ€ํ•œ ์‹œ๊ฐ์ด ๋ถ€์ •์ ์œผ๋กœ ๊ตณ์–ด์ง„ ๋ฉด์ด ์žˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋น„ํŒ์ด ๋จผ์ €์˜€๊ณ  ์ •ํ™•ํ•œ ๋งฅ๋ฝ ์„ค์ •์ด ๋’ค๋”ฐ๋ฅด์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ์ ์—์„œ ๋ถˆ์พŒํ•˜์…จ๋‹ค๋ฉด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

3๊ฐœ์˜ ์ข‹์•„์š”

๋ฒค์น˜๋งˆํฌ๊ฐ€ ๋ญ”๊ฐ€ ํ™•์ฆ ํŽธํ–ฅ์˜ ์ฆ๋ช…๊ฐ™๋‹ค๋Š” ๋А๋‚Œ์„ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ“๊ธ€์„ ์“ด ๊ฒƒ์ด์ง€, ์ œ ๊ธฐ๋ถ„ ๋‚˜์จ์„ ์•Œ๋ฆฌ๋ ค ์“ด ๊ธ€์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ถœ๋ฐœ์ ์ด ํŽธํ–ฅ์ ์ด๋ฉด ์˜ฌ๋ฐ”๋ฅธ ํ‰๊ฐ€๋ฅผ ํ•  ์ˆ˜ ์—†๊ณ , ๋ณด๋‹ค ๋‚˜์€ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“œ๋Š”๋ฐ ๋ฐฉํ•ด๊ฐ€ ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ๋Š”, ๋ฒค์น˜๋งˆํฌ๋ฅผ ์ƒˆ๋กœ ์ž‘์„ฑํ•˜๊ธฐ ๋ณด๋‹ค๋Š”, Frans Bouma ๊ฐ€ ์ž‘์„ฑํ•œ ORM ๋ณ„ ๋ฒค์น˜๋งˆํฌ ์ €์žฅ์†Œ ๋ฅผ fork ํ•œ ํ›„, NuVatis ์ผ€์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ๋‚˜์˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (ํ•„์š”ํ•˜๋‹ค๋ฉด ๊ธฐ์กด ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ๋ช‡๊ฐœ๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ ์ข€ ๋” ๊ทœ๋ชจ๋ฅผ ์ค„์ผ ์ˆ˜๋„ ์žˆ๊ตฌ์š”.)

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ ์ฝ”๋“œ์— ์„ ์ž…๊ฒฌ์ด ๊ฐœ์ž…ํ•  ์—ฌ์ง€๊ฐ€ ์—†์–ด์ง€๊ณ  NuVatis ์ฝ”๋“œ์—๋งŒ ์ง‘์ค‘ํ•˜๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

1๊ฐœ์˜ ์ข‹์•„์š”

ํŽธํ–ฅ๋œ ๋ฐ์ดํ„ฐ ๋งž์•„์š” ใ…‹ใ…‹ ์ œ๋ฏธ๋‚˜์ดํ•œํ…Œ ์ฃผ์„ ์ข€ ์“ฐ๋ผ๊ณ  ํ–ˆ๋”๋‹ˆ ์ •๋ง๋กœ ์ฃ„๋‹ค ์ฃผ์„์œผ๋กœ ๋งŒ๋“ค์–ด ๋ฒ„๋ฆฌ๊ณ  ๋Œ€์‹œ๋ณด๋“œ๋„ ๋ชฉ์—… ๋ฐ์ดํ„ฐ๋กœ ์‹น๋‹ค ๋ฐ•์•„๋„ฃ์–ด๋†จ๋Š”๋ฐ ์ดˆ๊ธฐ์— ์ง์ ‘ ์‹ค์ธกํ–ˆ๋˜ ๋ฐ์ดํ„ฐ๋“ค๊ณผ ๋งฅ๋ฝ์ด ๋น„์Šทํ•ด์„œ ์˜์‹ฌ์„ ๋ชปํ–ˆ์—ˆ์Šต๋‹ˆ๋‹คโ€ฆ

์ง„์งœ ์‹ค์ธก๋ฐ์ดํ„ฐ ์ž…๋‹ˆ๋‹ค.

1๊ฐœ์˜ ์ข‹์•„์š”