Skip to content

πŸš€ ν…ŒμŠ€νŠΈμ½”λ“œμ— λŒ€ν•œ μ°Έκ³  자료

Hyein Jeong edited this page Nov 5, 2024 · 2 revisions

ν…ŒμŠ€νŠΈμ½”λ“œμ— λŒ€ν•œ μ°Έκ³  자료


ν…ŒμŠ€νŠΈ κ΄€λ ¨ ν•™μŠ΅μ— 도움될 μžλ£Œλ“€

λ‚˜μ€‘μ— λ”°λ‘œ 아카이빙 ν•˜κ² μŠ΅λ‹ˆλ‹€.

μ œλ‘œμ΄ˆλ‹˜μ˜ Jest ν…ŒμŠ€νŠΈ κ°•μ˜

ν…ŒμŠ€νŠΈ with Jest: μ œλ‘œμ΄ˆμ—κ²Œ μ œλŒ€λ‘œ 배우기 κ°•μ˜ | 제둜초(μ‘°ν˜„μ˜) - μΈν”„λŸ°

ν”„λ‘ νŠΈμ•€λ“œ ν…ŒμŠ€νŠΈ κ°•μ˜

2μ‹œκ°„μœΌλ‘œ λλ‚΄λŠ” ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ κΈ°λ³ΈκΈ° κ°•μ˜ | 강병진 - μΈν”„λŸ°

  • μƒκ°ν•΄λ³΄λ‹ˆ Cypress도 μžˆμ—ˆλ„€μš”. 당근은 μ΄κ±°μ“΄λ‹€λ˜λ°

싀무에 λ°”λ‘œ μ μš©ν•˜λŠ” ν”„λŸ°νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ

싀무에 λ°”λ‘œ μ μš©ν•˜λŠ” ν”„λŸ°νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ - 1λΆ€. ν…ŒμŠ€νŠΈ 기초: λ‹¨μœ„γƒ»ν†΅ν•© ν…ŒμŠ€νŠΈ κ°•μ˜ | μ½”λ“œ 쑰컀, μ˜€ν”„ - μΈν”„λŸ°

싀무에 λ°”λ‘œ μ μš©ν•˜λŠ” ν”„λŸ°νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ - 2λΆ€. ν…ŒμŠ€νŠΈ 심화: μ‹œκ°μ  νšŒκ·€γƒ»E2E ν…ŒμŠ€νŠΈ κ°•μ˜ | μ½”λ“œ 쑰컀, μ˜€ν”„ - μΈν”„λŸ°

κ·Όλ³ΈμžˆλŠ” ν”„λ‘ νŠΈμ•€λ“œ μœ λ‹›ν…ŒμŠ€νŠΈ

κ·Όλ³ΈμžˆλŠ” ν”„λ‘ νŠΈμ—”λ“œ μœ λ‹›ν…ŒμŠ€νŠΈ κ°•μ˜ | μ–΄μ©”μ½”λ”© - μΈν”„λŸ°

TDD μ±…

  • 개인적으둜 λ§Œμ•½ TDD ν”„λ‘œμ νŠΈλ‘œ κ°€λ©΄ 이 바이블 μ±… μ •λ„λŠ” 읽어봐야 ν•  것 κ°™μ•„μ„œ, 이걸둜 κ·Έλ£Ήν”„λ‘œμ νŠΈ λ‚΄λΆ€ μŠ€ν„°λ””ν•΄λ„ μž¬λ°Œμ„ 것 κ°™μŠ΅λ‹ˆλ‹€.

product.kyobobook.co.kr

μ½”λ“œμ™€ν•¨κ»˜ μ‚΄νŽ΄λ³΄λŠ” ν”„λ‘ νŠΈμ—”λ“œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ - λ°°λ‹¬μ˜λ―Όμ‘±

μ½”λ“œμ™€ ν•¨κ»˜ μ‚΄νŽ΄λ³΄λŠ” ν”„λ‘ νŠΈμ—”λ“œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ – Part 1. 이둠 편 | μš°μ•„ν•œν˜•μ œλ“€ κΈ°μˆ λΈ”λ‘œκ·Έ

