๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ปSpring์—์„œ MyBatis์™€ JPA, ๋ฌด์—‡์„ ์จ์•ผ ํ• ๊นŒ?

์œค์ค€์ƒยท2025๋…„ 3์›” 21์ผ
0
post-thumbnail

Spring์œผ๋กœ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ MyBatis์™€ JPA๋ฅผ ๋ชจ๋‘ ์ ‘ํ•˜๊ฒŒ ๋œ๋‹ค. ์ฒ˜์Œ์—๋Š” โ€œ๋ญ๊ฐ€ ๋” ์ข‹์€ ๊ฑฐ์ง€?โ€, โ€œ๋‚ด๊ฐ€ ์–ธ์ œ ๋ญ˜ ์จ์•ผ ํ• ๊นŒ?โ€ ๊ฐ™์€ ๊ณ ๋ฏผ์ด ์žˆ๋‹ค.


MyBatis

์žฅ์ 

  • SQL์„ ์ง์ ‘ ์ž‘์„ฑ -> ์ฟผ๋ฆฌ ์ œ์–ด๊ฐ€ ์ž์œ ๋กญ๋‹ค
  • ๋ณต์žกํ•œ JOIN, ๋™์  ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ์— ๊ฐ•ํ•˜๋‹ค
  • ์–ด๋–ค SQL์ด ์‹คํ–‰๋˜๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์ธ๋‹ค

๋‹จ์ 

  • SQL์„ ์ „๋ถ€ ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•ด์„œ ์ƒ์‚ฐ์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ ์‹œ SQL๋„ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์„ค๊ณ„์—๋Š” ์กฐ๊ธˆ ์•ฝํ•œ ๋А๋‚Œ..?
<!-- UserMapper.xml -->
<select id="findByUsername" resultType="User">
  SELECT * FROM users WHERE username = #{username}
</select>
// UserMapper.java
User findByUsername(String username);

MyBatis๋Š” ์ด๋Ÿฐ ๊ณณ์—์„œ ์œ ์šฉํ•œ๋“ฏ

  • ํ†ต๊ณ„, ๋ถ„์„ ๋“ฑ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ๋งŽ์€ ๊ธฐ๋Šฅ
  • ์„ฑ๋Šฅ ํŠœ๋‹์ด ์ค‘์š”ํ•œ ์กฐํšŒ ์ค‘์‹ฌ ์„œ๋น„์Šค
  • SQL ์ž‘์„ฑ์ด ์ต์ˆ™ํ•œ ํŒ€์›๋“ค๊ณผ ํ˜‘์—…ํ•  ๋•Œ

JPA

์žฅ์ 

  • ๊ธฐ๋ณธ์ ์ธ CRUD๋Š” ์ฟผ๋ฆฌ ์—†์ด๋„ ๊ฐ€๋Šฅ -> ์ƒ์‚ฐ์„ฑ์ด ์ข‹๋‹ค
  • ์—”ํ‹ฐํ‹ฐ ์ค‘์‹ฌ์˜ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค
  • ์ง€์—ฐ ๋กœ๋”ฉ, ๋ณ€๊ฒฝ ๊ฐ์ง€ ๊ฐ™์€ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋„ ์ง€์›ํ•œ๋‹ค

๋‹จ์ 

  • ์ฒ˜์Œ์—” ๊ฐœ๋…์ด ๋งŽ๊ณ  ์–ด๋ ต๋‹ค(์˜์†์„ฑ ์ปจํ…์ŠคํŠธ, ์ง€์—ฐ ๋กœ๋”ฉ ๋“ฑ)
  • ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ์ž‘์„ฑ์ด ๋ถˆํŽธํ•˜๊ณ  ์„ฑ๋Šฅ ํŠœ๋‹์ด ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์Œ
  • ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋Š”์ง€ ๊ฐ์ด ์•ˆ ์žกํž ๋•Œ๊ฐ€ ์žˆ์„์ˆ˜๋„..?
// UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

JPA๋Š” ์ด๋Ÿฐ ๊ณณ์—์„œ ์œ ์šฉํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

  • CRUD๊ฐ€ ์ฃผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š” ์ผ๋ฐ˜์ ์ธ ์›น ์„œ๋น„์Šค
  • ๋„๋ฉ”์ธ ์ค‘์‹ฌ์˜ ๊ฐ์ฒด์ง€ํ–ฅ ๋ชจ๋ธ๋ง์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ
  • ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๊นŒ์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•  ๋•Œ

์ •๋ฆฌํ•˜๋ฉฐ

ํ•ญ๋ชฉMyBatisJPA
์ฟผ๋ฆฌ ๋ฐฉ์‹์ง์ ‘ ์ž‘์„ฑ์ž๋™ ์ƒ์„ฑ or JPQL
ํ•™์Šต ๋‚œ์ด๋„์‰ฌ์šด ํŽธ๊ฐœ๋…์ด ๋งŽ์•„ ์–ด๋ ค์›€
์ƒ์‚ฐ์„ฑ๋‚ฎ์Œ (์ฟผ๋ฆฌ ์ง์ ‘ ์ž‘์„ฑ)๋†’์Œ (์ž๋™ ์ฒ˜๋ฆฌ)
๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ•ํ•จ์ œํ•œ์ 
๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์•ฝํ•จ๊ฐ•ํ•จ
์œ ์ง€๋ณด์ˆ˜์–ด๋ ต๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์Œ๊ตฌ์กฐํ™”๋˜์–ด ํŽธํ•จ

