Database

์ฟผ๋ฆฌ ํŠœ๋‹ - ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ํŠน์ • ์ปฌ๋Ÿผ ์ œ์™ธํ•˜๊ณ  ์กฐํšŒ

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2024. 11. 13.

๊ฐœ์š”

Spring Data JPA ๋ฅผ ์‚ฌ์šฉํ•ด์„œ DB ๋ฅผ ์กฐํšŒํ•˜๋ฉด ์ง€์—ฐ ๋กœ๋”ฉ์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์ปฌ๋Ÿผ ๊ฐ’๋“ค์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. JPA ํŠน์ • ์ƒ ์ฒ˜์Œ์— ๋ชจ๋“  ๊ฐ’๋“ค์„ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๊ณ  ์Šค๋ƒ…์ƒต์„ ๊ธฐ์ค€์œผ๋กœ ๋”ํ‹ฐ ์ฒดํ‚น์„ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ readOnly = true์ผ ๊ฒฝ์šฐ๋Š” ๋”ํ‹ฐ์ฒดํ‚น์„ ํ•  ํ•„์š”๊ฐ€ ์—†๊ณ  ์›ํ•˜๋Š” ๊ฐ’๋งŒ ์–ป์œผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•ด์„œ ์–ป์„ ํ•„์š”๋„ ์—†๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด DocumentDB ์™€ ๊ฐ™์€ NoSQL์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , RDB๋กœ ์•„ํ‹ฐํด ์ •๋ณด๋ฅผ ์ €์žฅํ–ˆ๋‹ค๊ณ  ์น˜์ž. 

 

@Entity
public class Article {
    @Id
    @GeneratedValue
    private Long id;

    private String title;

    @Column(columnDefinition = "TEXT")
    private String content; // ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ (๋ณธ๋ฌธ ๋‚ด์šฉ)

    private String author;
}

 

์•„ํ‹ฐํด์˜ ๋ณธ๋ฌธ ๋‚ด์šฉ์€ ๊ธธ์ด๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์œผ๋‹ˆ SQL ์ž๋ฃŒํ˜•์ค‘์— ๋งŽ์€ ๋ฌธ์ž๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” TEXT ์ž๋ฃŒํ˜•์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.

์ด๋•Œ ์•„ํ‹ฐํด ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋‹ค์Œ์ฒ˜๋Ÿผ JPA ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

List<Article> articles = articleRepository.findAll();

 

์•„ํ‹ฐํด ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ ๋ฆฌ์Šคํฐ์Šค๋กœ ๋ณ€๊ฒฝํ›„ ์‘๋‹ต๊ฐ’์œผ๋กœ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๋งค๋ฒˆ ์•„๋ฌด๋ ‡์ง€ ์•Š๊ฒŒ ๋‹ค๋“ค ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์•„๋ฌด ์ƒ๊ฐ ์—†์ด ๊ทธ๋ƒฅ ์‚ฌ์šฉํ–ˆ๋‹ค๊ฐ„ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„์™€ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. 

SELECT id, title, content, author FROM articles;

 

 

์œ„ ๋ฐฉ์‹๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ์•„ํ‹ฐํด๋งˆ๋‹ค ๋ณธ๋ฌธ ๋‚ด์šฉ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ฒŒ ๋œ๋‹ค. ๋ณธ๋ฌธ ๋‚ด์šฉ์€ ๋‹ค๋ฅธ ํ•„๋“œ ๋ณด๋‹ค ๋” ํฐ ๋ฐ์ดํ„ฐ ์–‘์„ ๊ฐ–๊ณ  ์žˆ๊ณ , ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋Š” ๊ทธ์— ๋น„๋ก€ํ•˜์—ฌ ๋†’์€ ๋„คํŠธ์›Œํฌ ๋Œ€์—ญํญ๊ณผ ๋ถˆํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค.

 

TEXT, BLOB์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๊ฐ€ ํฐ ์ปฌ๋Ÿผ์€ ์กฐํšŒ ๋น„์šฉ์ด ๋†’์œผ๋ฏ€๋กœ, ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ , ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์„ ํƒ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์€ ํšจ์œจ์ ์ธ ์ž์› ์‚ฌ์šฉ์„ ์œ„ํ•ด ์ค‘์š”ํ•œ ํŠœ๋‹ ๊ธฐ๋ฒ•์ด๋‹ค. ๋”ฐ๋ผ์„œ DTO๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•˜๋„๋ก ์„ค๊ณ„๋ฅผ ๋ฐ”๊ฟ” ๋ฐ์ดํ„ฐ ์ „์†ก๊ณผ ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ์ค„์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

