๐ Entity์์ DTO๋ก: ์ธ ๊ฐ์ง ๋งคํ ๋ฐฉ์์ ์ฑ๋ฅ ๋น๊ต
๐ฏ ๋ค์ด๊ฐ๋ฉฐ
์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ ธ์ถํ ๋ DTO๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ง์ ์ฅ์ ์ด ์์ด ๊ฐ๋ ฅํ ๊ถ์ฅ๋ฉ๋๋ค. ๋ ธ์ถ๋๋ ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ถํฐ ์ฑ๋ฅ ๋ฐ ๋ณด์ ๋ฌธ์ ๊น์ง, DTO๋ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ๋์ ์์ด์ผ ํฉ๋๋ค.
ํ์ง๋ง DTO์๋ ์ค์ํ ๋จ์ ์ด ํ๋ ์์ต๋๋ค โ ๏ธ: ํญ์ ์ํฐํฐ์ DTO ๊ฐ์ ๋ณํ์ด ํ์ํ๋ค๋ ์ ์ ๋๋ค. ์ด๋ ์ถ๊ฐ์ ์ธ ๋ณต์ก์ฑ์ ๊ฐ์ ธ์ต๋๋ค.
๐ก ์ด ๊ธ์์๋ Entity๋ฅผ DTO๋ก ๋ณํํ๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ณ , ๊ทธ ์ค ์ด๋ค ๊ฒ์ด ๊ฐ์ฅ ์ฑ๋ฅ์ด ์ข์์ง ์ฐพ์๋ณด๊ฒ ์ต๋๋ค.
๐ ๏ธ ๋งคํ ๊ธฐ๋ฒ
์ด๋ฒ ๊ธ์์ ๋น๊ตํ ๋งคํ ์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1๏ธโฃ Manual mapping (์๋ ๋งคํ)
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฒ์ผ๋ก, ๊ฐ๋ฐ์๊ฐ Entity์ ํ๋๋ฅผ DTO๋ก ์๋์ผ๋ก ๋งคํํฉ๋๋ค.
2๏ธโฃ MapStruct
์๋ ๋ฐฉ์๊ณผ ์ ์ฌํ์ง๋ง ์๋์ผ๋ก ์ด๋ฃจ์ด์ง๋ฉฐ, ๊ฐ๋ฐ์๊ฐ ํ๋๋ฅผ ์๋์ผ๋ก ๋งคํํ ํ์๊ฐ ์์ต๋๋ค.
3๏ธโฃ JPQL
JPQL์ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ์์ ์ง์ Entity๋ฅผ DTO๋ก ๋ณํํ ์ ์์ต๋๋ค.
๊ฐ ์ ๊ทผ ๋ฐฉ์์๋ ์ฅ๋จ์ ์ด ์์ผ๋ฉฐ, ์ด๋ค ๊ฒ์ ์ฌ์ฉํ ์ง๋ ๊ฐ๋ฐ์ ๋ณต์ก์ฑ์ด๋ ์ํคํ ์ฒ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค ๐ค
โ๏ธ ๋น๊ต ์คํ
์ด์ ๋ ๊ฐ์ง ์๋๋ฆฌ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ธ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ์ฑ๋ฅ์ ๋น๊ตํด๋ณด๊ฒ ์ต๋๋ค:
- ๊ฐ๋จํ ์๋๋ฆฌ์ค
- ๋ณต์กํ ์๋๋ฆฌ์ค
๐ ๊ฐ๋จํ ์๋๋ฆฌ์ค
์คํ์ ๋ค๋ฅธ ์ํฐํฐ์ ๊ด๊ณ๊ฐ ์๋ ๊ฐ๋จํ ์ํฐํฐ๋ก ์์ํฉ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์๋ 1000๊ฐ์ ์ฑ ์ด ์ฝ์ ๋์ด ์์ต๋๋ค.
Book ์ํฐํฐ๋ ๋ค์๊ณผ ๊ฐ์ ํ๋๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค:
- id (๊ณ ์ ์๋ณ์)
- name (์ฑ ์ด๋ฆ)
- author (์ ์)
- releaseDate (์ถํ์ผ)
- numberOfPages (ํ์ด์ง ์)
- language (์ธ์ด)
BookDTO๋ ์ํฐํฐ์ ๋์ผํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค.
์ธ ๊ฐ์ง ๋งคํ ๋ฐฉ์ ๋ชจ๋ BookDTO ๋ฆฌ์คํธ๋ฅผ ๋ฐํํฉ๋๋ค. ๊ฐ ์๋๋ฆฌ์ค๋ง๋ค 100๋ฒ์ ์์ฒญ์ ์คํํ๊ณ , ๋ค์์ ๊ฐ๊ฐ์ ํ๊ท ์คํ ์๊ฐ(ms)์ ๋๋ค:
๐ ์ฑ๋ฅ ๊ฒฐ๊ณผ:
- โ Manual ๋ฐฉ์: 11ms
- ๐ง MapStruct ๋ฐฉ์: 10ms
- ๐ JPQL ๋ฐฉ์: 8ms
๋ณด์๋ค์ํผ, ์ธ ๋ฐฉ์ ๊ฐ์ ์ฐจ์ด๋ ๋ฏธ๋ฏธํฉ๋๋ค. JPQL ๋ฒ์ ์ด ์ฝ๊ฐ ๋ ๋น ๋ฅด์ง๋ง ํฐ ์ฐจ์ด๋ ์์ต๋๋ค.
๐ ๋ณต์กํ ์๋๋ฆฌ์ค
์ด์ ์ํฐํฐ์ @ManyToOne ๊ด๊ณ๋ฅผ ์ถ๊ฐํ์ฌ ์กฐ๊ธ ๋ ๋ณต์กํ๊ฒ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค. ๊ฐ Book์ ์ด์ Publisher๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
Publisher ์ํฐํฐ ํ๋:
- id (๊ณ ์ ์๋ณ์)
- name (์ถํ์ฌ ์ด๋ฆ)
- since (์ค๋ฆฝ์ผ)
- address (์ฃผ์)
- country (๊ตญ๊ฐ)
BookDTO๋ ์ด์ PublisherDTO๋ฅผ ํฌํจํ๋๋ก ๋ณ๊ฒฝ๋์์ต๋๋ค.
100๋ฒ์ ์์ฒญ์ ๋ค์ ์คํํ ๊ฒฐ๊ณผ:
๐ ์ฑ๋ฅ ๊ฒฐ๊ณผ:
- โ Manual ๋ฐฉ์: 472ms ๐ฑ
- ๐ง MapStruct ๋ฐฉ์: 494ms ๐ฑ
- ๐ JPQL ๋ฐฉ์: 19ms โก
์ด๋ฒ์๋ ์ฐจ์ด๊ฐ ํ์ฐํฉ๋๋ค! JPQL ์ต์ ์ด ๋ค๋ฅธ ๋ ์ต์ ๋ณด๋ค ํจ์ฌ ๋ ๋์ ์ฑ๋ฅ์ ๋ณด์์ต๋๋ค. Manual๊ณผ MapStruct๋ ๋น์ทํ ์ฑ๋ฅ์ ๋ณด์์ง๋ง... ์ฐจ์ด๊ฐ ๋๋ฌด ํฌ์ง ์๋์? ๐ค ์ข ๋ ๋ถ์ํด๋ด ์๋ค!
๐ N+1 ๋ฌธ์ ๋ฐ๊ฒฌ!
Manual๊ณผ MapStruct ๋ฒ์ ๋ชจ๋ JpaRepository์ findAll() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค. ๋ํ publisher์ fetch ํ์
์ด FetchType.LAZY๋ก ์ค์ ๋์ด ์์ด์, ์ฌ๊ธฐ์ N+1 ๋ฌธ์ ๊ฐ ์์์ต๋๋ค! ๐ต
์ด๋ ๊ฐ fetch๋ง๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค์ 1001๋ฒ์ select๊ฐ ๋ฐ์ํ๋ค๋ ์๋ฏธ์ ๋๋ค:
- ๐ 1๋ฒ: ๋ชจ๋ ์ฑ ์ ๊ฐ์ ธ์ค๋ select
- ๐ 1000๋ฒ: ๊ฐ ์ฑ ์ ์ถํ์ฌ๋ฅผ ๊ฐ์ ธ์ค๋ select (์ฑ ์ด 1000๊ฐ์์ผ๋ฏ๋ก)
๐ ๏ธ N+1 ๋ฌธ์ ํด๊ฒฐ
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด @Query์ JOIN FETCH๋ฅผ ์ฌ์ฉํ ์๋ก์ด ๋ฉ์๋๋ก ๊ต์ฒดํ์ต๋๋ค:
@Query("SELECT b FROM Book b JOIN FETCH b.publisher")
List<Book> findAllWithPublisher();
์ด ๋ณ๊ฒฝ ํ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ด ์๋ค! ๐
๐ ์ต์ข ์ฑ๋ฅ ๊ฒฐ๊ณผ:
- โ Manual ๋ฐฉ์: 24ms โจ
- ๐ง MapStruct ๋ฐฉ์: 23ms โจ
- ๐ JPQL ๋ฐฉ์: 19ms โก
Manual๊ณผ MapStruct ๋ฒ์ ์ ์คํ ์๊ฐ์ด ์์ฒญ๋๊ฒ ๊ฐ์ ๋์์ต๋๋ค! ๊ฒฐ๊ณผ๋ ๊ฐ๋จํ ์๋๋ฆฌ์ค์์ ์ป์ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. JPQL์ด ๋ค์ ์กฐ๊ธ ๋ ๋น ๋ฅด์ง๋ง, ํฐ ์ฐจ์ด๋ ์์ต๋๋ค.
๐ก ๊ฒฐ๋ก
์๋ก ๋ค๋ฅธ ๋ณต์ก๋๋ฅผ ๊ฐ์ง ๋ ๊ฐ์ง ์๋๋ฆฌ์ค์์ ์คํ์ ์คํํ ๊ฒฐ๊ณผ, Entity์์ DTO๋ก์ ์ธ ๊ฐ์ง ๋งคํ ์ ํ ๊ฐ์ ํฐ ์ฐจ์ด๊ฐ ์๋ค๋ ๊ฒ์ด ๋ฐํ์ก์ต๋๋ค.
ํ์ง๋ง ๋ ์๋๋ฆฌ์ค ๋ชจ๋์์ JPQL ์๋ฃจ์ ์ด ๊ฐ์ฅ ์ฐ์ํ๊ณ , ๊ทธ ๋ค์์ด MapStruct, ๋ง์ง๋ง์ผ๋ก Manual ์๋ฃจ์ ์ด์์ต๋๋ค ๐
์ฑ๋ฅ์ ๋น์ทํ์ง๋ง, ์ด๋ค ์๋ฃจ์ ๋ ๋ณดํธ์ ์ผ๋ก ์ด์์ ์ด์ง๋ ์์ต๋๋ค. ํ๋ก์ ํธ์ ๋ฐ๋ผ ํ ์ ๊ทผ ๋ฐฉ์์ด ๋ค๋ฅธ ๊ฒ๋ณด๋ค ๋ ์ ๋ง์ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ต์ ์ค ํ๋๋ฅผ ์ ํํ๋ ๊ฒ์ ์ ํธ๋๋ ํน์ ์๊ตฌ์ฌํญ์ ๋ฌธ์ ์ผ ์ ์์ต๋๋ค ๐ฏ
โ๏ธ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
๐ ์ถ์ฒ
์๋ฌธ: Entity to DTO: A Performance Comparison of Three Mapping Approaches
์ ์: Flavius Zichil
๋ฐํ: Level Up Coding (2025๋ 9์ 28์ผ)