μ½”λ“œμ™€ ν•¨κ»˜ μ‚΄νŽ΄λ³΄λŠ” ν”„λ‘ νŠΈμ—”λ“œ λ‹¨μœ„ ν…ŒμŠ€νŠΈ – Part 2. μ‹€μ „ 편 | μš°μ•„ν•œν˜•μ œλ“€ κΈ°μˆ λΈ”λ‘œκ·Έ

ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμžκ°€ μ•Œμ•„μ•Ό ν•  β€˜μœ λ‹› ν…ŒμŠ€νŠΈβ€™ μž‘μ„±λ²•

ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμžκ°€ μ•Œμ•„μ•Ό ν•  β€˜μœ λ‹› ν…ŒμŠ€νŠΈβ€™ μž‘μ„±λ²• | μš”μ¦˜IT

ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ μ˜λ―ΈμžˆλŠ” ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±ν•˜κΈ° - 미디움

ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ μ˜λ―ΈμžˆλŠ” ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±ν•˜κΈ°

ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ½”λ“œ λ„μž…κΈ°

ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ½”λ“œ λ„μž…κΈ°

λͺ¨λ˜ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅

λͺ¨λ˜ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅β€Šβ€”β€Š1편

λͺ¨λ˜ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅β€Šβ€”β€Š2편

ν”„λ‘ νŠΈμ•€λ“œ κ°œλ°œμ„ μœ„ν•œ ν…ŒμŠ€νŠΈ μž…λ¬Έ

ν”„λŸ°νŠΈμ—”λ“œ κ°œλ°œμ„ μœ„ν•œ ν…ŒμŠ€νŠΈ μž…λ¬Έ - 예슀24

μ‹€μš©μ μΈ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅ - NHN Cloud

μ‹€μš©μ μΈ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅ (1) : NHN Cloud Meetup

μ‹€μš©μ μΈ ν”„λ‘ νŠΈμ—”λ“œ ν…ŒμŠ€νŠΈ μ „λž΅ (2)

Toast UI의 ν…ŒμŠ€νŠΈμ½”λ“œ κ΄€λ ¨ λ‚΄μš© λͺ¨μŒ

Posts

ν”„λ‘ νŠΈμ•€λ“œμ—μ„œλ„ TDDκ°€ κ°€λŠ₯ν•œ 것을 λ³΄μ—¬μ€λ‹ˆλ‹€.

[A5] ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ TDDκ°€ κ°€λŠ₯ν•˜λ‹€λŠ” 것을 λ³΄μ—¬λ“œλ¦½λ‹ˆλ‹€.


πŸ“šΒ μ˜μƒ λ‚΄μš© 정리

πŸš€Β ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±ν•˜μ‹œλ‚˜μš”?

μž‘μ„±ν•˜λ €κ³  λ…Έλ ₯ν•˜λŠ” μ‚¬λžŒλ„ 있고, μ•„μ˜ˆ μ•ˆν•˜λŠ” μ‚¬λžŒλ„ μžˆλ‹€.

πŸš€Β μ™œ μ•ˆν•˜κ²Œ λ˜λŠ”κ°€?

λ„ˆλ¬΄ νž˜λ“€κ³ , 일정에 치이고 λ°”λΉ μ„œ λ‚˜μ€‘μ—.. λ‚˜μ€‘μ— ν•˜λ‹€λ³΄λ©΄..

λ‚˜μ€‘μ€ κ²°μ½” μ˜€μ§€ μ•Šμ•„μ„œ κ·Έλ ‡λ‹€.

πŸš€Β TDD (Test Driven Development)

μΌ„νŠΈλ²‘μ΄λΌλŠ” μ‚¬λžŒμ΄ ν…ŒμŠ€νŠΈ 주도 κ°œλ°œμ„ 잘 μ •λ¦¬ν–ˆλ‹€.

ꢁ극적 λͺ©ν‘œλŠ” Clean code라고 λ§ν•˜λŠ” κΉ”λ”ν•œ μ½”λ“œλ₯Ό λ§ν•œλ‹€.