public class ArticleDTO {
    private Long id;
    private String title;
    private String author;

    public ArticleDTO(Long id, String title, String author) {
        this.id = id;
        this.title = title;
        this.author = author;
    }
}

 

ํ•„์š”ํ•œ ๊ฐ’๋งŒ ํ•„๋“œ๋กœ ๊ฐ–๋Š” DTO๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

@Query("SELECT new com.example.dto.ArticleDTO(a.id, a.title, a.author) FROM Article a")
List<ArticleDTO> findArticlesWithoutContent();
SELECT id, title, author FROM articles;

 

๊ทธ๋ฆฌ๊ณ  JPQL๋กœ ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ์กฐํšŒํ•œ๋‹ค.

List<ArticleDTO> articles = articleRepository.findArticlesWithoutContent();

 

ORM ์— ์˜ํ•ด ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋“ค์€ DTO ์˜ ํ•„๋“œ์— ์•Œ๋งž๊ฒŒ ํŒŒ์‹ฑ๋œ๋‹ค. ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๋Š” ์ปฌ๋Ÿผ์„ ์ œ์™ธํ–ˆ์œผ๋ฏ€๋กœ ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ ์–‘์ด ์ค„์–ด๋“ค๊ณ , ์ฟผ๋ฆฌ ์‹คํ–‰ ์†๋„๊ฐ€ ํ–ฅ์ƒ๋œ๋‹ค.

 

์ด๋ ‡๊ฒŒ DTO๋กœ ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ์„ ๊ฐ–๋Š” ์ฟผ๋ฆฌ ํŠœ๋‹ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์„ ๊ฐ–๋Š”๋‹ค.

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค I/O ๊ฐ์†Œ
    • TEXT ๋˜๋Š” BLOB ๊ฐ™์€ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋“ค์ด๋Š” ๋น„์šฉ์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ๋„คํŠธ์›Œํฌ ์ „์†ก๋Ÿ‰ ๊ฐ์†Œ
    • ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ „์†กํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ ๋ถ€ํ•˜๊ฐ€ ์ค„์–ด๋“ ๋‹ค.
  3. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ตœ์ ํ™”
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ค„์–ด๋“ ๋‹ค.
  4. ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„ ๋‹จ์ถ•
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋ฐ์ดํ„ฐ ์–‘์ด ์ค„์–ด๋“ค์–ด ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„์ด ๋‹จ์ถ•๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋ชจ๋“  ์กฐํšŒ๋ฅผ ๋‹ค DTO๋ฅผ ์จ์„œ ์กฐํšŒํ•˜๋Š” ๊ฒŒ ํ•ญ์ƒ ์ข‹์€ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ํŠน์ • ๊ฒฝ์šฐ์—๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ํ•„๋“œ ๋‚ด์šฉ์„ ๋ชจ๋‘ ํฌํ•จํ•˜์—ฌ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค.

 

์กฐํšŒ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋”ฐ์ ธ๋ด์„œ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ์—†๋Š” ์ง€ ํ™•์ธํ•ด์•ผํ•œ๋‹ค.

  • ์ œ์™ธ ํ–ˆ๋˜ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•œ ์‹œ์ ์—์„œ ๋‹ค์‹œ ์กฐํšŒํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. (N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜)

๋˜ํ•œ DTO ์„ค๊ณ„๋„ ์œ ์˜ํ•ด์•ผํ•œ๋‹ค. DTO ํด๋ž˜์Šค๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, DTO ์‚ฌ์šฉ์ด ํ•ญ์ƒ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

 

DTO ์„ค๊ณ„

public class ChatRoomUserDTO {
    private Long chatRoomId;
    private String chatRoomName;
    private String userName;

