π Chapter 2: λꡬ λ€λ£¨κΈ°
π ν μ€ν νλ μμν¬β
λ€μμ μΉκ° κ°μ²΄, νκ³΅νΈ κ°μ²΄λ₯Ό μ
λ ₯λ°μ createReservation
μ passengerInformation
νλ‘νΌν°κ° μΉκ° κ°μ²΄, flightInformation
νλ‘νΌν°κ° νκ³΅νΈ κ°μ²΄μΈ μλ‘μ΄ κ°μ²΄λ₯Ό λ°ννλ€.
function createReservation(passenger, flight) {
return {
passengerInfo: passenger,
flightInfo: flight,
};
}
ν κ·μ μ λ¨μ ν μ€νΈ μμ΄(λ¨μ ν μ€νΈλ₯Ό κ±°μΉμ§ μκ³ ) μ ν μ½λλ₯Ό 체ν¬μΈ(CVS, SVNκ³Ό κ°μ μμ€ κ΄λ¦¬ μλ²μ μμ μ΄ μμ±ν μ½λλ₯Ό λ°μνλ κ²)ν μλ μμΌλ―λ‘ λ¨μ ν μ€νΈ μμ±μ λ°λμ νμνλ€.
describe('createReservation(passenger, flight)', function() {
it('μ£Όμ΄μ§ passengerλ₯Ό passengerInfo νλ‘νΌν°μ ν λΉνλ€', function() {
var testPassenger = {
firstName: 'μ€μ§',
lastName: 'κΉ',
};
var testFlight = {
number: '3443',
carrier: 'λνν곡',
destination: 'μΈμ°,'
};
var reservation = createReservation(testPassenger, testFlight);
expect(reservation.passengerInfo).toBe(testPassenger);
});
it('μ£Όμ΄μ§ flightλ₯Ό flightInfo νλ‘νΌν°μ ν λΉνλ€', function() {
var testPassenger = {
firstName: 'μ€μ§',
lastName: 'κΉ',
};
var testFlight = {
number: '3443',
carrier: 'λνν곡',
destination: 'μΈμ°,'
};
var reservation = createReservation(testPassenger, testFlight);
expect(reservation.flightInfo).toBe(testFlight);
});
});
it
ν¨μ κ°μλ κ°λ³ λ¨μ ν
μ€νΈκ³ (μ΄ μμμλ 2κ°μ λ¨μ ν
μ€νΈκ° μλ€), μ΄λ€μ ν¨μμμ λ°νλ κ°μ²΄μ μμ±μ΄ μ μ νμ§ expect
ν¨μλ‘ κ²μ¬νλ€.
κ·Έλ°λ° λ¨μ ν
μ€νΈμ μ€λ₯κ° λ³΄μΈλ€. λ°νλ μμ½ κ°μ²΄μ μμ±λͺ
μ passengerInformation
κ³Ό flightInformation
μ΄λΌκ³ λͺ
μΈμ λμ μλλ°, createReservation
κ°λ°μ λ무 μλλ₯Έ λλ¨Έμ§ μμ±λͺ
μ passengerInfo
μ flightInfo
λ‘ μλͺ» μ½λ©ν κ²μ΄λ€.
λͺ μΈκ° μλλΌ ν¨μ μ½λμ κ°λ°μ λ°λΌ ν μ€νΈλ₯Ό μμ±ν νμ ν μ€νΈλ κΈ°λνλ ν¨μ μλμ΄ μλ, ꡬνλ ν¨μμ (μλͺ»λ) μ€μ μλμ νμΈν κΌ΄μ΄λ€. λͺ μΈ κΈ°μ€μΌλ‘ ν μ€νΈ μ½λλ₯Ό μμ±νμΌλ©΄ μ λΉμ΄ μμ±λͺ μ ν릴 μΌμ μμμ κ²μ΄λ€.
π μλͺ»λ μ½λ λ°κ²¬νκΈ°β
TDDλ μ½λ κ²°ν¨μ μ΅λν 빨리, 곧 μ½λ μμ± μ§ν κ°μ§νλ©°, μμ κΈ°λ₯ νλλΌλ ν μ€νΈλ₯Ό λ¨Όμ μμ±ν λ€, μ΅μνμ μ½λλ§μΌλ‘ κΈ°λ₯μ ꡬννλ€.
λ€μ createReservation
ν¨μλ‘ λ€μ λμκ° ν
μ€νΈλ₯Ό λ¨Όμ μμ±νλ©΄ μ΄λ»κ² λ¬λΌμ§λ μμ보μ. λ€μ λ§νμ§λ§, μ΄ ν¨μμ λͺ
μΈλ λ€μκ³Ό κ°λ€.
createReservation
μ μΉκ° κ°μ²΄, νκ³΅νΈ κ°μ²΄λ₯Ό μ λ ₯λ°μpassengerInformation
νλ‘νΌν°κ° μΉκ° κ°μ²΄,flightInformation
νλ‘νΌν°κ° νκ³΅νΈ κ°μ²΄μΈ μλ‘μ΄ κ°μ²΄λ₯Ό λ°ννλ€.
λ¨Όμ passengerInformation
νλ‘νΌν° ν λΉμ΄ μ μμ μΈμ§ νμΈνλ ν
μ€νΈλ₯Ό μμ±νλ€.
describe('createReservation(passenger, flight)', function() {
it('μ£Όμ΄μ§ passengerλ₯Ό passengerInformation νλ‘νΌν°μ ν λΉνλ€', function() {
var testPassenger = {
firstName: 'μ€μ§',
lastName: 'κΉ',
};
var testFlight = {
number: '3443',
carrier: 'λνν곡',
destination: 'μΈμ°,'
};
var reservation = createReservation(testPassenger, testFlight);
expect(reservation.passengerInformation).toBe(testPassenger);
});
});
κ·Έλ° λ€μμ μ΄ ν
μ€νΈλ₯Ό μ±κ³΅μν¬ createReservation
μ½λλ₯Ό μ΅μνμΌλ‘ μμ±νλ€.
function createReservation(passenger, flight) {
return {
passengerInfo: passenger,
flightInformation: flight,
};
}
λ¨μ ν
μ€νΈνλ©΄ μ€ν¨νλ€. μ΄μ κ° λκΉ? λ°ν κ°μ²΄μ μμ±λͺ
μ μλͺ»ν΄μ passengerInformation
λμ passengerInfo
λ‘ μ μλ€. μμ±λͺ
μ μ μ νκ³ λ€μ ν
μ€νΈνλ©΄ μ±κ³΅νλ€.
λ°ν κ°μ²΄μ μμ±λͺ
μ μλͺ» μ΄ μ€μκ° createReservation
ν¨μλ₯Ό ꡬνν μ½λμ μ λ³΅ν΄ μμ§λ§, μ΄λ²μλ ν
μ€νΈλ₯Ό λ¨Όμ μμ±ν λ€ λͺ
μΈμ λ°λΌ ν
μ€νΈλ₯Ό νμΌλ―λ‘ λ€λ₯Έ κ°λ°μκ° ν΅ν© ν
μ€νΈλ₯Ό μ§ννλ€κ° μ°λ½ν λκΉμ§ λͺ μκ° κΈ°λ€λ¦¬μ§ μκ³ λ μλ¬λ₯Ό μ¦μ νμΈνμ¬ μ‘°μΉν μ μλ€.
π ν μ€νΈμ±μ κ°μνμ¬ μ€κ³νκΈ°β
ν μ€νΈλ₯Ό λ¨Όμ μμ±νλ 건 μ½λμ ν μ€νΈμ±μ μ°¨νμ λκ³ λ³Ό λ¬Έμ κ° μλλΌ μ°μ μ μΈ μ£Όμ κ΄μ¬μ¬λ‘ μκ°νλ κ²μ΄λ€. ν μ€νΈνκΈ° μ¬μ΄ μ½λκ° μ μ§ λ³΄μμ±κ³Ό νμ₯μ±μ΄ μλ±ν μ°μνλ€. ν μ€νΈμ±μ μ€κ³ λͺ©νλ‘ μ νλ©΄ SOLIDν μ½λλ₯Ό μμ±ν μ μλ€.
TDDμ μΆ©μ€ν μ¬λμ΄λ©΄ 무쑰건 μ μ§ν΄μ createReservation
μ κ³ μΉκΈ°λ³΄λ€λ μΌλ¨ μ κΈ° λ₯μ νμΈνλ ν
μ€νΈλ₯Ό μμ±νλ€. 첫 λ²μ§Έ ν
μ€νΈμμλ μμ½ λ°μ΄ν°κ° μ λλ‘ μΉ μλΉμ€ μ’
λ¨μ κΉμ§ 보λ΄μ‘λμ§λ₯Ό νμΈνλ€.
κ·Έλ°λ° μ¬κΈ°μ createReservation
μ΄ μΉ μλΉμ€ ν΅μ κΉμ§ 맑μμΌ νλ? νλ μλ¬Έμ νλ 건 μκΈ° κ³λ°μ μλΉν λμμ΄ λλ€.
describe('createReservation(passenger, flight)', () => {
// Existing tests
it('μμ½ μ 보λ₯Ό μΉ μλΉμ€ μ’
λ¨μ μΌλ‘ μ μ‘νλ€', () => {
// createReservationμ΄ μΉ μλΉμ€ ν΅μ κΉμ§ 맑μμΌ νλ?
});
});
μ λ΅μ κ·Έλ΄ μΌμ μλ€. μΉ μλΉμ€ ν΅μ μ λ΄ κ°μ²΄κ° μμΌλ©΄ νλ λ§λλ νΈμ΄ μ’λ€. μ½λ ν μ€νΈμ±μ κ·Ήλννλ©΄ SOLID μμΉμ μ΄κΈ΄ μ½ λλ₯Ό μ½κ² μμλΌ μ μλ€.
π κΌ νμν μ½λλ§ μμ±νκΈ°β
TDD μμ μ μ°¨λ μμ κΈ°λ₯ νλλ₯Ό κ²μ¦νλ €λ©΄ μ€ν¨νλ ν μ€νΈλ₯Ό λ¨Όμ μμ±ν λ€, ν μ€νΈλ₯Ό μ±κ³΅μν¬ λ§νΌλ§ μ΅μνμΌλ‘ μ½λ©νλ€. κ·Έ ν λ΄λΆμ μΌλ‘ ꡬν μΈλΆλ₯Ό λ³κ²½νλ 리ν©ν λ§ κ³Όμ μ κ±°μ³ κ°λ° μ€μΈ μ½λμμ μ€λ³΅ μ½λλ₯Ό λ€μ΄λΈλ€.
μ΅μνμ μ½λλ₯Ό λ£μ λ€μ 리ν©ν λ§μΌλ‘ μ€λ³΅ μ½λλ₯Ό μμ κ³ ,... μ΄λ° κ³Όμ μ κ±°μΉλ©΄μ κ²°κ΅ λ§μ§λ§μλ κΌ νμν μ½λλ§ μ΄μλ¨κ² λλ€.
π μμ ν μ μ§ λ³΄μμ 리ν©ν°λ§β
TDDλ₯Ό μ€μ²νλ©΄ νλ‘μ νΈ μ ν μ½λλ₯Ό λμμΌλ‘ νμ€ν λ¨μ ν μ€νΈ κΎΈλ¬λ―Έλ₯Ό ꡬμΆν μ μλ€. μμ μ μ λμκ°λ μ½λκ° μ§κΈμ μ λλ‘ μλνμ§ μλ νκ· κ²°ν¨μ μ½λ νμ§κ³Ό λ―Ώμμ±μ λ¨μ΄λ¨λ¦¬λ μμΈμ΄λ€.
λ¨μ ν μ€νΈμ κ²½μ° ν μ€νΈ κΎΈλ¬λ―Έλ₯Ό κ°λ°/보μνλλΌ μ¬λ° λΉμ©μ΄ λ€μ΄κ°λλ°, 보νκ³Ό λ§μ°¬κ°μ§λ‘ μ΄ μ¬λ° λΉμ©μ μ§λΆνλ λΆλ΄μμ λ²μ΄λλ μμ μ΄ μ¨λ€.
μ’ ν©μ μΈ λ¨μ ν μ€νΈ κΎΈλ¬λ―Έκ° λ§λ ¨λ μ ν μ½λλ₯Ό νμ₯ λλ 보μν λλ λΉμ·ν μλκ°μ λλ μ μλ€. μ€μλ‘ λ€λ₯Έ μ½λλ₯Ό 건λλ¦¬μ§ μμλ°λ νμ μ νκ³ μ½ λ μΌλΆλ₯Ό λ³κ²½ν μ μκΈ° λλ¬Έμ΄λ€.
π μ€ν κ°λ₯ν λͺ μΈβ
TDD μ€μ² κ²°κ³Ό, νννκ² κ΅¬μΆλ λ¨μ ν μ€νΈ κΎΈλ¬λ―Έλ ν μ€νΈ λμ μ½λμ μ€ν κ°λ₯ν λͺ μΈ μν λ νλ€.
createReservation
ν¨μλ‘ μλ₯Ό λ€λ©΄, λ¨μ ν
μ€νΈν κ²°κ³Ό λ©μμ§λ₯Ό λ³΄κ³ μ΄ ν¨μκ° λ¬΄μ¨ μΌμ νλμ§ ν° κ·Έλ¦Όμ κ·Έλ €λ³Ό μ μλ€. createReservation
μ΄ νλ μΌμ κ΅³μ΄ μ½λλ₯Ό μ½κ³ λΆμνμ§ μμλ λ¨μ ν
μ€νΈκ° μ΅λ€ μλ €μ£Όλ μ
μ΄λ€. λ¨μ ν
μ€νΈκ° μ μ¬νλ μ€ν κ°λ₯ λͺ
μΈλ νλ‘μ νΈ μ°Έμ¬ κ°λ°μμκ²λ, κ³Όκ±°μ μμ μ΄ μμ±ν μ½λλ₯Ό λ€μ μ°Ύμ보κ²λ μλ κ°λ°μμκ²λ ν‘ν‘ν νλͺ«νλ€.
π μ¬μ€λ―Ό λ€μ΄κ°κΈ°β
μ¬μ€λ―Όμ νμ μ£Όλ κ°λ°(Behavior-Driven Development, BDD) λ°©μμΌλ‘ μλ°μ€ν¬λ¦½νΈ λ¨μ ν μ€νΈλ₯Ό μμ±νκΈ° μν λΌμ΄λΈλ¬λ¦¬λ€.
λꡬμ λν μμΈν μ€λͺ μ 곡μ ννμ΄μ§λ₯Ό μ°Έμ‘° λ° μ± μ μ°Έκ³ (P.72 ~ P.78)
π μμ‘΄μ± μ£Όμ νλ μμν¬β
π μμ‘΄μ± μ£Όμ μ΄λ?β
μΉνμ μΌλ§ λ¨μ§ μμ μλ°μ€ν¬λ¦½νΈ μ½νΌλ°μ€ νμ¬μ μΉ μ¬μ΄νΈ κ΅¬μΆ μ 무λ₯Ό μμνλ€. μ°Έκ°μ μ’μ μμ½μ νμλ€. μΉνμ μ’μ μμ½ κΈ°λ₯μ κ°μΆ ν΄λΌμ΄μΈνΈ μΈ‘ μ½λ κ°λ°μ 맑μλ€.
DB μ°λμ μ½νΌλ°μ€ μΉ μλΉμ€λ₯Ό νΈμΆνκ² λμ΄ μλ€. κ°μ²΄ μ§ν₯ νλ‘κ·Έλλ° μμΉμ μΆ©μ€ν μΉνμ μ°μ ConferenceWebSvc
κ°μ²΄μ μλΉμ€λ₯Ό μΊ‘μννκ³ λ©μ§ νμ
λ©μμ§λ₯Ό νλ©΄μ νμν μλ°μ€ν¬λ¦½νΈ κ°μ²΄ Messenger
λ₯Ό μμ±νλ€.
μ°Έκ°γ μλ 1μΈλΉ μΈμ μ 10κ°κΉμ§ λ±λ‘ν μ μλ€. μ°Έκ°μκ° ν μΈμ μ λ±λ‘νλ©΄ κ·Έ κ²°κ³Όλ₯Ό μ±κ³΅/μ€ν¨ λ©μμ§λ‘ νλ©΄μ νμνλ ν¨μλ₯Ό κ°λ°ν΄μΌ νλ€. λ€μ μμ λ μ΄κΈ° λ²μ μ΄λ€.
Attendee = function(attendeeId) {
// newλ‘ μμ±νλλ‘ κ°μ νλ€.
if (!(this instanceof Attendee)) {
return new Attendee(attendeeId);
}
this.attendeeId = attendeeId;
this.service = new ConferenceWebSvc();
this.messenger = new Messenger();
};
// μ£Όμ΄μ§ μΈμ
μ μ’μ μμ½μ μλνλ€.
// μ±κ³΅/μ€ν¨ μ¬λΆλ₯Ό λ©μμ§λ‘ μλ €μ€λ€.
Attendee.prototype.reserve = function(sessionId) {
if (this.service.reserve(this.attendeeId, sessionId)) {
this.messenger.success('μ’μ μμ½μ΄ μλ£λμμ΅λλ€!', +
' κ³ κ°λμ' + this.service.getRemainingReservation() +
' μ’μμ μΆκ° μμ½νμ€ μ μμ΅λλ€.');
} else {
this.messenger.failure('μ£μ‘ν©λλ€, ν΄λΉ μ’μμ μμ½νμ€ μ μμ΄λλ€.');
}
};
ConferenceWebSvc
λ΄λΆμλ HTTP νΈμΆμ΄ μλ€. μ΄λ κ² HTTP ν΅μ μ΄ νμν μ½λλ λ¨μ ν
μ€νΈλ₯Ό μ΄λ»κ² ν κΉ? λ¨μ ν
μ€νΈλ κ·Έ μμ²΄λ‘ μ μνκ³ νκ³ ν΄μΌ νλ€. κ·Έλ¦¬κ³ Messenger
λ λ©μμ§λ§λ€ OK λ²νΌμ΄ μμ΄μΌ νλλ°, μ΄ λν μ΄ λͺ¨λμμ λ¨μ ν
μ€νΈν λμμ μλλ€.
Attendee
κ°μ²΄κ° μλλΌ μ΄ κ°μ²΄κ° μμ‘΄νλ μ½λλ€. μμ‘΄μ±μ μ£Όμ
νλ μμΌλ‘ λ°κΎΈλ©΄ ν΄κ²°ν μ μλ€. μ¦, ConferenceWebSvc
μ Messenger
μμ μμ‘΄μ±μ νλ μ½λ±νμ§ λ§κ³ μ΄λ€μ Attendee
μ μ£Όμ
νλ κ²μ΄λ€. λ¨μ ν
μ€νΈμ©μΌλ‘λ λͺ¨μ체(fake)λ μ¬μ€λ―Ό μ€νμ΄ κ°μ λ체μ λ₯Ό μ£Όμ
νλ©΄ λλ€.
// μ΄μ νκ²½:
var attendee = new Attendee(new ConferenceWebSvc(), new Messenger(), id);
// κ°λ°(ν
μ€νΈ) νκ²½:
var attendee = new Attendee(fakeService, fakeMessenger, id);
μ΄μ²λΌ DI νλ μμν¬λ₯Ό μ¬μ©νμ§ μκ³ μμ‘΄μ±μ μ£Όμ
νλ κ²μ λκ³ λΉμμ μμ‘΄μ± μ£Όμ
μ΄λΌ νλ€. λ€μ μμ λ λΉμμ μμ‘΄μ± μ£Όμ
λ°©μμΌλ‘ μμ±ν Attendee
κ°μ²΄λ€.
Attendee = function(service, messenger, attendeeId) {
// newλ‘ μμ±νλλ‘ κ°μ νλ€.
if (!(this instanceof Attendee)) {
return new Attendee(attendeeId);
}
this.attendeeId = attendeeId;
this.service = service;
this.messenger = messenger;
}
π μμ‘΄μ±μ μ£Όμ νμ¬ λ―Ώμμ§ν μ½λ λ§λ€κΈ°β
DIλ μ€μ κ°μ²΄λ³΄λ€ μ£Όμ ν μ€νμ΄λ λͺ¨μ κ°μ²΄μ λ λ§ μ μ μ΄κΆμ μ겨주λ―λ‘ λ€μν μλ¬ μ‘°κ±΄κ³Ό κΈ°μ΄ν μν©μ λ§λ€μ΄λ΄κΈ° μ½λ€. νΉμ λͺ¨λ₯Ό λ§μ½μ μ¬νλ₯Ό νλκ² μ»€λ²ν μ μκ² ν μ€νΈλ₯Ό μμ±ν μ μλ€.
λν, DIλ μ½λ μ¬μ¬μ©μ μ κ·Ήμ μΌλ‘ μ λνλ€. μμ‘΄μ±μ νμ, νλ μ½λ©ν λͺ¨λμ λ¬΄κ±°μ΄ μ§μ μ§μ§ λκ³ λ€λλ ν°λΌ λ³΄ν΅ μ¬μ¬μ©νκΈ° μ΄λ ΅λ€.
π μμ‘΄μ± μ£Όμ μ λͺ¨λ κ²β
μμ‘΄μ± μ£Όμ μ μ΄λ ΅μ§ μλ€. λλ¦¬μ΄ μΆμ νΈμνκ² ν΄μ€λ€.
μ΄λ€ κ°μ²΄λ₯Ό μ½λ©νλ μ΄λ€ κ°μ²΄λ₯Ό μμ±νλ μ§ μ€μ€λ‘ λ€μ μ§λ¬Έμ ν΄λΆμ. ν κ°μ§λΌλ λ΅λ²μ΄ μλΌλ©΄ μ§μ μΈμ€ν΄μ€ννμ§ λ§κ³ μ£Όμ νλ λ°©ν₯μΌλ‘ μκ°μ μ ννλΌ.
- κ°μ²΄ λλ μμ‘΄μ± μ€ μ΄λ νλλΌλ DB, μ€μ νμΌ, HTTP, κΈ°ν μΈνλΌ λ±μ μΈλΆ μμμ μμ‘΄νλκ°?
- κ°μ²΄ λ΄λΆμμ λ°μν μ§ λͺ¨λ₯Ό μλ¬λ₯Ό ν μ€νΈμμ κ³ λ €ν΄μΌ νλ?
- νΉμ ν λ°©ν₯μΌλ‘ κ°μ²΄λ₯Ό μλμμΌμΌ ν ν μ€νΈκ° μλκ°?
- μ΄ μλνν° μ 곡 κ°μ²΄κ° μλλΌ μ¨μ ν λ΄κ° μμ ν κ°μ²΄μΈκ°?
π μ¬λ‘ μ°κ΅¬: κ²½λκΈ μμ‘΄μ± μ£Όμ νλ μμν¬ κ°λ°β
μ§κΈκΉμ§λ μμ‘΄μ± μ£Όμ μ νλ μ½λ©νλ€. μ΅μ μ μλλ€. μ λ¬Έκ°λ€μ΄ μμ‘΄μ± μ£Όμ νλ μμν¬λ μ΄λ κ² μλνλ€.
- μ ν리μΌμ΄μ μ΄ μμλμλ§μ κ° μΈμ ν°λΈ(injectable: μ£Όμ κ°λ₯ν, λͺ¨λ μμ‘΄μ±μ μ§ν©μ μΌλ‘ μΌμ»«λ λ§μ΄λ€) λͺ μ νμΈνκ³ ν΄λΉ μΈμ ν°λΈμ΄ μ§λ μμ‘΄μ±μ μ§μΉνλ©° μμλλ‘ DI 컨ν μ΄λμ λ±λ‘νλ€.
- κ°μ²΄κ° νμνλ©΄ 컨ν μ΄λμ μμ²νλ€.
- 컨ν μ΄λλ μΌλ¨ μμ²λ°μ κ°μ²΄μ κ·Έ μμ‘΄μ±μ λͺ¨λ μ¬κ·μ μΌλ‘ μΈμ€ν΄μ€ννλ€. κ·Έλ° λ€μ, μ건μ λ°λΌ νμν κ°μ²΄μ κ°κ° μ£Όμ νλ€.
μ¬κΈ°μ μ€λͺ νλ μμ λ μλ½.. μ± μ μ°Έκ³ (P.81 ~ P.90)
TIPβ
- λμ± νμ€ν λ€κ±°ν°λΈ ν μ€νΈ(negative test)λ₯Ό μν΄μλ μλ¬κ° λ¬λ€λ μ¬μ€λΏλ§ μλλΌ μ€μ μλ¬ λ©μμ§κΉμ§ νμΈνλΌ. νλ‘ν νμ μ΄λ ν¨μλ₯Ό ν΅ν΄ ν μ€νΈ λμμ΄ κ°μ§ λ©μμ§λ₯Ό λ°μΌλ‘ νμΆνλ κ²μ΄λ€.
- μλ¬ μ²λ¦¬ μ½λλ₯Ό μ μΌ λ¨Όμ ν μ€νΈνλΌ. κ·Έλ€μ λ€λ₯Έ μ λ¬΄λ‘ λμ΄κ°λ λ¦μ§ μλ€.
- μ½λκ° μ ν μμ΄λ μ’μΌλ ν μ€νΈλ₯Ό μ±κ³΅μν¬ μ΅μνμ μ½λλ§ μμ±νλΌ. μ ν리μΌμ΄μ μ½λκ° ν μ€νΈλ³΄λ€ μμ λκ°λ©΄ μ λλ€.
- 리ν°λ΄ λμ λ³μλͺ μ μ μ ν΄μ DRYνκ³ μκΈ° μμ μ μΈ ν μ€νΈλ₯Ό μμ±νλΌ.