Test First programming을 λ§ν•œλ‹€.

image

  • 보톡 이런 Red, Green, Refactor λΌλŠ” 싸이클을 λˆλ‹€.
  • ν…ŒμŠ€νŠΈλ₯Ό ν†΅κ³Όμ‹œν‚€κ³ , 쀑볡을 μ œκ±°ν•˜λ©΄μ„œ κ°œλ°œμ„ μ§„ν–‰ν•˜λŠ” 사이클인데.. μ΄κ²ƒλ§Œ 보면 μ‰½κ²Œ μ ‘κ·Όν•  수 μžˆμ„ 것 같은데.. λ§Žμ€ μ‚¬λžŒλ“€μ΄ TDD에 λ„μ „ν•˜κ³  많이 μ’Œμ ˆν•œλ‹€.
  • μ—°μ‚¬μžλΆ„λ„ μ§€κΈˆ μ’Œμ ˆν•œλ‹€.

πŸš€Β μ™œ μ–΄λ €μš΄κ°€?

  • μ½”λ“œ μžμ²΄κ°€ Testableν•˜μ§€ μ•Šμ•„μ„œ κ·Έλ ‡λ‹€.
  • Testableν•œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜μ§€ μ•Šμ•„μ„œ κ·Έλ ‡λ‹€.
  • μš°λ¦¬κ°€ μœ μ§€λ³΄μˆ˜ν•˜λŠ” μ„œλΉ„μŠ€λŠ” λ ˆκ±°μ‹œκ°€ μ»€μ„œ Testableν•˜κΈ° 쉽지 μ•Šλ‹€.

πŸš€Β μ–΄λ–»κ²Œ ν•˜λŠ”κ°€?

  • κ΄€μ‹¬μ‚¬μ˜ 뢄리(Separation of concerns)
  • μžμ‹ μ΄ 관심갖고 μžˆλŠ” λΆ€λΆ„μ—λ§Œ κ΄€μ‹¬κ°€μ Έμ„œ κ°œλ°œν•˜λŠ” 방식을 λ§ν•œλ‹€.

πŸš€Β TDD의 κ°€μž₯ μ€‘μš”ν•œ 것

  • μžλ™ν™”λœ ν…ŒμŠ€νŠΈμ˜ μ‹€ν–‰

πŸš€Β Todo App을 ν…ŒμŠ€νŠΈλ‘œ μž‘μ„±

  • 제일 λ¨Όμ € ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„± (App componentλ₯Ό λ°”νƒ€μ‘λ‘œ μžκ²ƒγ…‡)
import React from 'react';
import {render} from '@testing-library/react';
import App from './App';

describe('App', () => {
	it('redners tasks', () => {
		const {container} = render({
			<App />
		});
		
		expect(container).toHaveTextContent('아무 일도 ν•˜κΈ° μ‹«λ‹€.');
	});
});
  • 이런 ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•œλ‹€.

πŸš€Β TDD의 원칙

  • 이걸 λΉ λ₯΄κ²Œ ν†΅κ³Όμ‹œν‚€κΈ° μœ„ν•΄μ„œ μˆ˜λ‹¨ 방법을 κ°€λ¦¬μ§€λ§ˆλΌ. 이게 원칙이닀.
import React from 'react';

export default function App() {
	return (
		<div>
			<h1>To-do</h1>
			<ul>
				<li>
					아무일도 ν•˜κΈ° μ‹«λ‹€.
				</li>
			</ul>
		</div>
	);
}
  • 이게 μš°λ¦¬κ°€ μ›ν•˜λŠ” λͺ¨μŠ΅μ€ μ•„λ‹ˆλ‹€.

πŸš€Β κ΄€μ‹¬μ‚¬μ˜ 뢄리

  • κ΄€μ‹¬μ‚¬μ˜ 뢄리λ₯Ό μœ„ν•΄μ„œ μš°λ¦¬κ°€ μ›ν•˜λŠ” ν˜•νƒœλ‘œ λΆ„λ¦¬ν•œλ‹€.