    public ChatRoomUserDTO(Long chatRoomId, String chatRoomName, String userName) {
        this.chatRoomId = chatRoomId;
        this.chatRoomName = chatRoomName;
        this.userName = userName;
    }
}
@Query("SELECT new com.example.dto.ChatRoomUserDTO(cr.id, cr.name, u.name) " +
       "FROM ChatRoom cr JOIN cr.user u")
List<ChatRoomUserDTO> findChatRoomsWithUsers();

 

์œ„์™€ ๊ฐ™์€ ๋ฐฉ์‹์„ ์˜ˆ๋กœ ๋“ค๋ฉด DTO ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์กฐํšŒ๊ฐ€ ์ผ์–ด๋‚˜๊ณ  ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ MyBatis ์—์„œ ํด๋ž˜์Šค๋ฅผ ๊ฒฝ๋กœ๋ฅผ ์ ๋Š” ๊ฒƒ ๊ฐ™์€ ๋ฐฉ์‹๋งŒ ์žˆ๋Š” ๊ฑด ์•„๋‹ˆ๋‹ค.

 

1. ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA์˜ ๊ธฐ๋ณธ ๊ทœ์น™ ํ™œ์šฉ

Spring Data JPA์—์„œ๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ DTO ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜๋ฉด, ์ž๋™์œผ๋กœ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค. DTO ํด๋ž˜์Šค๊ฐ€ ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ๊ฑฐ๋‚˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์™€ ๋™์ผํ•œ ๋ชจ๋“ˆ ๋‚ด์— ์กด์žฌํ•  ๊ฒฝ์šฐ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

ChatRoomUserDTO๊ฐ€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์™€ ๋™์ผํ•œ ํŒจํ‚ค์ง€์ด๊ฑฐ๋‚˜, ํด๋ž˜์Šค ๊ฒฝ๋กœ๋ฅผ Spring Data JPA๊ฐ€ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.

// ChatRoomUserDTO ํด๋ž˜์Šค๊ฐ€ ๊ฐ™์€ ํŒจํ‚ค์ง€์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
@Query("SELECT new ChatRoomUserDTO(cr.id, cr.name, u.name) " +
       "FROM ChatRoom cr JOIN cr.user u")
List<ChatRoomUserDTO> findChatRoomsWithUsers();

 

 

์œ„ ๋ฐฉ์‹์€ Spring Data JPA์™€์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ†ตํ•ฉํ•˜์—ฌ ๋”ฑํžˆ ์ถ”๊ฐ€ ์„ค์ •๋„ ํ•„์š”์—†๊ณ , DTO์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์˜๋„๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ DTO๋Š” ๋…๋ฆฝ์ ์ธ POJO๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์šฉ์ดํ•˜๋‹ค. DTO ํด๋ž˜์Šค์— ์ถ”๊ฐ€ ํ•„๋“œ๋ฅผ ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

 

2. Projection ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ

Spring Data JPA์—์„œ Projection์„ ์‚ฌ์šฉํ•˜๋ฉด DTO ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ํŠน์ • ํ•„๋“œ๋งŒ ์กฐํšŒํ•˜์—ฌ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

public interface ChatRoomUserProjection {
    Long getChatRoomId();
    String getChatRoomName();
    String getUserName();
}

 

์ฟผ๋ฆฌ์—์„œ ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ˜ํ™˜

Spring Data JPA๋Š” ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ Projection ์ธํ„ฐํŽ˜์ด์Šค์— ๋งž๊ฒŒ ์ž๋™์œผ๋กœ ๋งคํ•‘ํ•œ๋‹ค.

@Query("SELECT cr.id AS chatRoomId, cr.name AS chatRoomName, u.name AS userName " +
       "FROM ChatRoom cr JOIN cr.user u")
List<ChatRoomUserProjection> findChatRoomsWithUsers();


List<ChatRoomUserProjection> results = chatRoomRepository.findChatRoomsWithUsers();

 

์žฅ์ ์œผ๋กœ๋Š” DTO ๊ฐ์ฒด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ํ•˜์ง€๋งŒ Projection์€ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ, DTO์— ๋กœ์ง์ด๋‚˜ ๋ณ€ํ™˜ ์ž‘์—…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

 

3. ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ์™€ @SqlResultSetMapping ํ™œ์šฉ

