본문으둜 κ±΄λ„ˆλ›°κΈ°

🌈 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, 기타 인프라 λ“±μ˜ μ™ΈλΆ€ μžμ›μ— μ˜μ‘΄ν•˜λŠ”κ°€?
  • 객체 λ‚΄λΆ€μ—μ„œ λ°œμƒν• μ§€ λͺ¨λ₯Ό μ—λŸ¬λ₯Ό ν…ŒμŠ€νŠΈμ—μ„œ κ³ λ €ν•΄μ•Ό ν•˜λ‚˜?
  • νŠΉμ •ν•œ λ°©ν–₯으둜 객체λ₯Ό μž‘λ™μ‹œμΌœμ•Ό ν•  ν…ŒμŠ€νŠΈκ°€ μžˆλŠ”κ°€?
  • 이 μ„œλ“œνŒŒν‹° 제곡 객체가 μ•„λ‹ˆλΌ μ˜¨μ „νžˆ λ‚΄κ°€ μ†Œμœ ν•œ 객체인가?

🎈 사둀 연ꡬ: κ²½λŸ‰κΈ‰ μ˜μ‘΄μ„± μ£Όμž… ν”„λ ˆμž„μ›Œν¬ κ°œλ°œβ€‹

μ§€κΈˆκΉŒμ§€λŠ” μ˜μ‘΄μ„± μ£Όμž…μ„ ν•˜λ“œ μ½”λ”©ν–ˆλ‹€. μ΅œμ„ μ€ μ•„λ‹ˆλ‹€. μ „λ¬Έκ°€λ‹€μš΄ μ˜μ‘΄μ„± μ£Όμž… ν”„λ ˆμž„μ›Œν¬λŠ” μ΄λ ‡κ²Œ μž‘λ™ν•œλ‹€.

  1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹œμž‘λ˜μžλ§ˆμž 각 인젝터블(injectable: μ£Όμž… κ°€λŠ₯ν•œ, λͺ¨λ“  μ˜μ‘΄μ„±μ„ μ§‘ν•©μ μœΌλ‘œ μΌμ»«λŠ” 말이닀) λͺ…을 ν™•μΈν•˜κ³  ν•΄λ‹Ή 인젝터블이 μ§€λ‹Œ μ˜μ‘΄μ„±μ„ μ§€μΉ­ν•˜λ©° μˆœμ„œλŒ€λ‘œ DI μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘ν•œλ‹€.
  2. 객체가 ν•„μš”ν•˜λ©΄ μ»¨ν…Œμ΄λ„ˆμ— μš”μ²­ν•œλ‹€.
  3. μ»¨ν…Œμ΄λ„ˆλŠ” 일단 μš”μ²­λ°›μ€ 객체와 κ·Έ μ˜μ‘΄μ„±μ„ λͺ¨λ‘ μž¬κ·€μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€ν™”ν•œλ‹€. 그런 λ‹€μŒ, μš”κ±΄μ— 따라 ν•„μš”ν•œ 객체에 각각 μ£Όμž…ν•œλ‹€.

μ—¬κΈ°μ„œ μ„€λͺ…ν•˜λŠ” μ˜ˆμ œλŠ” 생락.. 책을 μ°Έκ³ (P.81 ~ P.90)

TIP​

  • λ”μš± ν™•μ‹€ν•œ λ„€κ±°ν‹°λΈŒ ν…ŒμŠ€νŠΈ(negative test)λ₯Ό μœ„ν•΄μ„œλŠ” μ—λŸ¬κ°€ λ‚¬λ‹€λŠ” μ‚¬μ‹€λΏλ§Œ μ•„λ‹ˆλΌ μ‹€μ œ μ—λŸ¬ λ©”μ‹œμ§€κΉŒμ§€ ν™•μΈν•˜λΌ. ν”„λ‘œν† νƒ€μž…μ΄λ‚˜ ν•¨μˆ˜λ₯Ό 톡해 ν…ŒμŠ€νŠΈ λŒ€μƒμ΄ 가진 λ©”μ‹œμ§€λ₯Ό λ°–μœΌλ‘œ ν‘œμΆœν•˜λŠ” 것이닀.
  • μ—λŸ¬ 처리 μ½”λ“œλ₯Ό 제일 λ¨Όμ € ν…ŒμŠ€νŠΈν•˜λΌ. κ·Έλ‹€μŒ λ‹€λ₯Έ μ—…λ¬΄λ‘œ λ„˜μ–΄κ°€λ„ λŠ¦μ§€ μ•Šλ‹€.
  • μ½”λ“œκ°€ μ „ν˜€ 없어도 μ’‹μœΌλ‹ˆ ν…ŒμŠ€νŠΈλ₯Ό μ„±κ³΅μ‹œν‚¬ μ΅œμ†Œν•œμ˜ μ½”λ“œλ§Œ μž‘μ„±ν•˜λΌ. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œκ°€ ν…ŒμŠ€νŠΈλ³΄λ‹€ μ•žμ„œ λ‚˜κ°€λ©΄ μ•ˆ λœλ‹€.
  • λ¦¬ν„°λŸ΄ λŒ€μ‹  λ³€μˆ˜λͺ…을 잘 μ •ν•΄μ„œ DRYν•˜κ³  자기 μ„œμˆ μ μΈ ν…ŒμŠ€νŠΈλ₯Ό μž‘μ„±ν•˜λΌ.

🎈 μ˜μ‘΄μ„± μ£Όμž… ν”„λ ˆμž„μ›Œν¬ ν™œμš©β€‹

μ•žμ„œ μžλ°”μŠ€ν¬λ¦½νŠΈ 콘퍼런슀 μ°Έκ°€μžμ˜ μ’Œμ„ μ˜ˆμ•½ λͺ¨λ“ˆμ„ κ°œλ°œν•˜λ©΄μ„œ Attendee의 μ˜μ‘΄μ„±μ„ μžμ‹ μ˜ μƒμ„±μžμ— ν•˜λ“œ μ½”λ”©ν•˜μ—¬ μ£Όμž…ν–ˆμ—ˆλ‹€.

var attendee = new Attendee(new ConferenceWebSvc(), new Messenger(), id);

이제 μ ν•©ν•œ DI μ»¨ν…Œμ΄λ„ˆλ₯Ό λ§ˆλ ¨ν–ˆμœΌλ‹ˆ 객체λ₯Ό 생성할 λ•Œλ§ˆλ‹€ μ˜μ‘΄μ„±μ„ ν•˜λ“œ μ½”λ”©ν•΄μ„œ 넣지 μ•Šμ•„λ„ λœλ‹€.

μ „μ—­ 객체 MyApp λ‚΄λΆ€μ—μ„œ μž‘λ™ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ€ λ‹€μŒ μ˜ˆμ œμ™€ 같은 μ„€μ • μ½”λ“œλ₯Ό 생각할 수 μžˆλ‹€.

MyApp = {};

MyApp.diContainer = new DiContainer();

MyApp.diContainer.register(
'Service', // μ›Ή μ„œλΉ„μŠ€λ₯Ό κ°€λ¦¬ν‚€λŠ” DI νƒœν¬
[], // μ˜μ‘΄μ„± μ—†μŒ
function() { // μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
return new ConferenceWebSvc();
},
);

MyApp.diContainer.register(
'Messenger',
[],
function() {
return new Messenger();
},
);

MyApp.diContainer.register(
'AttendeeFactory',
['Service', 'Messenger'], // AttendeeλŠ” service 및 messenger에 μ˜μ‘΄ν•œλ‹€.
function(service, messenger) {
return function(attendeeId) {
return new Attendee(service, messenger, attendeeId);
}
},
)