List.test.jsxλ₯Ό λ§Œλ“ λ‹€.

import {render} from '@testing-library/react';
import List from './App';

describe('List', () => {
	it('redners tasks', () => {
		const {container} = render({
			<List />
		});
		
		expect(container).toHaveTextContent('아무 일도 ν•˜κΈ° μ‹«λ‹€.');
	});
});

List.jsxλ₯Ό λ§Œλ“ λ‹€.

import React from 'react';

export default function App() {
	return (
			<ul>
				<li>
					아무일도 ν•˜κΈ° μ‹«λ‹€.
				</li>
			</ul>
	);
}

이후 싀행을 ν•˜λ©΄ ν…ŒμŠ€νŠΈκ°€ 톡과가 λœλ‹€.

그런데, 이 뢀뢄이 ν…ŒμŠ€νŠΈκ°€ μ•„λ‹ˆλ‹€. μš°λ¦¬λŠ” 배열을 λ°›μ•„μ„œ κ·Έ 배열에 μžˆλŠ” Todo 제λͺ©λ“€μ„ 보여주렀고 ν•˜λŠ” 것이닀.

import {render} from '@testing-library/react';
import List from './App';

describe('List', () => {
	it('redners tasks', () => {
		const tasks = [{id:1, title: '아무 일도 ν•˜κΈ° μ‹«λ‹€.'}]
		const {container} = render({
			<List tasks={tasks}/>
		});
		
		expect(container).toHaveTextContent('아무 일도 ν•˜κΈ° μ‹«λ‹€.');
	});
});
import React from 'react';

export default function App({tasks}) {
	return (
			<ul>
			{tasks.map((task)=>{
				<li key={task.id}>
					{task.title}
				</li>
			})}
			</ul>
	);
}

μ΄λ ‡κ²Œ λ°”κΏ”μ£Όλ©΄ λ™μž‘μ„ ν•œλ‹€.

μ—¬κΈ°κΉŒμ§€λ„ 살짝 λΆˆμ•ˆν•˜λ‹€. ν…ŒμŠ€νŠΈκ°€ μ œλŒ€λ‘œ λ™μž‘ν•˜λŠ” 지 μ•Œ 수 μ—†λ‹€.

import {render} from '@testing-library/react';
import List from './App';

describe('List', () => {
	it('redners tasks', () => {
		const tasks = [{id:1, title: '아무 일도 ν•˜κΈ° μ‹«λ‹€.'}, {id:2, title: '건물 λ§€μž…'}]
		const {container} = render({
			<List tasks={tasks}/>
		});
		
		expect(container).toHaveTextContent('아무 일도 ν•˜κΈ° μ‹«λ‹€.');
		expect(container).toHaveTextContent('건물 λ§€μž…');
	});
});

μ΄λ ‡κ²Œ ν•˜λ©΄ ν…ŒμŠ€νŠΈλ₯Ό ν†΅κ³Όν•œλ‹€. ListλŠ” ν…ŒμŠ€νŠΈλ₯Ό 잘 ν†΅κ³Όν•˜κ³  μžˆλ‹€.

λ‹€μ‹œ App을 μˆ˜μ •ν•΄λ³΄μž.

import React from 'react';

import List from './List';

export default function App() {
	return (
		<div>
			<h1>To-do</h1>
			<List />
			</ul>
		</div>
	);
}

κ·Έλ ‡κ²Œ ν•˜λ©΄ ν…ŒμŠ€νŠΈκ°€ 깨진닀.

각 ν…ŒμŠ€νŠΈλŠ” 독립적인데, App λ‚΄μ˜ ListλŠ” μƒνƒœλ₯Ό 바꾸지 μ•Šκ³  있기 λ•Œλ¬Έμ΄λ‹€. κ·Έλž˜μ„œ μž„μ˜λ‘œ 바꾸지 μ•ˆν₯λ©΄ ν…ŒμŠ€νŠΈκ°€ κΉ¨μ§€κ²Œ λ˜μ–΄μžˆλ‹€.

import React from 'react';

import List from './List';