DTO์˜ ์ƒ์„ฑ์ž ํ˜ธ์ถœ์„ ํ”ผํ•˜๊ณ , ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ์™€ @SqlResultSetMapping์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„์ ‘์ ์œผ๋กœ DTO๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค. JPA ํ‘œ์ค€ ๊ธฐ๋Šฅ์œผ๋กœ, ์ผ๋ฐ˜ JPA์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ DTO๋‚˜ ์—”ํ‹ฐํ‹ฐ์— ๋งคํ•‘ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. Spring Data JPA์—์„œ๋Š” ์ง์ ‘์ ์œผ๋กœ ์—ฐ๋™๋˜์ง€ ์•Š์œผ๋ฉฐ, ์‚ฌ์šฉํ•˜๋ ค๋ฉด EntityManager๋ฅผ ํ†ตํ•ด ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. EntityManager.createNativeQuery() ๋ฉ”์„œ๋“œ์—์„œ ์ฟผ๋ฆฌ์™€ @SqlResultSetMapping ์ด๋ฆ„์„ ์—ฐ๊ฒฐํ•˜์—ฌ ๋งคํ•‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

public class ChatRoomUserDTO {
    private Long chatRoomId;
    private String chatRoomName;
    private String userName;

    public ChatRoomUserDTO(Long chatRoomId, String chatRoomName, String userName) {
        this.chatRoomId = chatRoomId;
        this.chatRoomName = chatRoomName;
        this.userName = userName;
    }
}

 

@Entity
@SqlResultSetMapping(
    name = "ChatRoomUserMapping",
    classes = @ConstructorResult(
        targetClass = ChatRoomUserDTO.class,
        columns = {
            @ColumnResult(name = "chatRoomId", type = Long.class),
            @ColumnResult(name = "chatRoomName", type = String.class),
            @ColumnResult(name = "userName", type = String.class)
        }
    )
)
public class ChatRoom {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    //๋‹ค๋ฅธ ํ•„๋“œ๋“ค
}

 

@Repository
public class ChatRoomRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public List<ChatRoomUserDTO> findChatRoomsWithUsers() {
        return entityManager.createNativeQuery(
                "SELECT cr.id AS chatRoomId, cr.name AS chatRoomName, u.name AS userName " +
                "FROM chat_rooms cr JOIN users u ON cr.user_id = u.id",
                "ChatRoomUserMapping"
        ).getResultList();
    }
}

 

 

๋งค์šฐ ๋ณต์žกํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๊ฐ€ ์กด์žฌํ•  ๋•Œ ์‚ฌ์šฉํ• ๋งŒ ํ•˜๋‹ค. JPQL๋กœ ์ž‘์„ฑํ•˜๊ธฐ ์–ด๋ ค์šด ๋ณต์žกํ•œ SQL์„ ๋‹ค๋ค„์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.(e.g. ์„œ๋ธŒ์ฟผ๋ฆฌ, ๋ณต์žกํ•œ ์กฐํ•ฉ์ด๋‚˜ ํ†ต๊ณ„ ์ฟผ๋ฆฌ) ๋˜ํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค I/O๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ฑฐ๋‚˜, ๋„ค์ดํ‹ฐ๋ธŒ SQL์—์„œ JPA์˜ ์ œํ•œ์„ ๋ฒ—์–ด๋‚˜์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ถœ์ฒ˜: https://hyj.oopy.io/query-tuning

 

๊ฒฐ๋ก 

DTO๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ์ปฌ๋Ÿผ๋งŒ ์กฐํšŒํ•˜๊ณ , ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ์™ธํ•˜๋Š” ๋ฐฉ์‹์€ ํšจ๊ณผ์ ์ธ ์ฟผ๋ฆฌ ํŠœ๋‹ ๊ธฐ๋ฒ•์ด๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค I/O์™€ ๋„คํŠธ์›Œํฌ ์ „์†ก๋Ÿ‰์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค.

์‹ค๋ฌด์—์„œ๋„ ๋ฆฌ์ŠคํŠธํ˜• ํ™”๋ฉด์ด๋‚˜ ์ฝ๊ธฐ ์ „์šฉ API์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์ตœ์ ํ™” ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ํ•„์š” ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ œ์™ธํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ„์˜ ์ž์› ์‚ฌ์šฉ์„ ์ค„์ด๊ณ  ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋Œ“๊ธ€