Chapter 5 - KOO-YS/toby-spring GitHub Wiki
- ์คํ๋ง์ด ์ด๋ป๊ฒ ์ฑ๊ฒฉ์ด ๋น์ทํ ์ฌ๋ฌ ์ข ๋ฅ์ ๊ธฐ์ ์ ์ถ์ํํ๊ณ ์ด๋ฅผ ์ผ๊ด๋ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก ์ง์ํ๋์ง ์ดํด๋ณด๊ธฐ
๐ฑ Branch chapter05/refactor5.1์ ์ค์ต ์ ์ฉ
-
์๋ : ์ ๊ธฐ์ ์ผ๋ก ์ฌ์ฉ์์ ํ๋ ๋ด์ญ์ ์ฐธ๊ณ ํด์ ๋ ๋ฒจ์ ์กฐ์ ํด์ฃผ๋ ๊ธฐ๋ฅ ์ถ๊ฐ
-
์ฝ๋ ๋ฐ์ : User ํด๋์ค -> **์ฌ์ฉ์ ๋ ๋ฒจ ํ๋ [level : BASIC, SILVER, GOLD]**๋ฅผ ์ถ๊ฐ
DB์ varchar ํ์ ์ผ๋ก ์ ์ธํ๊ณ ๋ฌธ์ํ์ผ๋ก BASIC, SILVER, GOLD๋ฅผ ๋ฃ์ ์๋ ์์ง๋ง,
โถ ์ด๋ ํด๋์ค ์ถ๊ฐ ์๋ฃ
public enum Level { BASIC(1), SILVER(2), GOLD(3); private final int value; Level(int value) { this.value = value; // DB์ ์ ์ฅํ int ํ์ ์ ๊ฐ์ ๊ฐ์ง๊ณ ์์ง๋ง ๊ฒ์ผ๋ก๋ Level ํ์ ์ค๋ธ์ ํธ } // ... }
โถ DB ํ๋ ์ถ๊ฐ ์๋ฃ : users ํ ์ด๋ธ์ ํ๋ ์ถ๊ฐ
๋ฐ์ดํฐ ์ก์ธ์ค ๋ก์ง๊ณผ ๋น์ฆ๋์ค ๋ก์ง ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ์ฌ ์๋ก๊ฐ ๋ฐ๋์ด๋ ์ํฅ๋ฐ์ง ์๋๋ก ํ๋ค
โถ UserService ํด๋์ค ์์ฑ
๐ฑ Branch chapter05/refactor5.2์ ์ค์ต ์ ์ฉ
์ฌ์ฉ์ ๋ ๋ฒจ ์ ๊ทธ๋ ์ด๋๋ฅผ ์๋ํ๋ค๊ฐ ์ค๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํ์ ๊ฒฝ์ฐ ๊ทธ์ ์ ์ ๊ทธ๋ ์ด๋ ํ๋ ์ฌ์ฉ์๋ ๋ค์ ์๋ ์ํ๋ก ๋์๊ฐ๋์ง ํ์ธํ๊ธฐ
-> ๋ค์ ์ฒ๋ฆฌ์ ์์ธ๊ฐ ๋ฐ์ํ์์๋ ๋ถ๊ตฌํ๊ณ ์์ ์ ๊ทธ๋ ์ด๋๋ ๋์๊ฐ์ง ์๋๋ค
java.lang.AssertionError:
Expected: is <BASIC>
but: was <SILVER>-
๋ ์ด์ ๋๋ ์ ์๋ ๋จ์ ์์
-
์์์ฑ : ์์ ์ ์ชผ๊ฐ์ ์์ ๋จ์๋ก ๋ง๋ค ์ ์๋ ํธ๋์ญ์ ์ ํต์ฌ ์์ฑ
-
์ค๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํด์ ์์ ์ ์๋ฃํ ์ ์๋ค๋ฉด ์์ ์์ ์ด ์์๋์ง ์์ ๊ฒ ์ฒ๋ผ ์ด๊ธฐ ์ํ๋ก ๋๋ ค๋์ผํ๋ค
ํธ๋์ญ์
๋กค๋ฐฑ : ๋ ๊ฐ์ง ์์
์ด ํ๋์ ํธ๋์ญ์
์ด ๋ ๋, ๋ ๋ฒ์งธ SQL์ด ์ํ ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ์์์ ์ฒ๋ฆฌํ SQL ์์
๋ ์ทจ์์์ผ์ผ ํ๋ค
ํธ๋์ญ์
์ปค๋ฐ : ์ฌ๋ฌ ๊ฐ์ SQL์ ํ๋์ ํธ๋์ญ์
์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ์ ๋ชจ๋ SQL ์ํ ์์
์ด ๋ค ์ฑ๊ณต์ ์ผ๋ก ๋ง๋ฌด๋ฆฌ๋๋ค๊ณ DB์ ์๋ ค์ค ํ ์์
์ ํ์ ์ง์
- Rollback : ๋ชจ๋ ์์ ์ ๋ฌดํจํํ๋ ๋กค๋ฐฑ
- Commit : ๋ชจ๋ ์์ ์ ๋ค ํ์ ํ๋ ์ปค๋ฐ
ํ๋์ Connection์ ๊ฐ์ ธ์ ์ฌ์ฉํ๋ค๊ฐ ๋ซ๋ ์ฌ์ด์์ ์ผ์ด๋จ
ํธ๋์ญ์
์ ์์๊ณผ ์ข
๋ฃ๋ Connection ์ค๋ธ์ ํธ๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋ค
Connection c = dataSource.getConnection();
c.setAutoCommit(false); // ํธ๋์ญ์
์์
// ...
// ...
c.commit();
// or
c.rollback();โถ
setAutoCommit(false)๋ก ํธ๋์ญ์ ์ ์์์ ์ ์ธํ๊ณcommit()๋๋rollback()์ผ๋ก ํธ๋์ญ์ ์ ์ข ๋ฃํ๋ ์์ ์ **ํธ๋์ญ์ ์ ๊ฒฝ๊ณ์ค์ (transaction demarcation)**์ด๋ผ๊ณ ํ๋ค
โถ
๋ก์ปฌ ํธ๋์ญ์ : ํ๋์ DB ์ปค๋ฅ์ ์์์ ๋ง๋ค์ด์ง๋ ํธ๋์ญ์
(1) DB Connection ์์ฑ
(2) ํธ๋์ญ์
์์
try{
(3) DAO ๋ฉ์๋ ํธ์ถ
(4) ํธ๋์ญ์
์ปค๋ฐ
} catch(Exception e){
(5) ํธ๋์ญ์
๋กค๋ฐฑ
}finally {
(6) DB Connection ์ข
๋ฃ
}- UserService ๋ฉ์๋๋ค์ Connection ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋๋ค? -> DAO๋ฅผ ํ์๋ก ํ ๋ ๊ทธ ์ฌ์ด ๋ชจ๋ ๋ฉ์๋์ ๊ฑธ์ณ์ Connection ์ค๋ธ์ ํธ๊ฐ ๊ณ์ ์ ๋ฌ๋ผ์ผ ํ๋ค
- Connection ํ๋ผ๋ฏธํฐ๊ฐ UserDao ์ธํฐํ์ด์ค ๋ฉ์๋์ ์ถ๊ฐ๋๋ฉด UserDao๋ ๋์ด์ ๋ฐ์ดํฐ ์ก์ธ์ค ๊ธฐ์ ์ ๋ ๋ฆฝ์ ์ผ ์๊ฐ ์๋ค๋ ์
-
UserService์์ ํธ๋์ญ์ ์ ์์ํ๊ธฐ ์ํด ๋ง๋ Connection ์ค๋ธ์ ํธ๋ฅผ ํน๋ณํ ์ ์ฅ์์ ๋ณด๊ดํด๋๊ณ , ์ดํ์ ํธ์ถ๋๋ DAO ๋ฉ์๋์์๋ ์ ์ฅ๋ Connection์ ๊ฐ์ ธ๋ค๊ฐ ์ฌ์ฉํ๊ฒ ํ๋ ๊ฒ
-
ํธ๋์ญ์ ๋๊ธฐํ ์ ์ฅ์๋ ์์ ์ค๋ ๋๋ง๋ค ๋ ๋ฆฝ์ ์ผ๋ก Connection ์ค๋ธ์ ํธ๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ค์ค ์ฌ์ฉ์๋ฅผ ์ฒ๋ฆฌํ๋ ์๋ฒ์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ์ถฉ๋์ด ๋ ์ผ๋ ค๊ฐ ์๋ค
-
์คํ๋ง์ JdbcTemplate๊ณผ ๋๋ถ์ด ํธ๋์ญ์ ๋๊ธฐํ ๊ธฐ๋ฅ์ ์ง์ํ๋ ๊ฐ๋จํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ฅผ ์ ๊ณต ->
DataSourceUtils -
TransactionSynchronizationManager: ์คํ๋ง์ด ์ ๊ณตํ๋ ํธ๋์ญ์ ๋๊ธฐํ ๊ด๋ฆฌ ํด๋์ค. ์ด ํด๋์ค๋ฅผ ์ด์ฉํด ๋จผ์ ํธ๋์ญ์ ๋๊ธฐํ ์์ ์ ์ด๊ธฐํํ๋๋ก ์์ฒญpublic void upgradeLevels() throws SQLException { // ํธ๋์ญ์ ๋๊ธฐํ ๊ธฐ๋ฅ์ ์ง์ํ๋ ์คํ๋ง์ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ TransactionSynchronizationManager.initSynchronization(); // ํธ๋์ญ์ ๋๊ธฐํ ๊ด๋ฆฌ์๋ฅผ ์ด์ฉํด ๋๊ธฐํ ์์ ์ ์ด๊ธฐํ Connection c = DataSourceUtils.getConnection(dataSource); // DB ์ปค๋ฅ์ ์์ฑ๊ณผ ๋๊ธฐํ๋ฅผ ํจ๊ป ํด์ฃผ๋ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ c.setAutoCommit(false); // DB ์ปค๋ฅ์ ์ ์์ฑํ๊ณ ํธ๋์ญ์ ์ ์์ // ์ดํ DAO ์์ ์ ๋ชจ๋ ์ฌ๊ธฐ์๋ถํฐ ์์ํ ํธ๋์ญ์ ์์์ ์งํ๋๋ค try { List<User> users = userDao.getAll(); for (User user : users) { if (canUpgradeLevel(user)) // ํ ๋ช ์ฉ ์ ๊ทธ๋ ์ด๋ ๊ฐ๋ฅํ์ง ํ์ธ upgradeLevel(user); // ํ ๋ช ์ ๊ทธ๋ ์ด๋ } c.commit(); // ์ ์ ์ข ๋ฃ } catch (Exception e){ c.rollback(); // ์์ธ ๋ฐ์ -> ๋ฐ์ดํฐ ๋๋๋ฆฌ๊ธฐ throw e; } finally { DataSourceUtils.releaseConnection(c, dataSource); // DB ์ปค๋ฅ์ ์ ์์ ํ๊ฒ ๋ซ๋๋ค // ๋๊ธฐํ ์์ ์ข ๋ฃ ๋ฐ ์ ๋ฆฌ TransactionSynchronizationManager.unbindResource(this.dataSource); TransactionSynchronizationManager.clearSynchronization(); } }
- ํ๋์ ํธ๋์ญ์ ์์์ ์ฌ๋ฌ ๊ฐ์ DB์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๋ ์์ ์ ํด์ผํ ํ์ ๋ฐ์ํ์ ๋ ์ฌ์ฉ
- ๋ณ๋์ ํธ๋์ญ์ ๊ด๋ฆฌ์๋ฅผ ํตํด ํธ๋์ญ์ ์ ๊ด๋ฆฌ
- ์๋ฐ๋ JDBC ์ธ์ ๊ธ๋ก๋ฒ ํธ๋์ญ์
์ ์ง์ํ๋ ํธ๋์ญ์
๋งค๋์ ๋ฅผ ์ง์ํ๊ธฐ ์ํ API์ธ
JTA(Java Transaction API)๋ฅผ ์ ๊ณต
DB ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด SQL์ ์ด์ฉํ๋ ๋ฐฉ์์ ๊ณตํต์ ์ ๋ฝ์๋ด ์ถ์ํ ํ JDBC ๋๋ถ์ DB ์๊ด์์ด ์ผ๊ด๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ฐ์ดํฐ ์์ธ์ค ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ ๊ฒ์ฒ๋ผ, ํธ๋์ญ์
์ฒ๋ฆฌ ์ฝ๋์๋ ์ถ์ํ๋ฅผ ๋์
ํ๋ค๋ฉด?
์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง์ ์ข ๋ฅ์ ๋ฐ๋ฅธ ์ํ์ ๊ตฌ๋ถ์ด๋ ,
๋ก์ง๊ณผ ๊ธฐ์ ์ด๋ผ๋ ์์ง์ ์ธ ๊ตฌ๋ถ์ด๋ ,
๋ชจ๋ ๊ฒฐํฉ๋๊ฐ ๋ฎ์ผ๋ฉฐ ์๋ก ์ํฅ์ ์ฃผ์ง ์๊ณ ์์ ๋กญ๊ฒ ํ์ฅ๋ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค ์ ์๋ ๋ฐ๋ ์คํ๋ง์ DI๊ฐ ์ค์ํ ์ญํ ์ ํ๊ณ ์๋ค
์ด๋ฌํ ์ ์ ํ ๋ถ๋ฆฌ๊ฐ ๊ฐ์ ธ์ค๋ ํน์ง์ ๊ฐ์ฒด์งํฅ ์ค๊ณ์ ์์น ์ค์ ํ๋์ธ ๋จ์ผ ์ฑ ์ ์์น์ผ๋ก ์ค๋ช ํ ์ ์๋ค
ํ๋์ ๋ชจ๋์ ํ ๊ฐ์ง ์ฑ ์์ ๊ฐ์ ธ์ผ ํ๋ค.
ํ๋์ ๋ชจ๋์ด ๋ฐ๋๋ ์ด์ ๋ ํ ๊ฐ์ง์ฌ์ผ ํ๋ค.
๋จ์ผ ์ฑ ์ ์์น์ ์ฅ์
๋จ์ผ ์ฑ ์ ์์น์ ์ ์งํค๋ ์ฝ๋๋ฅผ ๋ง๋๋ ค๋ฉด?
์ธํฐํ์ด์ค ๋์ ํ, DI๋ก ์ฐ๊ฒฐ
๊ฐ๋ฐฉ ํ์ ์์น ๋ํ ์ค์
๋ชจ๋ ๊ฐ์ ๊ฒฐํฉ๋๊ฐ ๋ฎ์์ ์๋ก์ ๋ณ๊ฒฝ์ด ์ํฅ์ ์ฃผ์ง ์์
๋ณ๊ฒฝ์ด ๋จ์ผ ์ฑ ์์ ์ง์ค๋์ด ์์ง๋๊ฐ ๋์์ผํจ
๐ฑ Branch chapter05/refactor5.4์ ์ค์ต ์ ์ฉ
โถ ๋ฉ์ผ ์๋น์ค๋ฅผ ์ํ Userํด๋์ค์ ํ๋กํผํฐ์ DB์ ์ปฌ๋ผ ์ถ๊ฐ ์๋ฃ
- ์๋ฐ์์ ๋ฉ์ผ์ ๋ฐ์กํ ๋ ํ์ค ๊ธฐ์
-
javax.mailํจํค์ง์์ ์ ๊ณตํ๋ ์๋ฐ์ ์ด๋ฉ์ผ ํด๋์ค๋ฅผ ์ฌ์ฉ
- ๋ฉ์ผ ์ ์ก ๋ฉ์๋๋ฅผ ํ
์คํธํ๊ธฐ ์ํด ๋งค๋ฒ ์ค์ ๋ฉ์ผ์ ๋ฐ์กํ๋ ๊ฒ์ ๋ถ์ ํฉ ->
์๋ฒ ๋ถํ- ํ ์คํธ์ฉ ๋ฉ์ผ ์๋ฒ๋ฅผ ์ด์ฉํ์
- ๋ฉ์ผ ํ ์คํธ๋ฅผ ์ํด ๋งค๋ฒ ๋ฉ์ผ ์์ ์ฌ๋ถ๊น์ง ์ผ์ผ์ด ํ์ธํ๊ธฐ ๋ณด๋จ, ํ ์คํธ ๊ฐ๋ฅํ ๋ฉ์ผ ์๋ฒ๊น์ง๋ง ์ ์ ์ก๋๋์ง ํ์ธํ์
-
JavaMail์ API๋ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค
-
Session์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ด์ผ๋ง ๋ฉ์ผ ๋ฉ์์ง๋ฅผ ์์ฑ, ์ ์ก ๊ฐ๋ฅ -> Session์ ํด๋์ค๋ค..(์ธํฐํ์ด์ค X) -
์์ฑ์๊ฐ ๋ชจ๋
private๋ก ์ ์ธ๋์ด ์์ด์ ์ง์ ์์ฑ์ด ๋ถ๊ฐ๋ฅํ๋ค -
Sessionํด๋์ค๋ ๋ ์ด์ ์์์ด ๋ถ๊ฐ๋ฅํ final ํด๋์ค์ด๋ค -
MailMessage(๋ฉ์ผ ๋ฉ์์ง ์์ฑ),Transport(์ ์ก)๋ ๋ง์ฐฌ๊ฐ์ง..@Deprecated private void sendUpgradeEMail(User user) { Properties props = new Properties(); props.put("mail.smtp.host", "mail.yaans.com"); Session s = Session.getInstance(props, null); MimeMessage message = new MimeMessage(s); // ๋ฉ์ผ ๋ฉ์์ง ์์ฑ try { message.setFrom(new InternetAddress(TEMP_EMAIL)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail())); message.setSubject("Upgrade ์๋ด"); message.setText(user.getName()+" ์ฌ์ฉ์๋์ ๋ฑ๊ธ์ด "+user.getLevel().name()+"๋ก ์ ๊ทธ๋ ์ด๋ ๋์์ต๋๋ค"); Transport.send(message); // ์ ์ก } catch (AddressException e) { e.printStackTrace(); } catch (MessagingException e) { e.printStackTrace(); } }
-
MailSenderInterface ์ฌ์ฉ :SimpleMailMessage์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค์ ๋ด๊ธด ๋ฉ์ผ ๋ฉ์์ง ์ ์ก์ ํ๋ ๋ฉ์๋๋ก ๊ตฌ์ฑprivate void sendUpgradeEMail(User user){ // (์คํ๋ง์ด ์ฌ๊ณตํ๋ )JavaMail์ ์ฌ์ฉํด ๋ฉ์ผ ๋ฐ์ก ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ JavaMailSenderImpl ํด๋์ค JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost("mail.server.com"); SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setTo(user.getEmail()); mailMessage.setFrom(TEMP_EMAIL); mailMessage.setSubject("Upgrade ์๋ด"); mailMessage.setText(user.getName()+" ์ฌ์ฉ์๋์ ๋ฑ๊ธ์ด "+user.getLevel().name()+"๋ก ์ ๊ทธ๋ ์ด๋ ๋์์ต๋๋ค"); mailSender.send(mailMessage); }
JavaMail์ด ์๋ ๋ค๋ฅธ ๋ฉ์์ง ์๋ฒ์ API๋ฅผ ์ด์ฉํด ๋ฉ์ผ์ ์ ์กํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ฒจ๋, ํด๋น ๊ธฐ์ ์ API๋ฅผ ์ด์ฉํ์ง ์๋ MailSender ๊ตฌํ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ DIํด์ฃผ๋ฉด ๋๋ค
DummyMailSender๊ฐ ๋น ํด๋์ค์์๋ ๋ถ๊ตฌํ๊ณ ๋ฉ์ผ ๊ธฐ๋ฅ ํ
์คํธ๋ฅผ ํจ์ ์์ด์ ๊ต์ฅํ ์ ์ฉํ๋ค.
์ด์ฒ๋ผ ํ ์คํธ ํ๊ฒฝ์์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ๋ ๊ธฐ๋ฒ :
-
ํ ์คํธ ๋์์ด ๋๋ ์ค๋ธ์ ํธ์ ๊ธฐ๋ฅ์๋ง ์ถฉ์คํ๊ฒ ์ํํ๋ฉด์ ๋น ๋ฅด๊ฒ, ์์ฃผ ํ ์คํธ๋ฅผ ์คํํ ์ ์๋๋ก ์ฌ์ฉํ๋ ์ค๋ธ์ ํธ๋ฅผ ํต๋ค์ด์ ํ๋ ๋ง
- ex)
UserServiceTest์ ๊ด์ฌ์ฌ๋UserService์์ ๊ตฌํํด๋์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ๊ณตํ๋ ๋น์ฆ๋์ค ๋ก์ง์ด์ง, ๋ฉ์ผ์ด ์ด๋ป๊ฒ ์ ์ก๋ ๊ฒ์ธ์ง๊ฐ ์๋ -> ํ ์คํธ ์,DummyMailSender๋ก ์ ํํด์ ์ฌ์ฉ
- ex)
-
ํ ์คํธ ์คํ (test stub)
- ๋ํ์ ์ธ ํ ์คํธ ๋์ญ
- ํ ์คํธ ๋์ ์ค๋ธ์ ํธ์ ์์กด๊ฐ์ฒด๋ก์ ์กด์ฌ & ํ ์คํธ ๋์์ ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ์ํํ ์ ์๋๋ก ๋๋ ๊ฒ
- ์ผ๋ฐ์ ์ผ๋ก ๋ฉ์๋๋ฅผ ํตํด ์ ๋ฌํ๋ ํ๋ผ๋ฏธํฐ์ ๋ฌ๋ฆฌ, ํ ์คํธ ์ฝ๋ ๋ด๋ถ์์ ๊ฐ์ ์ ์ผ๋ก ์ฌ์ฉ
- DI ๋ฑ์ ํตํด ๋ฏธ๋ฆฌ ์์กด ์ค๋ธ์ ํธ๋ฅผ ํ
์คํธ ์คํ
์ผ๋ก ๋ณ๊ฒฝํด์ผํ๋ค ex)
DummyMailSender
-
๋ชฉ ์ค๋ธ์ ํธ(mock object)
- ํ ์คํธ ๋์์ ๊ฐ์ ์ ์ธ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๊ณ , ํ ์คํธ ๋์ ์ค๋ธ์ ํธ์ ์์กด ์ค๋ธ์ ํธ "์ฌ์ด"์์ ์ผ์ด๋๋ ์ผ์ ๊ฒ์ฆํ ์ ์๋๋ก **ํน๋ณํ๊ฒ ์ค๊ณ๋ ์ค๋ธ์ ํธ **
- ํ ์คํธ ์ค๋ธ์ ํธ๊ฐ ์ ์์ ์ผ๋ก ์คํ๋๋๋ก ๋์์ฃผ๋ฉด์, ํ ์คํธ ์ค๋ธ์ ํธ์ ์์ ์ ์ฌ์ด์์ ์ผ์ด๋๋ ์ปค๋ฎค๋์ผ์ด์ ๋ด์ฉ์ ์ ์ฅํด๋๋ค๊ฐ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ ๋ฐ ํ์ฉํ ์ ์๊ฒ ํด์ค