@Transactional

์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๊ฐ€ ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„์— ํฌํ•จ๋˜์–ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. Spring์€ ์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ๊ฐ์ง€ํ•˜๊ณ  ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๋ฉฐ, ๋ฉ”์„œ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ํŠธ๋žœ์žญ์…˜์„ ์ปค๋ฐ‹ํ•˜๊ฑฐ๋‚˜ ๋กค๋ฐฑํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ํŠน์ง• ๋ฐ ์ฃผ์˜ ์‚ฌํ•ญ

1. Propaging(์ „ํŒŒ ์˜ต์…˜):

  • ํŠธ๋žœ์žญ์…˜์˜ ์ „ํŒŒ ๋™์ž‘์„ ์ง€์ •ํ•œ๋‹ค

์ข…๋ฅ˜

  1. REQUIRED (ํ•„์š”ํ•œ ๊ฒฝ์šฐ):

    • ํŠธ๋žœ์žญ์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.REQUIRED)
      public void requiredMethod() {
          // ์ด๋ฏธ ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜๋ฉด ์‚ฌ์šฉํ•˜๊ณ , ์—†์œผ๋ฉด ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
      }
  2. SUPPORTS (์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ):

    • ํŠธ๋žœ์žญ์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํŠธ๋žœ์žญ์…˜ ์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.SUPPORTS)
      public void supportsMethod() {
          // ์ด๋ฏธ ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜๋ฉด ์‚ฌ์šฉํ•˜๊ณ , ์—†์œผ๋ฉด ํŠธ๋žœ์žญ์…˜ ์—†์ด ์‹คํ–‰
      }
  3. MANDATORY (ํ•„์ˆ˜):

    • ํŠธ๋žœ์žญ์…˜์ด ์ด๋ฏธ ์กด์žฌํ•ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.MANDATORY)
      public void mandatoryMethod() {
          // ํŠธ๋žœ์žญ์…˜์ด ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•จ. ์—†์œผ๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ
      }
  4. REQUIRES_NEW (ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜):

    • ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํŠธ๋žœ์žญ์…˜์€ ์ผ์‹œ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void requiresNewMethod() {
          // ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘. ๊ธฐ์กด ํŠธ๋žœ์žญ์…˜์€ ์ผ์‹œ ์ค‘๋‹จ
      }
  5. NOT_SUPPORTED (ํŠธ๋žœ์žญ์…˜ ์ง€์› ์•ˆ ํ•จ):

    • ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜์ง€ ์•Š์•„์„œ ํŠธ๋žœ์žญ์…˜ ์™ธ๋ถ€์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํŠธ๋žœ์žญ์…˜์€ ์ผ์‹œ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.NOT_SUPPORTED)
      public void notSupportedMethod() {
          // ํŠธ๋žœ์žญ์…˜ ์—†์ด ์‹คํ–‰. ๊ธฐ์กด ํŠธ๋žœ์žญ์…˜์€ ์ผ์‹œ ์ค‘๋‹จ
      }
  6. NEVER (ํŠธ๋žœ์žญ์…˜ ์‚ฌ์šฉ ๊ธˆ์ง€):

    • ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฉฐ, ํŠธ๋žœ์žญ์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.NEVER)
      public void neverMethod() {
          // ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋จ. ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ
      }
  7. NESTED (์ค‘์ฒฉ๋œ ํŠธ๋žœ์žญ์…˜):

    • ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜๋ฉด ์ค‘์ฒฉ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ผ๋ฐ˜ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

      @Transactional(propagation = Propagation.NESTED)
      public void nestedMethod() {
          // ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜๋ฉด ์ค‘์ฒฉ ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ผ๋ฐ˜ ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
      }

2. Isolation(๊ฒฉ๋ฆฌ ์ˆ˜์ค€):

  • ํŠธ๋žœ์žญ์…˜์˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์ง€์ •ํ•œ๋‹ค

