๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Today I Learned(TIL)/์ŠคํŒŒ๋ฅดํƒ€ ๋‚ด์ผ๋ฐฐ์›€์บ ํ”„

[ TIL ] ์ฃผํŠน๊ธฐ ์‹ฌํ™”_Day 2

by carrot0911 2024. 12. 31.

์˜ค๋Š˜ ํ•œ ๊ณต๋ถ€ ๐Ÿง 

  • ์‹ฌํ™” Spring 1์ฃผ์ฐจ ๊ฐ•์˜ ๋“ฃ๊ธฐ → ์–ด์ œ ๋“ค์—ˆ๋˜ ๋ถ€๋ถ„๋ถ€ํ„ฐ ์ด์–ด์„œ ์ˆ˜๊ฐ•
  • ์‹ฌํ™” Spring 2์ฃผ์ฐจ ๊ฐ•์˜ ๋“ฃ๊ธฐ
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ด๋ก  ์„ธ์…˜ ๋“ฃ๊ธฐ
  • ์—ฐ๋ง ๊ธฐ๋… ๋ผ๋””์˜ค ๐Ÿคฉ
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

 

์˜ค๋Š˜ ์–ป์€ ๋‚ด์šฉ ์ •๋ฆฌ โœ๏ธ 

์‹ฌํ™” Spring ๊ฐ•์˜ ๋“ฃ๊ธฐ

  • Proxy ๊ฐ์ฒด๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๋„์›€์„ ๋ฐ›์•„์•ผ๋งŒ ์‹ค์ œ Entity์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • LazyInitializationException → ์‹ค์ œ JPA ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ๋งˆ์ฃผ์น˜๋Š” Exception
  • ์˜์†์„ฑ ์ „์ด๋Š” ์ง€์—ฐ ๋กœ๋”ฉ, ์ฆ‰์‹œ ๋กœ๋”ฉ๊ณผ๋Š” ์•„๋ฌด ๊ด€๋ จ์ด ์—†๋‹ค.

๊ฐ•์˜๋ฅผ ๋“ฃ๋‹ค๊ฐ€ ๊ถ๊ธˆํ–ˆ๋˜ ์ 

FetchType.LAZY์˜ ๊ฐœ๋… ์žก๊ธฐ

  • FetchType.LAZY: ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์ œ๋กœ ์ ‘๊ทผํ•  ๋•Œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์ด๋‹ค. ๊ด€๋ จ๋œ Entity๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • FetchType.EAGER: ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ฆ‰์‹œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์ด๋‹ค. Entity๋ฅผ ์กฐํšŒํ•˜๋ฉด ์—ฐ๊ด€๋œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ์กฐํšŒํ•œ๋‹ค.

FetchType.LAZY๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

  • ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž์ฃผ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ ๋•Œ: ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋“œ๋ฌผ๋‹ค๋ฉด, ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ ์‹œ์ ์— ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ด๋‹ค.
  • N+1 ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋ ค๊ณ  Fetch Join์„ ์‚ฌ์šฉํ•  ๋•Œ: FetchType.EAGER๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ์—๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋น„ํšจ์œจ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค. LAZY๋กœ ์„ค์ •ํ•˜๋ฉด ํ•„์š”์— ๋”ฐ๋ผ Fetch Join์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ
Entiy

@Entity
class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // User๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ Orders๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ
    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private List<Order> orders = new ArrayList<>();
}

@Entity
class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String productName;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}
  1. User Entity๋Š” Order Entity์™€ 1:N ๊ด€๊ณ„์ด๋‹ค.
  2. orders ํ•„๋“œ๋Š” FetchType.LAZY๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด์„œ User๋ฅผ ์กฐํšŒํ•  ๋•Œ Order ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๋กœ ์กฐํšŒํ•˜์ง€ ์•Š๋Š”๋‹ค. → ์ฒ˜์Œ์— ์กฐํšŒํ•˜์ง€ ์•Š๊ณ  Proxy ๊ฐ์ฒด๋กœ๋งŒ ๋‚จ์•„์žˆ๋‹ค.
  3. Order ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

Repository ์‚ฌ์šฉ ์˜ˆ์‹œ

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void fetchUserOrders(Long userId) {
        // 1. User๋งŒ ์กฐํšŒ (Order๋Š” ์กฐํšŒํ•˜์ง€ ์•Š์Œ)
        User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
        System.out.println("User name: " + user.getName());  // "์Šน์ฐฌ" ์ถœ๋ ฅ

        // 2. ์ด ์‹œ์ ์— LAZY ๋กœ๋”ฉ์ด ์‹คํ–‰๋จ (Order ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ๊นŒ)
        List<Order> orders = user.getOrders();
        System.out.println("Orders count: " + orders.size());  // "์Šน์ฐฌ"์˜ ์ „์ฒด ์ฃผ๋ฌธ ์ˆ˜ ์ถœ๋ ฅ
    }
}
  1. findById( )๋กœ User๋งŒ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ Order ๋ฐ์ดํ„ฐ๋Š” ์กฐํšŒํ•˜์ง€ ์•Š๋Š”๋‹ค.
  2. user.getOrders( )๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ˆœ๊ฐ„, Order ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

FetchType.LAZY์˜ ์žฅ์ 

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

์‚ฌ์šฉ ์‹œ ์ฃผ์˜ ์‚ฌํ•ญ

  • LazyInitializationException: LAZY ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ธ์…˜์ด ์—ด๋ ค ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    Service Layer์—์„œ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•œ๋‹ค.
  • ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค: LAZY๋กœ ์„ค์ •๋œ ํ•„๋“œ๋ฅผ ์“ธ ์ผ์ด ๋งŽ๋‹ค๋ฉด, JPQL์—์„œ Fetch Join๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•œ๊บผ๋ฒˆ์— ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค.