Attendeeλ₯Ό μ–΄λ–»κ²Œ DiContainer μ•ˆμ— λ„£λŠ”μ§€ μ£Όλͺ©ν•˜λΌ. 맀우 μ€‘μš”ν•œ κ³ κΈ‰ 기법이닀. Attendeeλ₯Ό λ§Œλ“œλŠ” ν•¨μˆ˜κ°€ μ•„λ‹Œ, Attendeeλ₯Ό λ§Œλ“€ νŒ©ν† λ¦¬λ₯Ό λ§Œλ“œλŠ” ν•¨μˆ˜κ°€ 등둝을 λŒ€μ‹ ν•œλ‹€. AttendeeλŠ” μžμ‹ μ˜ μ˜μ‘΄μ„± 외에도 attendeeId νŒŒλΌλ―Έν„°κ°€ ν•„μš”ν•˜λ―€λ‘œ DI μ»¨ν…Œμ΄λ„ˆλŠ” μ΄λ ‡κ²Œ μ½”λ”©ν•œλ‹€.

var attendee = MyApp.diContainer.get('Attendee', attendeeId);

ν•˜μ§€λ§Œ 그러면 λ‹€λ₯Έ 객체의 μž¬κ·€μ  μ˜μ‘΄μ„±μœΌλ‘œ Attendeeλ₯Ό μ œκ³΅ν•  방법이 μ—†λ‹€.

λ‹€μŒ 예제 처럼 νŒ©ν† λ¦¬κ°€ 있으면 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κΉŠμˆ™ν•œ κ³³μ—μ„œλ„ DI μ»¨ν…Œμ΄λ„ˆλ‘œλΆ€ν„° Attendeeλ₯Ό κ°€μ Έμ˜¬ 수 μžˆλ‹€.

var attendeeId = 123;
var sessionId = 1;

// DI μ»¨ν…Œμ΄λ„ˆμ—μ„œ attendeeIdλ₯Ό λ„˜κ²¨ Attendeeλ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•œλ‹€.
var attendee = MyApp.diContainer.get('AttendeeFactory')(attendeeId);
attendee.reserve(sessionId);

🎈 μ΅œμ‹  μ˜μ‘΄μ„± μ£Όμž… ν”„λ ˆμž„μ›Œν¬β€‹

  • μ•΅κ·€λŸ¬ JS
  • 리콰이어 JS

πŸ“š μ• μŠ€νŒ©νŠΈ νˆ΄ν‚·β€‹

μ• μŠ€νŒ©νŠΈ 지ν–₯ ν”„λ‘œκ·Έλž˜λ°(AOP)은 (λ‹¨μΌν•œ μ±…μž„ λ²”μœ„ 내에 μžˆμ§€ μ•Šμ€) ν•˜λ‚˜ μ΄μƒμ˜ 객체에 μœ μš©ν•œ μ½”λ“œλ₯Ό ν•œλ° λ¬Άμ–΄ λˆˆμ— 띄지 μ•Šκ²Œ 객체에 λ°°ν¬ν•˜λŠ” 기법이닀.

AOP μš©μ–΄λ‘œ, 배포할 μ½”λ“œ 쑰각을 μ–΄λ“œλ°”μ΄μŠ€(advice), μ–΄λ“œλ°”μ΄μŠ€κ°€ μ²˜λ¦¬ν•  문제λ₯Ό μ• μŠ€νŒ©νŠΈ(aspect) λ˜λŠ” νš‘λ‹¨ 관심사(cross-cutting concern)라고 ν•œλ‹€.

🎈 사둀 연ꡬ: AOP μžˆλŠ”/μ—†λŠ” 캐싱​

  • 예제 μƒλž΅. (P.94, 95)

AOP둜 λ―ΏμŒμ§ν•œ μ½”λ“œ λ§Œλ“€κΈ°β€‹