๊ฒฐ๊ตญ ์„ ํƒ์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ

๊ฐœ์ธ์ ์œผ๋กœ CRUD ์œ„์ฃผ์˜ ์„œ๋น„์Šค๋Š” JPA,
๋ณต์žกํ•œ ํ†ต๊ณ„์„ฑ ์ฟผ๋ฆฌ๋‚˜ ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ MyBatis๋กœ ๋‚˜๋ˆ ์„œ ์“ฐ๋Š”๊ฒŒ ์ข‹์•˜๋‹ค.
๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ๊ณ ์ง‘ํ•  ํ•„์š”๋Š” ์—†๊ณ , ์ƒํ™ฉ์— ๋”ฐ๋ผ ์„ ํƒํ•˜๊ฑฐ๋‚˜ ํ˜ผํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค.


๊ทธ๋Ÿผ MyBatis๋ž‘ JPA๋Š” ์–ด๋–ป๊ฒŒ ๋Œ์•„๊ฐ€๋Š” ๊ฑธ๊นŒ?

  • MyBatis๋Š” XML์— SQL์„ ์ง์ ‘ ์ž‘์„ฑํ•˜๊ณ , ์ธํ„ฐํŽ˜์ด์Šค๋ž‘ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค

resources/mapper/ ๊ฐ™์€ ๊ฒฝ๋กœ์— XML ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ , SQL์„ <select>, <insert> ๋“ฑ์œผ๋กœ ์ž‘์„ฑํ•ด์ค€๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค ํŒŒ์ผ์—์„œ XML์˜ id ๊ฐ’๊ณผ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค.

<!-- UserMapper.xml -->
<select id="findByUsername" resultType="User">
  SELECT * FROM users WHERE username = #{username}
</select>
// UserMapper.java
@Mapper
public interface UserMapper {
    User findByUsername(String username);
}

์ด๋ ‡๊ฒŒ ๋งคํ•‘ํ•˜๋ฉด UserMapper์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ XML ์•ˆ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
SQL์„ ๋‚ด๊ฐ€ ๋‹ค ์งœ์•ผ ํ•˜๊ธด ํ•˜์ง€๋งŒ, ๊ทธ๋งŒํผ ์ปจํŠธ๋กค๋„ ํ™•์‹คํžˆ ๊ฐ€๋Šฅํ•˜๋‹ค.
๋ณต์žกํ•œ ์กฐ๊ฑด์ด ํ•„์š”ํ•œ ์ฟผ๋ฆฌ๋‚˜ ์„ฑ๋Šฅ ํŠœ๋‹์ด ํ•„์š”ํ•  ๋•Œ ์ง์ ‘ ๊ฑด๋“œ๋ฆด ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ๊ฝค ํฐ ์žฅ์ ์ด๋‹ค.


JPA๋Š” Repository ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๋งŒ๋“ค์–ด๋„ ๊ธฐ๋ณธ์ ์ธ CRUD๋Š” ๋‹ค ๋œ๋‹ค

Spring Data JPA์—์„œ ์ œ๊ณตํ•˜๋Š” JpaRepository๋ฅผ ์ƒ์†๋ฐ›์œผ๋ฉด
๋ณ„๋‹ค๋ฅธ ์„ค์ • ์—†์ด๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

๋ฉ”์„œ๋“œ ์ด๋ฆ„๋งŒ ์ง€์–ด๋„ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋ผ์„œ ์‹คํ–‰๋œ๋‹ค.
๋งŒ์•ฝ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด @Query ์–ด๋…ธํ…Œ์ด์…˜์„ ์จ์„œ JPQL์„ ์ง์ ‘ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ๊ฐ์ฒด ์ค‘์‹ฌ์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด๊ณ ,
์„ค๊ณ„๊ฐ€ ์ž˜ ๋˜์–ด ์žˆ๋‹ค๋ฉด ์œ ์ง€๋ณด์ˆ˜๋‚˜ ํ™•์žฅ๋„ ์ˆ˜์›”ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.


์ด๋ ‡๊ฒŒ ๋™์ž‘ ๋ฐฉ์‹๊นŒ์ง€ ์‚ดํŽด๋ณด๋‹ˆ,
JPA๋Š” ํŽธ๋ฆฌํ•จ๊ณผ ๊ตฌ์กฐ์ ์ธ ์„ค๊ณ„๋ฅผ ์ง€ํ–ฅํ•˜๊ณ ,
MyBatis๋Š” ์ฟผ๋ฆฌ ์ œ์–ด์˜ ์œ ์—ฐํ•จ๊ณผ ์„ฑ๋Šฅ ์ค‘์‹ฌ์˜ ์„ค๊ณ„์— ๊ฐ€๊น๋‹ค๋Š” ๊ฒŒ ํ™•์‹คํžˆ ๋ณด์ธ๋‹ค.

๋‘˜ ๋‹ค ์žฅ๋‹จ์ ์ด ํ™•์‹คํ•ด์„œ ํ”„๋กœ์ ํŠธ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํžˆ ๊ณ ๋ฅด๋Š” ๊ฒŒ ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

profile
ํ˜๋Ÿฌ๊ฐ€๋˜ ์›ํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ

0๊ฐœ์˜ ๋Œ“๊ธ€