export default function App() {
		const tasks = [{id:1, title: '아무 일도 ν•˜κΈ° μ‹«λ‹€.'}, {id:2, title: '건물 λ§€μž…'}]
		
	return (
		<div>
			<h1>To-do</h1>
			<List tasks={tasks}/>
			</ul>
		</div>
	);
}

μž„μ˜λ‘œ μƒνƒœλ₯Ό λ§Œλ“€μ–΄μ„œ λ„£μ–΄μ£Όλ©΄, ν…ŒμŠ€ν¬λŠ” ν†΅κ³Όλœλ‹€.

πŸš€Β νŒ€μ˜ λ¬Έν™”

ν…ŒμŠ€νŠΈμ™€, μžλ™ν™”λœ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό 보고 λΈŒλΌμš°μ €λ₯Ό λ³Ό ν•„μš”λŠ” 거의 μ—†λ‹€.

거의 ν™•μ‹€ν•œ ν”Όλ“œλ°± 루프가 있고, 거의 ν™•μ‹€ν•œ ν”Όλ“œλ°± λͺ¨λ“œκ°€ 있기 λ•Œλ¬Έμ΄λ‹€.

πŸš€Β Redux

  • μ™œ μ“°λŠ”κ°€?

  • μƒνƒœκ΄€λ¦¬ μΈ‘λ©΄μ—μ„œ μ“΄λ‹€.

  • μ’€ 더 깊게 λ“€μ–΄κ°€μ„œ 보자.

  • React의 관심사 λ•Œλ¬Έμ— μ“΄λ‹€.

  • React의 κ΄€μ‹¬μ‚¬λŠ” state reflection 즉, μƒνƒœ λ°˜μ˜μ΄λ‹€.

  • μƒνƒœκ°€ μ „λ‹¬λ˜λ©΄ μƒνƒœλ₯Ό λ°˜μ˜ν•˜λŠ” 것을 μ‹ κ²½μ“΄λ‹€.

  • κ·Έλž˜μ„œ λ¦¬μ•‘νŠΈλŠ” μƒνƒœ 관리에 λŒ€ν•΄μ„œλŠ” 관심이 μ—†λ‹€. λ°˜μ˜μ—λ§Œ 관심이 μžˆμ„ 뿐이지.

  • 둜그인 κΈ°λŠ₯ 등이 μΆ”κ°€λ˜κ³  앱이 λΉ„λŒ€ν•΄μ§€λ©΄, 관심사 뢄리가 μ–΄λ ΅κ³  ν…ŒμŠ€νŠΈν•˜κΈ° μ–΄λ €μš΄κ±Έ 자주 확인할 수 μžˆλ‹€.

image

Container component만 redux의 쑴재λ₯Ό μ•Œκ³  μ–˜λ§Œ μƒνƒœλ₯Ό κ°€μ Έμ˜¨λ‹€.

κ·Έ μƒνƒœλ₯Ό κ°€μ Έμ™€μ„œ presentation component에 μ „λ‹¬ν•œλ‹€.

πŸš€Β ν•­μƒ μ»΄ν¬λ„ŒνŠΈ μž…μž₯μ—μ„œ 이런 질문이 λ‚˜μ˜¨λ‹€.

응~ κ·Έκ±° λ‚΄ 관심사 μ•„λ‹ˆμ•Ό.

κ·Έλž˜μ„œ μš”μ†Œμ™€ μ»΄ν¬λ„ŒνŠΈλ₯Ό μž‘κ²Œ μž‘κ²Œ λ§Œλ“€ 수 μžˆλ„λ‘ 주의λ₯Ό κΈ°μšΈμ—¬μ•Ό ν•œλ‹€.

πŸš€Β SRP :: Single Responsibility Principle

μ˜μ‘΄μ„±μ΄ 생기지 μ•Šκ³  또 λ‹€μ‹œ ν…ŒμŠ€νŠΈλ₯Ό μ‰½κ²Œ μž‘μ„±ν•  수 있고, κ·Έλž˜μ•Ό TDDλ₯Ό ν•  수 μžˆλ‹€.

Clone this wiki locally