AOP둜 μ–΄λ–»κ²Œ ν•˜λ©΄ λ―ΏμŒμ§ν•œ μ½”λ“œλ₯Ό λ§Œλ“€κΉŒ?

  1. AOPλŠ” ν•¨μˆ˜λ₯Ό λ‹¨μˆœν•˜κ²Œ μœ μ§€ν•œλ‹€. ν•¨μˆ˜ 각자의 단일 μ±…μž„μ„ μˆ˜ν–‰ν•  뿐이닀. λ‹¨μˆœν•¨μ€ 곧 λ―ΏμŒμ„±μ΄λ‹€.
  2. AOPλŠ” μ½”λ“œλ₯Ό DRYν•˜κ²Œ ν•΄μ€€λ‹€. μ–΄λ–€ μ½”λ“œκ°€ μ—¬κΈ°μ €κΈ° 좜λͺ°ν•˜λ©΄ λ‚˜μ€‘μ— λ‹€λ₯Έ κ°œλ°œμžκ°€ 잘λͺ» κ±΄λ“œλ¦΄ 여지도 많고, κ·ΈλŸ¬λ‹€ 보면 동기화가 꺠질 κ°€λŠ₯성이 λ‹Ήμ—°νžˆ 컀진닀. 그런데 μ—¬κΈ°μ„œ λ†“μΉ˜λ©΄ μ•ˆ 될 ν¬μΈνŠΈλŠ”, κΈ°μ‘΄ κΈ°λŠ₯에 μƒˆ κΈ°λŠ₯을 λΆ™μ΄λŠ” μ½”λ“œλ₯Ό λ°˜λ³΅ν•˜κ³  싢지 μ•Šλ‹€λŠ” 점이닀.

μ—¬λŸ¬ μ½”λ“œ 블둝을 자체둜 λ°˜λ³΅ν•˜μ§€ μ•ŠλŠ” 일만큼 λ‹€λ₯Έ μ½”λ“œμ™€ μ—°κ²°ν•˜λŠ” 뢀뢄을 λ°˜λ³΅ν•˜μ§€ μ•ŠλŠ” 일도 μ€‘μš”ν•˜λ‹€.

  1. AOPλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 섀정을 ν•œ 곳에 μ§‘μ€‘μ‹œν‚¨λ‹€. μ• μŠ€νŒ©νŠΈ 섀정이 단일 μ±…μž„μΈ ν•¨μˆ˜κ°€ ν•˜λ‚˜λ§Œ 있으면 뢀속 κΈ°λŠ₯ 전체λ₯Ό 찾을 λ•Œ 이 ν•¨μˆ˜λ§Œ 뒀지면 λœλ‹€. 무엇보닀 디버깅할 λ•Œ μ†μ‰½κ²Œ 캐싱 같은 κΈ°λŠ₯을 λ„κ±°λ‚˜ 인자 체크 κΈ°λŠ₯을 μΌ€ 수 μžˆμ–΄ μ’‹λ‹€.

🎈 사둀 연ꡬ: Aop.js λͺ¨λ“ˆ κ°œλ°œβ€‹

μ• μŠ€νŒ©νŠΈ ν”„λ‘œκ·Έλž˜λ°μ€ μƒˆλ‘œμš΄ λ°©λ²•μœΌλ‘œ ν•¨μˆ˜λ₯Ό λŒμ–΄λͺ¨μ€λ‹€.
μš°λ¦¬λŠ” ν”„λ ˆλ“œλ¦­ μ•„νŽ λ²„κ·Έμ™€ 데이브 ν΄λ ˆμ΄ν„΄μ΄ κ°œλ°œν•œ μ•„μ£Ό μš°μ•„ν•œ ν”„λ ˆμž„μ›Œν¬(Aop.jsμ—μ„œ 무료둜 내렀받을 수 μžˆλ‹€)λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