๊ฒฐ๋ก 

  • FetchType.LAZY๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ด€๋ จ๋œ ๊ฐœ๋…์ธ FetchType.EAGER์™€ Fetch Join, JPQL์— ๋Œ€ํ•ด์„œ๋„ ์ž˜ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

 

์˜ค๋Š˜ ํ•˜๋ฃจ ์ƒ๊ฐ ์ •๋ฆฌ โœ๏ธ

์˜ค๋Š˜์€ 2024๋…„ ๋งˆ์ง€๋ง‰๋‚ ....
์˜ฌํ•ด๋Š” ์œ ๋… ์‹œ๊ฐ„์ด ์—„์ฒญ ๋นจ๋ฆฌ ์ง€๋‚˜๊ฐ„ ๊ฒƒ ๊ฐ™๋‹ค.. 2์›”์— ๋Œ€ํ•™๊ต ์กธ์—…์„ ํ•˜๊ณ , ๋‹ค๋ฅธ ๋ถ€ํŠธ์บ ํ”„๋„ 6๊ฐœ์›” ์ •๋„ ๋“ฃ๊ณ , ์ทจ์—…์„ ์ค€๋น„ํ•˜๋‹ค๊ฐ€ ์ŠคํŒŒ๋ฅดํƒ€ ๋‚ด๋ฐฐ์บ ์— ํ•ฉ๋ฅ˜ํ–ˆ์œผ๋‹ˆ๊นŒ.. ์•Œ์ฐจ๊ฒŒ ๋ณด๋‚ธ ๊ฑฐ๊ฒ ์ง€??

๋ถ„๋ช… ๊ณต๋ถ€๋Š” ๊ณ„์† ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์†์€ ๋นˆ ๊นกํ†ต์ธ ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ์ž๊พธ ๋“ ๋‹ค..
ํ•˜๋ฉด ํ• ์ˆ˜๋ก ๋‚ด๊ฐ€ ์ž˜ํ•˜๊ณ  ์žˆ๋Š” ๊ฒŒ ๋งž๋Š” ๊ฑด๊ฐ€.. ์˜๋ฌธ์ด ๋“ค๊ณ   ๊ณต๋ถ€ํ•˜๋Š” ๊ฒƒ๋“ค์ด ๋‚ด ๋จธ๋ฆฟ์†์— ์ž˜ ์ €์žฅ๋˜๊ณ  ์žˆ๋Š” ๊ฑด์ง€.. ๋„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๊ฒŒ ์™œ ์ด๋ ‡๊ฒŒ ์ง„ํ–‰๋˜๊ณ  ์–ด๋–ค ์›๋ฆฌ๋กœ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ๋ชจ๋ฅด๋Š” ๋Š๋‚Œ...?

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

ํ™•์‹คํžˆ ๋‚œ ๋น„์ „๊ณต์ž์ด๊ณ  ์ „๊ณต์ž๋“ค์„ ๋”ฐ๋ผ์žก์œผ๋ ค๋ฉด ๋ช‡ ๋ฐฐ๋Š” ๋” ๋…ธ๋ ฅํ•ด์•ผ ํ•œ๋‹ค! ๊ทธ๋ถ„๋“ค์€ 4๋…„๋™์•ˆ ์Œ“์•„์˜จ ๊ฒƒ์ด ์žˆ๊ณ  ๋‚˜๋Š” ์˜ฌํ•ด 11์›”๋ถ€ํ„ฐ ์Œ“์•„๋‚˜๊ฐ€๊ธฐ ์‹œ์ž‘ํ–ˆ์œผ๋‹ˆ๊นŒ! ์ง€๊ธˆ์ฒ˜๋Ÿผ ๊พธ์ค€ํ•˜๊ฒŒ ๋…ธ๋ ฅํ•œ๋‹ค๋ฉด ๋ถ„๋ช… ์—ฌ๊ธฐ์„œ ๋” ์„ฑ์žฅํ•˜๊ณ  ๊ณ„์† ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋‹ค!!

ํ›„... ์—ฐ๋ง์ด๋ผ๊ณ  ํ˜ผ์ž ์ƒ๊ฐ์ด ๋งŽ์•„์กŒ์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค ๐Ÿฅฒ

์•„๋ฌดํŠผ ์˜ฌํ•ด ์ž˜ ๋งˆ๋ฌด๋ฆฌํ–ˆ์œผ๋‹ˆ๊นŒ ๋‚ด๋…„์—๋„ ์—ด์ • ๋„˜์น˜๊ฒŒ ๋ณด๋‚ด๋ณด์ž!!!
๋ฝœ์ดํ‹ฐ์ด์ด์ด์ด์ด์ž‰!!!!!!!!!!!! ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ

 

๋‚ด์ผ ๊ณ„ํš โฐ

  • ์ƒˆํ•ด๋‹ˆ๊นŒ ์—ฌ์œ ๋กญ๊ฒŒ ๋ณด๋‚ด๋„ ๋˜์ง€ ์•Š์„๊นŒ...? ๋Š” ์•ˆ ๋˜๊ฒ ์ง€.. ๐Ÿ˜”
  • ์‹ฌํ™” Spring 3์ฃผ์ฐจ ๊ฐ•์˜ ๋“ฃ๊ธฐ
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ด๋ก  ๋…นํ™”๋ณธ ์˜ฌ๋ผ์˜จ๋‹ค๋ฉด ๋ณต์Šต
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

+ ์ง‘์ค‘๋ ฅ์ด ์ข‹๋‹ค ์‹ถ์œผ๋ฉด ๋” ๊ณต๋ถ€!