๐ AutoMapper ์ฌ์ฉ๋ฒ: ๊ฐ์ฒด ๊ฐ ๋งคํ ์๋ํ์ ์ ์ธ๊ณ ๐

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ C# ๊ฐ๋ฐ์๋ค์ ์ถ์ 180๋ ๋ฐ๊ฟ๋์ ๋ง๋ฒ ๊ฐ์ ๋๊ตฌ, AutoMapper์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ์ด ๊ธ์ ๋ค ์ฝ๊ณ ๋๋ฉด ์ฌ๋ฌ๋ถ๋ AutoMapper ๋ง์คํฐ๊ฐ ๋ ์ ์์ ๊ฑฐ์์! ๐
AutoMapper๋ ๊ฐ์ฒด ๊ฐ ๋งคํ์ ์๋ํํด์ฃผ๋ ์ด๊ฐ๋ ฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๋ฐ์, ์ด๊ฑธ ์ฌ์ฉํ๋ฉด ์ฝ๋ ์์ฑ ์๊ฐ๋ ์ค์ด๊ณ , ์ค์๋ ์ค์ด๊ณ , ๊ฐ๋ฐ์์ ์ถ์ ์ง๋ ์ฌ๋ผ๊ฐ๋ต๋๋ค. ใ ใ ใ
๊ทธ๋ผ ์ง๊ธ๋ถํฐ AutoMapper์ ์ธ๊ณ๋ก ํจ๊ป ๋น ์ ธ๋ณผ๊น์? ๐โโ๏ธ
๐ ์ ๊น! ์๋ ค๋๋ฆด๊ฒ์
์ด ๊ธ์ ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ '์ง์์ธ์ ์ฒ' ๋ฉ๋ด์์ ๋ง๋๋ณด์ค ์ ์์ด์. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ์ ์ฉํ ์ ๋ณด๋ฟ๋ง ์๋๋ผ ๋ค์ํ ์ฌ๋ฅ๋ ๊ฑฐ๋ํ ์ ์๋ต๋๋ค. ๊ฐ๋ฐ ๊ด๋ จ ๋์์ด ํ์ํ๋ค๋ฉด ์ฌ๋ฅ๋ท์ ํ ๋ฒ ๋๋ฌ๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์์!
๐ AutoMapper, ๋๋์ฒด ๋ญ๊ธธ๋?
์, ์ฌ๋ฌ๋ถ! AutoMapper๊ฐ ๋ญ์ง ๊ถ๊ธํ์์ฃ ? ๊ฐ๋จํ ๋งํด์ AutoMapper๋ ๊ฐ์ฒด์ ๊ฐ์ฒด ์ฌ์ด์ ํ๋กํผํฐ๋ฅผ ์๋์ผ๋ก ๋งคํํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์. ๋ญ ์๋ฆฌ๋๊ณ ์? ์ฝ๊ฒ ์ค๋ช ํด๋๋ฆด๊ฒ์! ๐
์๋ฅผ ๋ค์ด, ์ฐ๋ฆฌ๊ฐ ์ด๋ฐ ํด๋์ค๋ค์ ๊ฐ์ง๊ณ ์๋ค๊ณ ํด๋ณผ๊น์?
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
User ํด๋์ค์ ๊ฐ์ฒด๋ฅผ UserDto ํด๋์ค์ ๊ฐ์ฒด๋ก ๋ณํํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ๋ณดํต์ ์ด๋ ๊ฒ ํ์ฃ :
var user = new User { Id = 1, Name = "ํ๊ธธ๋", Email = "hong@example.com", BirthDate = new DateTime(1990, 1, 1) };
var userDto = new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email,
Age = DateTime.Now.Year - user.BirthDate.Year
};
์... ์ข ๊ท์ฐฎ์ฃ ? ๐ ํนํ ํ๋กํผํฐ๊ฐ ๋ง์์ง๋ฉด ๋ ๊ท์ฐฎ์์ ธ์. ์ฌ๊ธฐ์ AutoMapper์ ๋ฑ์ฅ! ์ง์~ ๐
AutoMapper๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๊ฐ๋จํด์ง๋๋ค:
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<user userdto>()
.ForMember(dest => dest.Age, opt => opt.MapFrom(src => DateTime.Now.Year - src.BirthDate.Year)));
var mapper = config.CreateMapper();
var user = new User { Id = 1, Name = "ํ๊ธธ๋", Email = "hong@example.com", BirthDate = new DateTime(1990, 1, 1) };
var userDto = mapper.Map<userdto>(user);
</userdto></user>
์์ฐ! ์ด๋ ๊ฒ ํ๋ฉด User ๊ฐ์ฒด์ ๋ชจ๋ ํ๋กํผํฐ๊ฐ ์๋์ผ๋ก UserDto๋ก ๋งคํ๋๊ณ , Age๊น์ง ๊ณ์ฐ๋์ด ๋ค์ด๊ฐ์. ์์ ์ ์ธ๊ณ ์๋๊ฐ์? ใ ใ ใ
์ด๊ฒ ๋ฐ๋ก AutoMapper์ ๋ง๋ฒ์ด์์. ๊ฐ์ฒด ๊ฐ ๋งคํ์ ์๋ํํด์ ์ฐ๋ฆฌ์ ์ฝ๋๋ฅผ ๋ ๊น๋ํ๊ณ , ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด์ฃผ๋ ๊ฑฐ์ฃ . ๐
๐ก ๊ฟํ
AutoMapper๋ ๋จ์ํ ๊ฐ์ฒด ๊ฐ ๋งคํ๋ง ํด์ฃผ๋ ๊ฒ ์๋์์. ๋ณต์กํ ๋งคํ ๊ท์น๋ ์ค์ ํ ์ ์๊ณ , ์ปฌ๋ ์ ๋งคํ, ์์ ๊ด๊ณ์ ์๋ ๊ฐ์ฒด ๋งคํ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ต๋๋ค. ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ๋์ค์ ์์ธํ ์์๋ณผ ๊ฑฐ์์!
์, ์ด์ AutoMapper๊ฐ ๋ญ์ง ๋์ถฉ ๊ฐ์ด ์ค์๋์? ๊ทธ๋ผ ์ด์ ๋ถํฐ ๋ณธ๊ฒฉ์ ์ผ๋ก AutoMapper์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ๊น์? ์ค๋น๋์ จ๋์? Let's go! ๐
๐ ๏ธ AutoMapper ์ค์นํ๊ธฐ: ์ฒซ ๊ฑธ์๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ
์, ์ด์ AutoMapper๋ฅผ ์ค์ ๋ก ์ฌ์ฉํด๋ณผ ์ฐจ๋ก์์. ๊ทผ๋ฐ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ ์ค์น๋ฅผ ํด์ผ๊ฒ ์ฃ ? ๊ฑฑ์ ๋ง์ธ์, ์์ฃผ ์ฌ์์! ๐
1. NuGet ํจํค์ง ๋งค๋์ ์ฌ์ฉํ๊ธฐ
Visual Studio๋ฅผ ์ฌ์ฉํ๊ณ ๊ณ์ ๋ค๋ฉด, NuGet ํจํค์ง ๋งค๋์ ๋ฅผ ํตํด ์ฝ๊ฒ AutoMapper๋ฅผ ์ค์นํ ์ ์์ด์. ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์์:
- ์๋ฃจ์ ํ์๊ธฐ์์ ํ๋ก์ ํธ๋ฅผ ์ฐํด๋ฆญํฉ๋๋ค.
- 'NuGet ํจํค์ง ๊ด๋ฆฌ'๋ฅผ ์ ํํด์.
- ๊ฒ์์ฐฝ์ 'AutoMapper'๋ฅผ ์ ๋ ฅํ๊ณ ๊ฒ์ํด์.
- AutoMapper ํจํค์ง๋ฅผ ์ฐพ์ '์ค์น' ๋ฒํผ์ ํด๋ฆญํด์.
์! ์ด๋ ๊ฒ ํ๋ฉด AutoMapper๊ฐ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ์ค์น๋ฉ๋๋ค. ์์ ์ฝ์ฃ ? ใ ใ ใ
2. ํจํค์ง ๋งค๋์ ์ฝ์ ์ฌ์ฉํ๊ธฐ
์ฝ์ ๋ช ๋ น์ด๋ฅผ ์ข์ํ์ ๋ค๋ฉด, ํจํค์ง ๋งค๋์ ์ฝ์์ ํตํด ์ค์นํ ์๋ ์์ด์. ๋ฐฉ๋ฒ์ ์ด๋ ์ต๋๋ค:
- Visual Studio์์ '๋๊ตฌ' > 'NuGet ํจํค์ง ๊ด๋ฆฌ์' > 'ํจํค์ง ๊ด๋ฆฌ์ ์ฝ์'์ ์ ํํด์.
- ์ฝ์ ์ฐฝ์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๊ณ Enter๋ฅผ ๋๋ฌ์:
Install-Package AutoMapper
์ง์~ ์ด๋ ๊ฒ ํ๋ฉด AutoMapper๊ฐ ์ค์น๋ฉ๋๋ค! ๐
3. .NET CLI ์ฌ์ฉํ๊ธฐ
.NET Core ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๊ณ ๊ณ์๋ค๋ฉด, .NET CLI๋ฅผ ํตํด ์ค์นํ ์๋ ์์ด์. ํฐ๋ฏธ๋์ด๋ ๋ช ๋ น ํ๋กฌํํธ๋ฅผ ์ด๊ณ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํ ํ, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์:
dotnet add package AutoMapper
์ด๋ ๊ฒ ํ๋ฉด AutoMapper๊ฐ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ์ถ๊ฐ๋ฉ๋๋ค. ์์ ๊ฐ๋จํ์ฃ ?
๐ ์ฃผ์์ฌํญ
AutoMapper๋ฅผ ์ค์นํ ๋๋ ํญ์ ์ต์ ๋ฒ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์์. ํ์ง๋ง ํ๋ก์ ํธ์ .NET ๋ฒ์ ๊ณผ ํธํ๋๋์ง ๊ผญ ํ์ธํด์ผ ํด์. ํธํ์ฑ ๋ฌธ์ ๋ก ๊ณจ์น ์ํ์ง ์ ์๊ฑฐ๋ ์! ๐
์, ์ด์ AutoMapper๋ฅผ ์ค์นํ์ด์. ์ด๋์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
์ด์ ์ฐ๋ฆฌ๋ AutoMapper๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ์๋ฃ๋์ด์. ๋ค์ ๋จ๊ณ์์๋ AutoMapper๋ฅผ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์์๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ํน์ ๊ฐ๋ฐ ๊ด๋ จํด์ ๋์์ด ๋ ํ์ํ์ ๊ฐ์? ๊ทธ๋ ๋ค๋ฉด ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ ํ ๋ฒ ๋ฐฉ๋ฌธํด๋ณด์ธ์. ๋ค์ํ ๊ฐ๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ๊ฐ์ง ๋ถ๋ค๊ณผ ์ฐ๊ฒฐ๋ ์ ์๋ต๋๋ค. ์ฌ๋ฌ๋ถ์ ๊ฐ๋ฐ ์ฌ์ ์ ํฐ ๋์์ด ๋ ๊ฑฐ์์! ๐จโ๐ป๐ฉโ๐ป
์, ๊ทธ๋ผ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ณผ๊น์? AutoMapper๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ ์ฐจ๋ก์์. ์ค๋น๋์ จ๋์? Let's go! ๐
๐จ AutoMapper ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ: ์ฒซ ๋งคํ ๋ง๋ค๊ธฐ
์, ์ด์ AutoMapper๋ฅผ ์ค์นํ์ผ๋ ์ค์ ๋ก ์ฌ์ฉํด๋ณผ ์ฐจ๋ก์์. ์ด๋ป๊ฒ ํ๋์ง ๊ถ๊ธํ์์ฃ ? ๊ฑฑ์ ๋ง์ธ์, ์ ๊ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ค๋ช ํด๋๋ฆด๊ฒ์! ๐
1. ๋งคํ ์ค์ ํ๊ธฐ
AutoMapper๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ ๋งคํ ์ค์ ์ ํด์ผ ํด์. ์ด๊ฑด ์ฐ๋ฆฌ๊ฐ ์ด๋ค ๊ฐ์ฒด๋ฅผ ์ด๋ค ๊ฐ์ฒด๋ก ๋ณํํ ์ง AutoMapper์๊ฒ ์๋ ค์ฃผ๋ ๊ณผ์ ์ด์์. ์ฝ๋๋ก ๋ณด๋ฉด ์ด๋ ๊ฒ ์๊ฒผ์ด์:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<source destination>();
});
IMapper mapper = config.CreateMapper();
</source>
์ฌ๊ธฐ์ Source๋ ์๋ณธ ๊ฐ์ฒด ํ์ ์ด๊ณ , Destination์ ๋ณํํ๊ณ ์ ํ๋ ๋์ ๊ฐ์ฒด ํ์ ์ด์์. ์ด๋ ๊ฒ ํ๋ฉด AutoMapper๋ Source ํ์ ์ ๊ฐ์ฒด๋ฅผ Destination ํ์ ์ ๊ฐ์ฒด๋ก ๋ณํํ ์ค๋น๋ฅผ ๋ง์น๊ฒ ๋ผ์.
2. ๊ฐ์ฒด ๋งคํํ๊ธฐ
๋งคํ ์ค์ ์ ๋ง์ณค๋ค๋ฉด, ์ด์ ์ค์ ๋ก ๊ฐ์ฒด๋ฅผ ๋งคํํ ์ ์์ด์. ๋ฐฉ๋ฒ์ ์์ฃผ ๊ฐ๋จํด์:
var source = new Source { /* ์์ฑ ์ค์ */ };
var destination = mapper.Map<destination>(source);
</destination>
์ง์~ ์ด๋ ๊ฒ ํ๋ฉด source ๊ฐ์ฒด์ ๋ชจ๋ ์์ฑ์ด destination ๊ฐ์ฒด๋ก ์๋์ผ๋ก ๋ณต์ฌ๋ผ์. ์์ ์ ๊ธฐํ์ง ์๋์? ใ ใ ใ
3. ์ค์ ์์ ๋ก ๋ณด๊ธฐ
์, ์ด์ ์ค์ ์์ ๋ฅผ ํตํด ๋ ์์ธํ ์์๋ณผ๊น์? ์๊น ๋ดค๋ User์ UserDto ํด๋์ค๋ฅผ ๋ค์ ํ ๋ฒ ์ฌ์ฉํด๋ณผ๊ฒ์:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
// ๋งคํ ์ค์
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<user userdto>()
.ForMember(dest => dest.Age, opt => opt.MapFrom(src => DateTime.Now.Year - src.BirthDate.Year));
});
var mapper = config.CreateMapper();
// ๊ฐ์ฒด ์์ฑ
var user = new User
{
Id = 1,
Name = "ํ๊ธธ๋",
Email = "hong@example.com",
BirthDate = new DateTime(1990, 1, 1)
};
// ๋งคํ ์คํ
var userDto = mapper.Map<userdto>(user);
Console.WriteLine($"Id: {userDto.Id}");
Console.WriteLine($"Name: {userDto.Name}");
Console.WriteLine($"Email: {userDto.Email}");
Console.WriteLine($"Age: {userDto.Age}");
</userdto></user>
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์์:
Id: 1
Name: ํ๊ธธ๋
Email: hong@example.com
Age: 33
์์ฐ! User ๊ฐ์ฒด์ ๋ชจ๋ ์์ฑ์ด UserDto๋ก ์ ๋งคํ๋์๊ณ , ์ฌ์ง์ด Age๊น์ง ์๋์ผ๋ก ๊ณ์ฐ๋์ด ๋ค์ด๊ฐ์ด์. ์ด๊ฒ ๋ฐ๋ก AutoMapper์ ๊ฐ๋ ฅํ ํ์ด์์! ๐
๐ก ๊ฟํ
AutoMapper๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ ์ด๋ฆ์ ์์ฑ๋ผ๋ฆฌ ์๋์ผ๋ก ๋งคํํด์ค์. ํ์ง๋ง ์ ์์ ์ฒ๋ผ ForMember() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ์์ฑ์ ๋ํด ์ปค์คํ ๋งคํ ๊ท์น์ ์ ์ํ ์ ์์ด์. ์ด๋ฅผ ํตํด ๋ณต์กํ ๋ณํ ๋ก์ง๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ต๋๋ค!
์, ์ด๋ ์ธ์? AutoMapper์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ๋ฐฐ์๋ดค๋๋ฐ, ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
์ด์ ์ฌ๋ฌ๋ถ๋ AutoMapper๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ฒด ๊ฐ ๋งคํ์ ์ฝ๊ฒ ํ ์ ์์ ๊ฑฐ์์. ํ์ง๋ง ์ด๊ฑด ์์์ ๋ถ๊ณผํด์. AutoMapper์๋ ๋ ๋ง์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ด ์๋ต๋๋ค. ๋ค์ ์น์ ์์๋ ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ํน์ ์ด๋ฐ ๊ฐ๋ฐ ์ง์์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๋๋๊ณ ์ถ์ผ์ ๊ฐ์? ๊ทธ๋ ๋ค๋ฉด ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ ํ์ฉํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ์ฌ๋ฌ๋ถ์ ์ง์์ ๊ณต์ ํ๊ณ , ๋ค๋ฅธ ์ฌ๋๋ค์ ์ฌ๋ฅ๋ ๋ฐฐ์ธ ์ ์๋ ์ข์ ๊ธฐํ๊ฐ ๋ ๊ฑฐ์์! ๐จโ๐ซ๐ฉโ๐ซ
์, ๊ทธ๋ผ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ณผ๊น์? AutoMapper์ ๋ ๊น์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ ์๊ฐ์ด์์. ์ค๋น๋์ จ๋์? Let's dive deeper! ๐โโ๏ธ
๐ AutoMapper ๊ณ ๊ธ ๊ธฐ๋ฅ: ๋ ๊น์ด ๋ค์ด๊ฐ๋ณด์!
์, ์ด์ AutoMapper์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ จ์ผ๋ ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ ์ฐจ๋ก์์. AutoMapper์๋ ์ ๋ง ๋ค์ํ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ด ์๋ต๋๋ค. ์ด ๊ธฐ๋ฅ๋ค์ ์๋ฉด ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉ ์ค๋ ฅ์ด ํ ๋จ๊ณ ์ ๊ทธ๋ ์ด๋๋ ๊ฑฐ์์! ๐
1. ๋ณต์กํ ๋งคํ ๊ท์น ์ค์ ํ๊ธฐ
๋๋ก๋ ๋จ์ํ ์์ฑ ์ด๋ฆ์ด ๊ฐ๋ค๊ณ ํด์ ๋งคํ์ด ๋๋ ๊ฒ๋ง์ผ๋ก๋ ๋ถ์กฑํ ๋๊ฐ ์์ด์. ์ด๋ด ๋ ์ฌ์ฉํ๋ ๊ฒ ๋ฐ๋ก ๋ณต์กํ ๋งคํ ๊ท์น์ด์์.
cfg.CreateMap<source destination>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.FirstName + " " + src.LastName))
.ForMember(dest => dest.Age, opt => opt.MapFrom(src => DateTime.Now.Year - src.BirthDate.Year));
</source>
์ด๋ ๊ฒ ํ๋ฉด Source์ FirstName๊ณผ LastName์ ํฉ์ณ์ Destination์ FullName์ผ๋ก ๋งคํํ๊ณ , BirthDate๋ฅผ ์ด์ฉํด Age๋ฅผ ๊ณ์ฐํ ์ ์์ด์. ์์ ๋๋ํ์ฃ ? ใ ใ ใ
2. ์กฐ๊ฑด๋ถ ๋งคํ
ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋งคํ์ ๋ค๋ฅด๊ฒ ํ๊ณ ์ถ์ ๋๊ฐ ์์ฃ ? ์ด๋ด ๋๋ ์กฐ๊ฑด๋ถ ๋งคํ์ ์ฌ์ฉํด์.
cfg.CreateMap<source destination>()
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Age < 18 ? "Minor" : "Adult"))
.ForMember(dest => dest.CanVote, opt => opt.Condition(src => src.Country == "USA"));
</source>
์ด๋ ๊ฒ ํ๋ฉด ๋์ด์ ๋ฐ๋ผ Status๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํ๊ณ , ๊ตญ๊ฐ๊ฐ USA์ผ ๋๋ง CanVote ์์ฑ์ ๋งคํํ ์ ์์ด์. ์์ ์ ์ฐํ์ฃ ? ๐
3. ์๋ฐฉํฅ ๋งคํ
๋ณดํต์ A์์ B๋ก ๋งคํํ์ง๋ง, ๋๋ก๋ B์์ A๋ก๋ ๋งคํํด์ผ ํ ๋๊ฐ ์์ด์. ์ด๋ด ๋๋ ์๋ฐฉํฅ ๋งคํ์ ์ฌ์ฉํด์.
cfg.CreateMap<source destination>()
.ReverseMap();
</source>
์ด๋ ๊ฒ ํ๋ฉด Source์์ Destination์ผ๋ก, Destination์์ Source๋ก์ ๋งคํ์ด ๋ชจ๋ ๊ฐ๋ฅํด์ ธ์. ์๋ฐฉํฅ ์ํต์ด ๊ฐ๋ฅํด์ง๋ ๊ฑฐ์ฃ ! ๐ฅ
4. ์์ ๊ด๊ณ ๋งคํ
๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์์๋ ์์์ด ์ค์ํ์ฃ ? AutoMapper๋ ์์ ๊ด๊ณ๋ฅผ ์ ์ฒ๋ฆฌํ ์ ์์ด์.
cfg.CreateMap<animal animaldto>()
.Include<dog dogdto>()
.Include<cat catdto>();
cfg.CreateMap<dog dogdto>();
cfg.CreateMap<cat catdto>();
</cat></dog></cat></dog></animal>
์ด๋ ๊ฒ ํ๋ฉด Animal์ AnimalDto๋ก ๋งคํํ ๋, Dog์ Cat ๊ฐ์ฒด๋ ์๋ง๊ฒ ์ฒ๋ฆฌํ ์ ์์ด์. ์์ ๊ด๊ณ๋ ๋ฌธ์ ์์ด ๋งคํ! ๐จโ๐ฉโ๐งโ๐ฆ
5. ์ปฌ๋ ์ ๋งคํ
๊ฐ์ฒด ํ๋๋ง ๋งคํํ๋ ๊ฒ ์๋๋ผ ๋ฆฌ์คํธ๋ ๋ฐฐ์ด ๊ฐ์ ์ปฌ๋ ์ ์ ๋งคํํด์ผ ํ ๋๋ ์์ฃ ? AutoMapper๋ ์ด๊ฒ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ด์.
var sourceList = new List<source> { /* ์์ค ๊ฐ์ฒด๋ค */ };
var destinationList = mapper.Map<list>>(sourceList);
</list></source>
์ด๋ ๊ฒ ํ๋ฉด ์์ค ๋ฆฌ์คํธ์ ๊ฐ ์์๊ฐ ๋์ ํ์ ์ผ๋ก ๋ณํ๋์ด ์๋ก์ด ๋ฆฌ์คํธ๊ฐ ๋ง๋ค์ด์ ธ์. ๋ฆฌ์คํธ๋ ํ ๋ฒ์ ๋ณ์ ! ๐
6. ๋์ ๋งคํ
๋๋ก๋ ๋งคํ ์ค์ ์ ๋ฏธ๋ฆฌ ํ์ง ์๊ณ , ๋ฐํ์์ ๋์ ์ผ๋ก ๋งคํ์ ์ํํด์ผ ํ ๋๊ฐ ์์ด์. AutoMapper๋ ์ด๋ฐ ์ํฉ๋ ์ง์ํด์.
var source = new ExpandoObject();
source.FirstName = "John";
source.LastName = "Doe";
var destination = mapper.Map<destination>(source);
</destination>
์ด๋ ๊ฒ ํ๋ฉด ๋์ ๊ฐ์ฒด๋ ๋งคํํ ์ ์์ด์. ๋ฐํ์์ ๊ฐ์ฒด์ ๊ตฌ์กฐ๊ฐ ๊ฒฐ์ ๋๋๋ผ๋ ๋ฌธ์ ์์ฃ ! ๋์ ์ด๊ณ ์ ์ฐํด! ๐คธโโ๏ธ
๐ก ๊ฟํ
AutoMapper์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ๋๋ ํญ์ ์ฑ๋ฅ์ ๊ณ ๋ คํด์ผ ํด์. ๋ณต์กํ ๋งคํ ๊ท์น์ด๋ ๋์ ๋งคํ์ ํธ๋ฆฌํ์ง๋ง, ๋๋ก๋ ์ฑ๋ฅ ์ ํ๋ฅผ ์ผ์ผํฌ ์ ์์ด์. ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๊ณ , ๊ฐ๋ฅํ๋ฉด ๊ฐ๋จํ ๋งคํ์ ์ ์งํ๋ ๊ฒ์ด ์ข๋ต๋๋ค!
์ด๋์? AutoMapper์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ดค๋๋ฐ, ์ ๋ง ๋ค์ํ๊ณ ๊ฐ๋ ฅํ์ฃ ? ใ ใ ใ
์ด๋ฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ ๋์ฑ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํด์ง ๊ฑฐ์์. ํ์ง๋ง ๋๋ฌด ๋ณต์กํ๊ฒ ๋ง๋ค์ง ์๋๋ก ์ฃผ์ํด์ผ ํด์. ๋จ์ํจ์ด ๋๋ก๋ ์ต๊ณ ์ ๋ฏธ๋์ด๋๋๋ค! ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ์ด๋ฐ ๊ณ ๊ธ ๊ธฐ์ ์ ์ตํ๋ค ๋ณด๋ฉด ๋๋ก๋ ๋งํ๋ ๋ถ๋ถ์ด ์์ ์ ์์ด์. ๊ทธ๋ด ๋๋ ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ ํ์ฉํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ ๋์์ ๋ฐ์ ์ ์๊ณ , ์ฌ๋ฌ๋ถ์ ์ง์๋ ๋๋ ์ ์๋ ์ข์ ๊ธฐํ๊ฐ ๋ ๊ฑฐ์์! ๐ก
์, ์ด์ AutoMapper์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค๋ ์ดํด๋ดค์ด์. ๋ค์ ์น์ ์์๋ AutoMapper๋ฅผ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ฃผ์ํด์ผ ํ ์ ์ ๋ฌด์์ธ์ง ์์๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? Let's go to the next level! ๐
๐๏ธ ์ค์ ํ๋ก์ ํธ์์ AutoMapper ํ์ฉํ๊ธฐ
์, ์ด์ AutoMapper์ ๊ธฐ๋ณธ๋ถํฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๊น์ง ๋ค ๋ฐฐ์ ์ด์. ๊ทผ๋ฐ ์ด๊ฑธ ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ป๊ฒ ํ์ฉํด์ผ ํ ๊น์? ๊ฑฑ์ ๋ง์ธ์, ์ ๊ฐ ๋ค ์๋ ค๋๋ฆด๊ฒ์! ๐
1. ์์กด์ฑ ์ฃผ์ (Dependency Injection) ํ์ฉํ๊ธฐ
์ค์ ํ๋ก์ ํธ์์๋ AutoMapper๋ฅผ ์์กด์ฑ ์ฃผ์ ์ ํตํด ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์์. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๊ณ ํ ์คํธํ๊ธฐ ์ฌ์์ง๋ต๋๋ค.
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper(typeof(Startup));
}
// ์ฌ์ฉํ ํด๋์ค์์
public class UserService
{
private readonly IMapper _mapper;
public UserService(IMapper mapper)
{
_mapper = mapper;
}
public UserDto GetUser(int id)
{
var user = // ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง
return _mapper.Map<userdto>(user);
}
}
</userdto>
์ด๋ ๊ฒ ํ๋ฉด AutoMapper๋ฅผ ์๋น์ค๋ก ๋ฑ๋กํ๊ณ , ํ์ํ ๊ณณ์์ ์ฃผ์ ๋ฐ์ ์ฌ์ฉํ ์ ์์ด์. ๊น๋ํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ข์ ์ฝ๋๊ฐ ๋๋ ๊ฑฐ์ฃ ! ๐
2. ํ๋กํ(Profile) ์ฌ์ฉํ๊ธฐ
๋งคํ ์ค์ ์ด ๋ง์์ง๋ฉด ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์์ง ์ ์์ด์. ์ด๋ด ๋๋ AutoMapper์ Profile ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ข์์.
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<user userdto>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
.ForMember(dest => dest.Age, opt => opt.MapFrom(src => DateTime.Now.Year - src.BirthDate.Year));
CreateMap<userdto user>();
}
}
// Startup.cs
services.AddAutoMapper(typeof(Startup));
</userdto></user>
์ด๋ ๊ฒ ํ๋ฉด ๋งคํ ์ค์ ์ ๊น๋ํ๊ฒ ๊ด๋ฆฌํ ์ ์์ด์. ํ๋กํ๋ณ๋ก ๋งคํ์ ๊ตฌ๋ถํ๋๊น ์ฝ๋๋ ๋ ์ฝ๊ธฐ ์ฌ์์ง์ฃ ! ๐
3. ์ ํจ์ฑ ๊ฒ์ฌ ์ถ๊ฐํ๊ธฐ
๋งคํ ๊ณผ์ ์์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ถ๊ฐํ๋ฉด ๋ ์์ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด์.
CreateMap<source destination>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.Age, opt => {
opt.PreCondition(src => src.Age > 0);
opt.MapFrom(src => src.Age);
});
</source>
์ด๋ ๊ฒ ํ๋ฉด Age๊ฐ 0๋ณด๋ค ํฐ ๊ฒฝ์ฐ์๋ง ๋งคํ์ด ์ด๋ฃจ์ด์ ธ์. ์๋ชป๋ ๋ฐ์ดํฐ๊ฐ ๋ค์ด๊ฐ๋ ๊ฑธ ๋ฐฉ์งํ ์ ์์ฃ ! ์์ ์ ์ผ! ๐ก๏ธ
4. ์ฑ๋ฅ ์ต์ ํํ๊ธฐ
AutoMapper๋ ํธ๋ฆฌํ์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ด์. ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๋ต๋๋ค.
- ๋งคํ ์ค์ ์ ์ฑ ์์ ์ ํ ๋ฒ๋ง ํ์ธ์.
- ๋ณต์กํ ๋งคํ์ ํผํ๊ณ , ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ์ธ์.
- ๋๋์ ๋ฐ์ดํฐ๋ฅผ ๋งคํํ ๋๋ ProjectTo๋ฅผ ์ฌ์ฉํ์ธ์.
var users = dbContext.Users.ProjectTo<userdto>(_mapper.ConfigurationProvider).ToList();
</userdto>
์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ๋จ๊ณ์์ ๋งคํ์ด ์ด๋ฃจ์ด์ ธ์ ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋ผ์! ๋น ๋ฅธ ๊ฒ์ด ์ข์ ๊ฑฐ์ผ~ ๐
5. ๋จ์ ํ ์คํธ ์์ฑํ๊ธฐ
AutoMapper๋ฅผ ์ฌ์ฉํ ๋๋ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ค์ํด์. ๋งคํ์ด ์ ๋๋ก ์ด๋ฃจ์ด์ง๋์ง ํ์ธํ ์ ์๊ฑฐ๋ ์.
[Fact]
public void AutoMapper_Configuration_IsValid()
{
var config = new MapperConfiguration(cfg => cfg.AddProfile<userprofile>());
config.AssertConfigurationIsValid();
}
[Fact]
public void Map_User_To_UserDto_IsCorrect()
{
// Arrange
var user = new User { Id = 1, FirstName = "John", LastName = "Doe", BirthDate = new DateTime(1990, 1, 1) };
var mapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<userprofile>()));
// Act
var userDto = mapper.Map<userdto>(user);
// Assert
Assert.Equal(1, userDto.Id);
Assert.Equal("John Doe", userDto.FullName);
Assert.Equal(DateTime.Now.Year - 1990, userDto.Age);
}
</userdto></userprofile></userprofile>
์ด๋ ๊ฒ ํ ์คํธ๋ฅผ ์์ฑํ๋ฉด ๋งคํ ์ค์ ์ ๋ฌธ์ ๊ฐ ์๋์ง, ์ค์ ๋ก ๋งคํ์ด ์ ๋๋ก ์ด๋ฃจ์ด์ง๋์ง ํ์ธํ ์ ์์ด์. ํ ์คํธ๋ ์ฌ๋์ ๋๋ค~ โค๏ธ
๐ก ๊ฟํ
AutoMapper๋ฅผ ์ฌ์ฉํ ๋๋ ํญ์ 'Convention over Configuration' ์์น์ ๊ธฐ์ตํ์ธ์. ๊ฐ๋ฅํ ํ ๊ธฐ๋ณธ ๊ท์น์ ๋ฐ๋ฅด๊ณ , ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ปค์คํ ๋งคํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์์. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๊ฐ ๋ ๊ฐ๊ฒฐํด์ง๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์์ง๋ต๋๋ค!
์, ์ด์ AutoMapper๋ฅผ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉํ๋์ง ์์๋ดค์ด์. ์ด๋์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
์ด๋ ๊ฒ AutoMapper๋ฅผ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ํ์ง๋ ๋์์ง๊ณ , ๊ฐ๋ฐ ์๊ฐ๋ ๋จ์ถํ ์ ์์ด์. ํ์ง๋ง ํญ์ ์ฃผ์ํด์ผ ํ ์ ์ ์์ด์. ๋๋ฌด ๋ณต์กํ ๋งคํ์ ์คํ๋ ค ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ผ๋, ์ ์ ํ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํด์!
๊ทธ๋ฆฌ๊ณ ์ ๊น! ํน์ ์ด๋ฐ ์ค์ ํ๋ก์ ํธ ๊ฒฝํ์ ๋ ์๊ณ ์ถ์ผ์ ๊ฐ์? ๊ทธ๋ ๋ค๋ฉด ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ ํ์ฉํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ์ค์ ํ๋ก์ ํธ์ ์ฐธ์ฌํ๊ฑฐ๋, ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ๊ฒฝํ์ ๊ณต์ ํ ์ ์๋ ์ข์ ๊ธฐํ๊ฐ ๋ ๊ฑฐ์์! ๐
์, ์ด์ ์ฐ๋ฆฌ์ AutoMapper ์ฌํ์ด ๊ฑฐ์ ๋๋๊ฐ๊ณ ์์ด์. ๋ง์ง๋ง์ผ๋ก AutoMapper ์ฌ์ฉ ์ ์ฃผ์ํด์ผ ํ ์ ๋ค๊ณผ ๋ช ๊ฐ์ง ํ์ ์ ๋ฆฌํด๋ณผ๊น์? ์ค๋น๋์ จ๋์? Let's wrap it up! ๐
๐ฏ AutoMapper ์ฌ์ฉ ์ ์ฃผ์์ฌํญ ๋ฐ ํ
์, ์ด์ AutoMapper์ ๊ฑฐ์ ๋ชจ๋ ๊ฒ์ ๋ฐฐ์ ์ด์. ํ์ง๋ง ์ ๊น! AutoMapper๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค์ด ์์ด์. ์ด ์ ๋ค๋ง ์ ๊ธฐ์ตํ๋ฉด ์ฌ๋ฌ๋ถ์ ์ง์ ํ AutoMapper ๋ง์คํฐ๊ฐ ๋ ์ ์์ ๊ฑฐ์์! ๐
1. ์ฑ๋ฅ์ ์ฃผ์ํ์ธ์
AutoMapper๋ ํธ๋ฆฌํ์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ ์ ํ์ ์์ธ์ด ๋ ์ ์์ด์.
- ๋งคํ ์ค์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ํ ๋ฒ๋ง ํ์ธ์.
- ๋ณต์กํ ๋งคํ์ ํผํ๊ณ , ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ์ธ์.
- ๋๋์ ๋ฐ์ดํฐ๋ฅผ ๋งคํํ ๋๋ ProjectTo๋ฅผ ์ฌ์ฉํ์ธ์.
์ด๋ ๊ฒ ํ๋ฉด AutoMapper๋ฅผ ์ฌ์ฉํ๋ฉด์๋ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์์ด์. ๋น ๋ฅธ ๊ฒ ์ข์์์? ๐
2. ๋งคํ ๊ท์น์ ๋ช ํํ๊ฒ
๋ณต์กํ ๋งคํ ๊ท์น์ ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ด์. ๊ฐ๋ฅํ ํ ๊ฐ๋จํ๊ณ ๋ช ํํ ๋งคํ ๊ท์น์ ์ฌ์ฉํ์ธ์.
// ์ข์ ์
CreateMap<source destination>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"));
// ๋์ ์
CreateMap<source destination>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src =>
src.Title + " " + src.FirstName + " " + src.MiddleName + " " + src.LastName + " " + src.Suffix));
</source></source>
๊ฐ๋จํ๊ณ ๋ช ํํ ๋งคํ ๊ท์น์ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ฌ์์ ธ์. ๋จ์ํจ์ด ์ต๊ณ ! ๐
3. Null ๊ฐ ์ฒ๋ฆฌ์ ์ฃผ์ํ์ธ์
๋งคํ ๊ณผ์ ์์ Null ๊ฐ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ๋ช ํํ ์ ์ํด์ผ ํด์. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์์น ๋ชปํ NullReferenceException์ด ๋ฐ์ํ ์ ์์ด์.
CreateMap<source destination>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name ?? "Unknown"));
</source>
์ด๋ ๊ฒ Null ๊ฐ์ ๋ช ์์ ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด ์์ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด์. ์์ ์ ์ผ! ๐ก๏ธ
4. ์๋ฐฉํฅ ๋งคํ์ ์ ์คํ๊ฒ
ReverseMap์ ์ฌ์ฉํ ์๋ฐฉํฅ ๋งคํ์ ํธ๋ฆฌํ์ง๋ง, ๋๋ก๋ ์์์น ๋ชปํ ๊ฒฐ๊ณผ๋ฅผ ๋ณ์ ์ ์์ด์. ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ์ธ์.
CreateMap<source destination>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
.ReverseMap()
.ForMember(src => src.FirstName, opt => opt.Ignore())
.ForMember(src => src.LastName, opt => opt.Ignore());
</source>
์ด๋ ๊ฒ ReverseMap์ ์ฌ์ฉํ ๋๋ ๋งคํ ๊ท์น์ ๋ช ํํ ์ ์ํด์ผ ํด์. ์๋ฐฉํฅ์ด๋ผ๊ณ ๋ค ์ข์ ๊ฑด ์๋์์! โ๏ธ
5. ๋ฒ์ ๊ด๋ฆฌ์ ์ฃผ์ํ์ธ์
AutoMapper์ ๋ฒ์ ์ด ๋ณ๊ฒฝ๋๋ฉด ๋งคํ ๋์์ด ๋ฌ๋ผ์ง ์ ์์ด์. ํญ์ ์ต์ ๋ฒ์ ์ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ธํ๊ณ , ํ์ํ๋ค๋ฉด ๋งคํ ์ค์ ์ ์ ๋ฐ์ดํธํ์ธ์.
๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ ํ๋ฉด ์์์น ๋ชปํ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ ์ ์์ด์. ์ต์ ์ด ์ข๊ธด ํ๋ฐ, ์ ์คํ๊ฒ! ๐ต๏ธโโ๏ธ
6. ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ์ธ์
AutoMapper ์ค์ ์ด ์ฌ๋ฐ๋ฅธ์ง ํ์ธํ๊ธฐ ์ํด ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ์ธ์. ํนํ ๋ณต์กํ ๋งคํ ๊ท์น์ด ์๋ ๊ฒฝ์ฐ์๋ ๋์ฑ ์ค์ํด์.
[Fact]
public void AutoMapper_Configuration_IsValid()
{
var config = new MapperConfiguration(cfg => cfg.AddProfile<myprofile>());
config.AssertConfigurationIsValid();
}
</myprofile>
๋จ์ ํ ์คํธ๋ฅผ ํตํด ๋งคํ ์ค์ ์ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ๊ฒฌํ ์ ์์ด์. ํ ์คํธ๋ ์ฌ๋์ ๋๋ค~ โค๏ธ
๐ก ์ต์ข ๊ฟํ
AutoMapper๋ฅผ ์ฌ์ฉํ ๋๋ ํญ์ 'KISS' ์์น์ ๊ธฐ์ตํ์ธ์. Keep It Simple, Stupid! ๊ฐ๋ฅํ ํ ๊ฐ๋จํ๊ฒ ์ ์งํ๊ณ , ๋ณต์กํ ๋งคํ์ ํผํ์ธ์. ๊ทธ๋ฆฌ๊ณ ํญ์ ์ฑ๋ฅ๊ณผ ๊ฐ๋ ์ฑ ์ฌ์ด์ ๊ท ํ์ ์ ์งํ๋ ๊ฒ์ด ์ค์ํด์. ์ด๋ ๊ฒ ํ๋ฉด AutoMapper์ ์ง์ ํ ํ์ ๋๋ ์ ์์ ๊ฑฐ์์!
์, ์ด์ ์ ๋ง AutoMapper์ ๋ชจ๋ ๊ฒ์ ๋ฐฐ์ ์ด์. ์ด๋ ์ธ์? ์๊ฐ๋ณด๋ค ๋ง์ ๋ด์ฉ์ด์์ฃ ? ใ ใ ใ
ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์. ์ด ๋ชจ๋ ๋ด์ฉ์ ํ ๋ฒ์ ์๋ฒฝํ๊ฒ ์ดํดํ๊ณ ์ ์ฉํ๊ธฐ๋ ์ด๋ ค์์. ์ค์ํ ๊ฑด ์ด๋ฐ ์ ๋ค์ ์๊ณ ์๋ค๋ ๊ฑฐ์์. ์ค์ ๋ก ํ๋ก์ ํธ์ ์ ์ฉํ๋ฉด์ ํ๋์ฉ ์ตํ๋๊ฐ๋ฉด ๋ผ์.
๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์! ๊ฐ๋ฐ์ ํผ์ ํ๋ ๊ฒ ์๋์์. ์ด๋ ค์ด ์ ์ด ์๋ค๋ฉด ์ธ์ ๋ ๋๋ฃ๋ค์๊ฒ ๋ฌผ์ด๋ณด๊ฑฐ๋, ์ฌ๋ฅ๋ท(https://www.jaenung.net) ๊ฐ์ ํ๋ซํผ์ ํตํด ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ ๋์์ ๋ฐ์ ์ ์์ด์. ํจ๊ป ์ฑ์ฅํ๋ ๊ฒ ๊ฐ์ฅ ๋น ๋ฅธ ๊ธธ์ด๋๋๋ค! ๐ฑ
์, ์ด์ ์ฌ๋ฌ๋ถ์ AutoMapper์ ์ง์ ํ ๋ง์คํฐ๊ฐ ๋์์ด์. ์ด ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ํ์ฉํด์ ๋ฉ์ง ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ ๋์ฑ ๊น๋ํ๊ณ ํจ์จ์ ์ผ๋ก ๋ณํ ๊ฑฐ์์. ํ์ดํ ! ๐ช
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