// Created by Fredrik Appelberg: http://fredrik.appelberg.me/2010/05/07/aop-js.html
// ν”„λ‘œν† νƒ€μž…μ„ 지원할 수 있게 데이브 ν΄λ ˆμ΄ν„΄μ΄ μˆ˜μ •ν•¨
Aop = {
// 주어진 이름곡간에 λ§€μΉ­λ˜λŠ” λͺ¨λ“  ν•¨μˆ˜ μ£Όλ³€(around)에 μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•œλ‹€.
around: function(pointcut, advice, namespaces) {
// 이름곡간이 μ—†μœΌλ©΄ μ „μ—­ 이름곡간을 μ°Ύμ•„λ‚΄λŠ” 꼼수λ₯Ό μ“΄λ‹€.
if (namespaces == undefined || namespaces.length == 0)
namespaces = [ (function(){return this;}).call() ];
// 이름곡간을 μ „λΆ€ μˆœνšŒν•œλ‹€.
for(var i in namespaces) {
var ns = namespaces[i];
for(var member in ns) {
if(typeof ns[member] == 'function' && member.match(pointcut)) {
(function(fn, fnName, ns) {
// member fn μŠ¬λ‘―μ„ 'advice' ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 래퍼둜 κ΅μ²΄ν•œλ‹€.
ns[fnName] = function() {
return advice.call(this, { fn: fn,
fnName: fnName,
arguments: arguments });
};
})(ns[member], member, ns);
}
}
}
},

next: function(f) {
return f.fn.apply(this, f.arguments);
}
};

Aop.before = function(pointcut, advice, namespaces) {
Aop.around(pointcut,
function(f) {
advice.apply(this, f.arguments);
return Aop.next.call(this, f);
},
namespaces);
};

Aop.after = function(pointcut, advice, namespaces) {
Aop.around(pointcut,
function(f) {
var ret = Aop.next.call(this, f);
advice.apply(this, f.arguments);
return ret;
},
namespaces);
};

module.exports = Aop;

ν…ŒμŠ€νŠΈ 주도 κ°œλ°œμ„ ν•˜λ©΄ 과거의 λ°©λ²•λ‘ μ²˜λŸΌ 믿음 있고 μš°μ•„ν•œ μ½”λ“œλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

AOP의 핡심은 ν•¨μˆ˜ μ‹€ν–‰(타깃)을 κ°€λ‘œμ±„μ–΄ λ‹€λ₯Έ ν•¨μˆ˜(μ–΄λ“œλ°”μ΄μŠ€)λ₯Ό μ‹€ν–‰ν•˜κΈ° μ§μ „μ΄λ‚˜ 직후, λ˜λŠ” 전후에 μ‹€ν–‰μ‹œν‚€λŠ” 것이닀.

  • TDD둜 AOPλ₯Ό κ΅¬ν˜„ν•˜λŠ” 예제 μƒλž΅ (P.97 ~ P.110)

πŸ“š μ½”λ“œ 검사 도ꡬ​

μ½”λ“œ 검사 λ„κ΅¬λŠ” μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ μ†ŒμŠ€ μ½”λ“œμ˜ ꡬ쑰/ꡬ문을 μ‘°μ‚¬ν•˜λŠ”, 정적 뢄석을 μˆ˜ν–‰ν•œλ‹€. μ½”λ“œ μ‹€ν–‰ μ‹œ μ—λŸ¬κ°€ λ‚  κ±° 같은 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ₯Ό λΆ€μ •ν™•ν•˜κ²Œ μ‚¬μš©ν•œ 곳을 μ°Ύμ•„ μ•Œλ €μ£ΌλŠ” 일이 주된 업무닀.

이런 도ꡬλ₯Ό 보톡 λ¦°ν„°(linter)라고 ν•œλ‹€.

🎈 λ¦°νŒ… λ„κ΅¬λ‘œ λ―ΏμŒμ§ν•œ μ½”λ“œ λ§Œλ“€κΈ°β€‹

λ¦°νŒ…μ€ 특히 μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ”© μ‹œ κΈ΄μš”ν•˜λ‹€. 인터프리터 언어인 μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” κ°œλ°œμžκ°€ μ‹€μˆ˜ν•΄λ„ 뭐라고 μ–˜κΈ°ν•΄μ£ΌλŠ” μ»΄νŒŒμΌλŸ¬κ°€ μ—†μ–΄μ„œ μ½”λ“œλ₯Ό 싀행해보기 μ „μ—λŠ” ꡬ문 μ—λŸ¬λ₯Ό μ•Œ 길이 μ—†λ‹€.

🎈 도ꡬ듀​

  • JSHint
  • ESLint

🎈 엄격 λͺ¨λ“œβ€‹