์ข…๋ฅ˜

  1. READ_UNCOMMITTED (๋ฏธํ™•์ธ ์ฝ๊ธฐ):

    • ๋ฌธ์ œ์ : Dirty Read (๋”๋Ÿฌ์šด ์ฝ๊ธฐ)

    • ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์•„์ง ์ปค๋ฐ‹๋˜์ง€ ์•Š์€ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void readUncommittedMethod() {
        // ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์˜ ์ปค๋ฐ‹๋˜์ง€ ์•Š์€ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ์ฝ์„ ์ˆ˜ ์žˆ์Œ
    }
    • ์˜ˆ์‹œ:

      • A ์‚ฌ์šฉ์ž๊ฐ€ 10000์›์„ ์€ํ–‰ ๊ณ„์ขŒ์— ์ž…๊ธˆํ•˜๋Š” ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ ์•„์ง ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ, B ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ„์ขŒ ์ž”์•ก์„ ์กฐํšŒํ•˜๋ฉด 10000์›์ด ๋”ํ•ด์ง„ ์ž”์•ก์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ A ์‚ฌ์šฉ์ž๊ฐ€ ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑํ•˜๋ฉด B ์‚ฌ์šฉ์ž๋Š” ์ž˜๋ชป๋œ ์ •๋ณด๋ฅผ ๋ณธ ๊ฒƒ์ด ๋ฉ๋‹ˆ๋‹ค.

  2. READ_COMMITTED (ํ™•์ธ ์ฝ๊ธฐ):

    • ๋ฌธ์ œ์ : Non-Repeatable Read (๋น„๋ฐ˜๋ณต ์ฝ๊ธฐ)

    • ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์ปค๋ฐ‹๋œ ๋ณ€๊ฒฝ ๋‚ด์šฉ๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommittedMethod() {
        // ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์˜ ์ปค๋ฐ‹๋œ ๋ณ€๊ฒฝ ๋‚ด์šฉ๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ์Œ
    }
    • ์˜ˆ์‹œ:

      • A ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ๊ณ„์ขŒ ์ž”์•ก์„ ์กฐํšŒํ–ˆ์„ ๋•Œ 50000์›์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด B ์‚ฌ์šฉ์ž๊ฐ€ A ์‚ฌ์šฉ์ž์˜ ๊ณ„์ขŒ์—์„œ 20000์›์„ ์ถœ๊ธˆํ–ˆ์Šต๋‹ˆ๋‹ค. A ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์‹œ ์ž”์•ก์„ ์กฐํšŒํ•˜๋ฉด 30000์›์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๋‘ ๋ฒˆ์˜ ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

  3. REPEATABLE_READ (๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ์ฝ๊ธฐ):

    • ๋ฌธ์ œ์ : Phantom Read (์œ ๋ น ์ฝ๊ธฐ)

    • ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘ํ•  ๋•Œ ์ฝ์€ ๋ฐ์ดํ„ฐ๋Š” ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜ ๋™์•ˆ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์— ์˜ํ•ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void repeatableReadMethod() {
        // ํŠธ๋žœ์žญ์…˜ ๋™์•ˆ ์ฝ์€ ๋ฐ์ดํ„ฐ๋Š” ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์— ์˜ํ•ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ
    }
    • ์˜ˆ์‹œ:

      • A ์‚ฌ์šฉ์ž๊ฐ€ 30์„ธ ์ดํ•˜์˜ ๊ณ ๊ฐ์„ ์กฐํšŒํ–ˆ์„ ๋•Œ 5๋ช…์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด B ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ๋กœ์šด 30์„ธ ์ดํ•˜์˜ ๊ณ ๊ฐ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. A ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์‹œ 30์„ธ ์ดํ•˜์˜ ๊ณ ๊ฐ์„ ์กฐํšŒํ•˜๋ฉด 6๋ช…์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.

  4. SERIALIZABLE (์ง๋ ฌํ™” ๊ฐ€๋Šฅ):

    • ํŠธ๋žœ์žญ์…˜๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜์–ด ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializableMethod() {
        // ์ฝ”๋“œ
    }
    • ์˜ˆ์‹œ:

      • A ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ๊ณ„์ขŒ ์ž”์•ก์„ ๋ณ€๊ฒฝํ•˜๋Š” ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๋ฉด, ๊ทธ ๋™์•ˆ B ์‚ฌ์šฉ์ž๋Š” A ์‚ฌ์šฉ์ž์˜ ๊ณ„์ขŒ์— ์–ด๋– ํ•œ ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. A ์‚ฌ์šฉ์ž์˜ ํŠธ๋žœ์žญ์…˜์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค

๋™์‹œ์„ฑ ๋ฌธ์ œ

  1. Dirty Reads (์˜ค์—ผ๋œ ์ฝ๊ธฐ):

    • ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ณ€๊ฒฝ๋œ (๊ทธ๋Ÿฌ๋‚˜ ์•„์ง ์ปค๋ฐ‹๋˜์ง€ ์•Š์€) ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์ฝ๋Š” ๊ฒฝ์šฐ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์•„์ง ํ™•์ •๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ํ•ด๊ฒฐ๋ฐฉ๋ฒ•:

      • READ_COMMITTED ์ด์ƒ์˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์‚ฌ์šฉํ•˜์—ฌ Dirty Reads๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปค๋ฐ‹๋œ ๋ฐ์ดํ„ฐ๋งŒ ์ฝ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  2. Non-Repeatable Reads (๋น„๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ์ฝ๊ธฐ):

    • ํ•œ ํŠธ๋žœ์žญ์…˜ ๋„์ค‘์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‘ ๋ฒˆ ์ด์ƒ ์ฝ์„ ๋•Œ, ๋‘ ๋ฒˆ์งธ ์ฝ๊ธฐ์—์„œ ์ฒซ ๋ฒˆ์งธ ์ฝ๊ธฐ์™€ ๋‹ค๋ฅธ ๊ฐ’์„ ์–ป๋Š” ๊ฒฝ์šฐ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์— ์˜ํ•ด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

    • ํ•ด๊ฒฐ๋ฐฉ๋ฒ•:

      • REPEATABLE_READ ์ด์ƒ์˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์‚ฌ์šฉํ•˜์—ฌ Non-Repeatable Reads๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋  ๋•Œ ์ฝ์€ ๋ฐ์ดํ„ฐ๋Š” ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜ ๋™์•ˆ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.

  3. Phantom Reads (ํ™˜์˜ ์ฝ๊ธฐ):

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

    • ํ•ด๊ฒฐ๋ฐฉ๋ฒ•:

      • SERIALIZABLE ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์‚ฌ์šฉํ•˜์—ฌ Phantom Reads๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜์–ด, ํ•œ ํŠธ๋žœ์žญ์…˜์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ฐ์ดํ„ฐ์˜ ์ถ”๊ฐ€๋‚˜ ์‚ญ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Timeout (์‹œ๊ฐ„ ์ดˆ๊ณผ):

  • timeout ์˜ต์…˜์€ ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ง€์ •๋œ ์‹œ๊ฐ„ ๋‚ด์— ์™„๋ฃŒ๋˜์ง€ ์•Š์œผ๋ฉด ๊ฐ•์ œ๋กœ ๋กค๋ฐฑ๋ฉ๋‹ˆ๋‹ค.

    @Transactional(timeout = 5)  // 5์ดˆ
    public void timeoutMethod() {
        // ์ด ํŠธ๋žœ์žญ์…˜์€ 5์ดˆ ๋‚ด์— ์™„๋ฃŒ๋˜์ง€ ์•Š์œผ๋ฉด ๋กค๋ฐฑ๋ฉ๋‹ˆ๋‹ค.
    }

Read-only (์ฝ๊ธฐ ์ „์šฉ):

  • readOnly ์˜ต์…˜์€ ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ ์ž‘์—…์—์„œ๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    @Transactional(readOnly = true)
    public Account getAccount(Long id) {
        // ์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ๋งŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ˆ˜์ •์€ ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
        return accountRepository.findById(id).orElse(null);
    }

์„ฑ๋Šฅ ํ–ฅ์ƒ ์ด์œ :

  1. ์ตœ์ ํ™”๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—”์ง„ ๋™์ž‘:

    • ๋Œ€๋ถ€๋ถ„์˜ RDBMS๋Š” ์—ฌ๋Ÿฌ ์œ ํ˜•์˜ ๋ฝํ‚น ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์˜ ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์— ๊ด€๋ จ๋œ ๋ฝ(์˜ˆ: ์“ฐ๊ธฐ ๋ฝ)์„ ํš๋“ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์€ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์— ์˜ํ•ด ๋ธ”๋กœํ‚น๋˜๋Š” ๋นˆ๋„๊ฐ€ ์ค„์–ด๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ์˜ˆ: ์ƒ์ ์˜ ์žฌ๊ณ  ํ™•์ธ ์‹œ์Šคํ…œ์—์„œ, ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์žฌ๊ณ ๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒฝ์šฐ์—, ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์žฌ๊ณ  ์ •๋ณด๋ฅผ ๋น ๋ฅด๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์“ฐ๊ธฐ ๋ฝ ์—†์ด ์ •๋ณด๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์–ด, ๋ธ”๋กœํ‚น ์—†์ด ๋™์‹œ์— ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ๋ฒ„์ „ ๊ด€๋ฆฌ์™€ ๋ฝํ‚น ์ตœ์†Œํ™”:

    • ORM ๋„๊ตฌ(์˜ˆ: Hibernate)๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์„ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•ด ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฒ„์ „ ๊ด€๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ–‰์— ๋Œ€ํ•œ ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ๋‘ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ์ƒํ™ฉ(๋™์‹œ์„ฑ ๋ฌธ์ œ)์„ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ์—†์œผ๋ฏ€๋กœ, ์ด๋Ÿฌํ•œ ๋ฒ„์ „ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š” ์—†์–ด์ง‘๋‹ˆ๋‹ค.

    • ์˜ˆ: ์€ํ–‰์˜ ๊ณ„์ขŒ ์ž”์•ก ํ™•์ธ ์‹œ์Šคํ…œ์—์„œ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž”์•ก๋งŒ ํ™•์ธํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ORM์ด ๋ฒ„์ „ ๊ด€๋ฆฌ๋‚˜ ๋ฝํ‚น ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋˜๋ฏ€๋กœ, ์‘๋‹ต ์†๋„๊ฐ€ ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. ์บ์‹ฑ ํšจ์œจ์„ฑ:

    • ORM ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ข…์ข… ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•˜์—ฌ, ๋™์ผํ•œ ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ๋น ๋ฅธ ์‘๋‹ต ์‹œ๊ฐ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์บ์‹œ๋œ ๋ฐ์ดํ„ฐ์˜ ์œ ํšจ์„ฑ์— ๋Œ€ํ•œ ์šฐ๋ ค๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

    • ์˜ˆ: ๋‰ด์Šค ์›น์‚ฌ์ดํŠธ์—์„œ, ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‰ด์Šค ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ, ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ORM ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ด์ „์— ์กฐํšŒ๋œ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œ์—์„œ ๋น ๋ฅด๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  4. ์ผ๊ด€์„ฑ ์œ ์ง€:

    • ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์€ ์‹ค์ˆ˜๋กœ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์˜๋„์น˜ ์•Š๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ์˜ˆ: ๋ณ‘์› ์‹œ์Šคํ…œ์—์„œ, ํ™˜์ž์˜ ๋ณ‘๋ ฅ์„ ํ™•์ธํ•˜๋Š” ๊ฒฝ์šฐ, ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด, ์‹ค์ˆ˜๋กœ ํ™˜์ž ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Rollback rules (๋กค๋ฐฑ ๊ทœ์น™):

  • ๊ธฐ๋ณธ์ ์œผ๋กœ ๋Ÿฐํƒ€์ž„ ์˜ˆ์™ธ(RuntimeException ๋ฐ ๊ทธ ํ•˜์œ„ ์˜ˆ์™ธ)๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋กค๋ฐฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค

  • rollbackFor

    • ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑํ•˜๋Š” ๊ทœ์น™์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    @Transactional(rollbackFor = InsufficientBalanceException.class)
    public void transferMoney() {
        // InsufficientBalanceException์ด ๋ฐœ์ƒํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜์€ ๋กค๋ฐฑ๋ฉ๋‹ˆ๋‹ค.
    }
  • noRollbackFor

    • ์ด ์†์„ฑ์€ ์ง€์ •๋œ ์˜ˆ์™ธ ์œ ํ˜•์— ๋Œ€ํ•œ ๋กค๋ฐฑ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ํŠธ๋žœ์žญ์…˜์€ ๋กค๋ฐฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    @Transactional(noRollbackFor = BusinessException.class)
    public void businessOperation() {
        // ...
        // BusinessException์ด ๋ฐœ์ƒํ•ด๋„ ํŠธ๋žœ์žญ์…˜์€ ๋กค๋ฐฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    }

AOP (๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ):

  • ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์—์„œ๋Š” **@Transactional**์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๋Š” Spring์˜ ํ”„๋ก์‹œ ๋ฐฉ์‹ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์™ธ๋ถ€ ๋นˆ์„ ํ†ตํ•ด ๊ฐ„์ ‘์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, ํ”„๋กœ๊ทธ๋žจ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Last updated

Was this helpful?