νŠΉμ • μŠ€μ½”ν”„(μ „μ—­ λ˜λŠ” ν•¨μˆ˜ μŠ€μ½”ν”„)에 λ‹€μŒ μ½”λ“œλ₯Ό λ„£μœΌλ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈ ν•΄μ„κΈ°λŠ” μ „ν˜€ λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ μ²˜λ¦¬ν•œλ‹€.

'use strict';

이 μ§€μ‹œμžκ°€ μžˆλŠ” μ½”λ“œμ—μ„œ κ°œλ°œμžκ°€ ν”νžˆ 저지λ₯΄λŠ” μ‹€μˆ˜λ₯Ό λ²”ν•˜λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈ μ—λŸ¬κ°€ λ‚œλ‹€.(예: λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κΈ°λ„ 전에 μ‚¬μš©, 읽기 μ „μš© ν”„λ‘œνΌν‹°λ₯Ό μˆ˜μ •, μ˜ˆμ•½μ–΄λ‘œ λ³€μˆ˜λ₯Ό λͺ…λͺ… λ“±).

엄격 λͺ¨λ“œλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•˜λ©΄ 'use strict' λ¬Έμžμ—΄μ€ λ¬΄μ‹œλœλ‹€.

πŸ“š μ •λ¦¬ν•˜κΈ°β€‹

λ‹¨μœ„ ν…ŒμŠ€νŒ… ν”„λ ˆμž„μ›Œν¬λŠ” μ˜¬λ°”λ₯Έ μ†Œν”„νŠΈμ›¨μ–΄ κ°œλ°œμ„ μ΄λ„λŠ” ν•„μˆ˜ν’ˆμ΄λ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 점점 λ³΅μž‘ν•΄μ§€λ©΄μ„œ μ»΄ν¬λ„ŒνŠΈλ₯Ό κ°œλ³„μ μœΌλ‘œ 잘 μ •λˆν•˜κ³  λΆ„λ¦¬ν•˜λŠ” 일이 λ”μš± μ€‘μš”ν•΄μ‘Œλ‹€. 그런 μ μ—μ„œ μ˜μ‘΄μ„± μ£Όμž…μ€ μ€‘μš”ν•œ ν…Œν¬λ‹‰μ΄λ‹€.

TDD 사둀λ₯Ό λ“€κΈ° μœ„ν•΄ μ• μŠ€νŒ©νŠΈ 지ν–₯ ν”„λ‘œκ·Έλž˜λ° νˆ΄ν‚·μ„ κ°œλ°œν–ˆλ‹€. AOPλ₯Ό μ“°λ©΄ 전체 μ»΄ν¬λ„ŒνŠΈλ₯Ό 바꾸지 μ•Šκ³ λ„ 캐싱 같은 곡톡 κΈ°λŠ₯을 μ†Œν”„νŠΈμ›¨μ–΄ μ»΄ν¬λ„ŒνŠΈμ— λΌμ›Œ 넣을 수 있고, μ½”λ“œλ₯Ό DRYν•˜κ²Œ μœ μ§€ν•˜λ©΄μ„œλ„ 단일 μ±…μž„ 원칙을 κ°–κ³  개방/폐쇄 원칙에 μΆ©μ‹€ν•œ μ½”λ“œλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

λ¦°ν„°λŠ” μ½”λ“œ 검사 λ„κ΅¬λ‘œ, ꡬ문 였λ₯˜λ‚˜ μ½”λ”© κ·œμΉ™μ„ μ–΄κΈ΄ μ½”λ“œλ₯Ό 미리 κ²½κ³ ν•¨μœΌλ‘œμ¨ λ―Έμ‹œ μˆ˜μ€€μ—μ„œ μ½”λ“œ λ―ΏμŒμ„±μ„ 높인닀. 엄격 λͺ―λŠ” ꡬ문 μˆ˜μ€€μ—μ„œ μ‹€μˆ˜λ₯Ό μ˜ˆλ°©ν•  λ°©λ²•μœΌλ‘œ ꢌμž₯ν•  λ§Œν•˜λ‹€.