πŸ›Ό μš°μ•„ν•œ ν…Œν¬μΊ ν”„ 3μ£Όμ°¨ 회고(0718~0722)

Lee JooamΒ·2022λ…„ 7μ›” 31일
1

🎯 3, 4μ£Όμ°¨ λ―Έμ…˜

1. SPA 가계뢀 ν”„λ‘ νŠΈμ—”λ“œ κ΅¬ν˜„(바닐라 JS, μ˜΅μ €λ²„ νŒ¨ν„΄ 이용)

2. 가계뢀 λ°±μ—”λ“œ κ΅¬ν˜„(ExpressJS, MySQL 이용)

3. AWS 이용 배포(슀크립트 이용 지속 배포)


처음으둜 2주짜리 λ―Έμ…˜μ„ μ‹œμž‘ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이번 λ―Έμ…˜μ€ 가계뢀 μ„œλΉ„μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. νŒ€ λ‹¨μœ„λ‘œ λ―Έμ…˜μ„ μˆ˜ν–‰ν•˜λŠ”λ° 1주차에 같은 그룹으둜 λ°°μ •λœ 뢄이라 μ„œλ‘œ λ―Έμ…˜μ„ μˆ˜ν–‰ν•˜λŠ”λ°μ— 큰 νŠΈλŸ¬λΈ”μ€ μ—†μ—ˆμŠ΅λ‹ˆλ‹€. πŸ˜ƒ

🍎 λ―Έμ…˜ 진행 쀑 κ³ λ €ν•œ 사항

πŸŽ€ ν”„λ‘ νŠΈμ—”λ“œ

πŸ‘ μ˜΅μ €λ²„ νŒ¨ν„΄

μƒνƒœκ΄€λ¦¬λ₯Ό μœ„ν•΄ μ˜΅μ €λ²„ νŒ¨ν„΄μ„ μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€. μ˜΅μ €λ²„ νŒ¨ν„΄μ€ μƒνƒœ 객체λ₯Ό λ°œν–‰ν•˜λŠ” 기관이 있고 각 μ»΄ν¬λ„ŒνŠΈ λ˜λŠ” κ°μ²΄μ—μ„œ 그것을 κ΅¬λ…ν•˜λŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€. κ΅¬λ…ν•œ κ°μ²΄μ—μ„œ λ³€ν™”κ°€ κ°μ§€λ˜λ©΄ κ΅¬λ…ν•œ μš”μ†Œλ“€μ€ μž„μ˜μ˜ λ‘œμ§μ„ μ‹€ν–‰ν•©λ‹ˆλ‹€.

κ°„λ‹¨ν•˜κ²Œ λ§ν•˜μžλ©΄ λ¦¬μ•‘νŠΈμ—μ„œ λ¦¬λ•μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 것과 κ°™μŠ΅λ‹ˆλ‹€. λ¦¬λ•μŠ€μ—μ„œλŠ” μƒνƒœλ₯Ό κ΅¬λ…ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈκ°€ ν•΄λ‹Ή μƒνƒœκ°€ λ³€ν™”ν•˜λ©΄ λ¦¬λ Œλ”λ§λ©λ‹ˆλ‹€. 이번 λ―Έμ…˜μ—μ„œλ„ λ¦¬λ•μŠ€μ˜ ν˜•νƒœλ₯Ό λ³Έλ”° μ€‘μ•™μ§‘μ€‘ν˜• μƒνƒœκ΄€λ¦¬ μ €μž₯μ†Œλ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

import reducer from './reducer';

function isSameState(state, newState) {
	return JSON.stringify(state) === JSON.stringify(newState);
}

function createStore(reducer) {
	let listeners = [];
	let state = reducer(undefined, { type: null });

	function subscribe(key, callback) {
		const listener = { key, callback };
		listeners.push(listener);

		function unsubscribe() {
			listeners = listeners.filter((l) => l !== listener);
		}

		return unsubscribe;
	}

	function getState(key) {
		return state[key];
	}

	function getChangedKeys(newState) {
		return Object.keys(newState).reduce(
			(changedKeys, key) =>
				state[key] !== newState[key] ? [...changedKeys, key] : changedKeys,
			[]
		);
	}

	function invokeListeners(key) {
		listeners.forEach((listener) => {
			if (listener.key === key) {
				listener.callback();
			}
		});
	}

	function notify(changedKeys) {
		changedKeys.forEach((key) => {
			invokeListeners(key);
		});
	}

	function dispatch(action) {
		const newState = reducer(state, action);
		if (isSameState(state, newState)) {
			return;
		}

		const changedKeys = getChangedKeys(newState);
		state = newState;
		notify(changedKeys);
	}

	function resetListeners() {
		listeners = [];
	}

	return { subscribe, getState, dispatch, resetListeners };
}

export default createStore(reducer);

λ―Έμ…˜μ—μ„œ μ‚¬μš©ν•œ storeμž…λ‹ˆλ‹€. subscribeλ₯Ό μ΄μš©ν•΄ κ΅¬λ…ν•˜κ³  dispatch에 μ•‘μ…˜ 객체λ₯Ό μ „λ‹¬ν•©λ‹ˆλ‹€. 그리고 μ§€μ •ν•œ reducerμ—μ„œ μ•‘μ…˜μ— λ§žλŠ” λ™μž‘μ„ μˆ˜ν–‰ν•˜κ³  stateλ₯Ό λ³€κ²½μ‹œν‚΅λ‹ˆλ‹€. 변경이 κ°μ§€λ˜λ©΄ 바뀐 key 값듀을 μ‹λ³„ν•˜κ³  그에 따라 λ“±λ‘λœ listenerλ₯Ό μ‹€ν–‰μ‹œν‚΅λ‹ˆλ‹€. listenerλŠ” state의 key와 λ§€ν•‘λ˜λŠ” callback인데 보톡 μ»΄ν¬λ„ŒνŠΈμ˜ render ν•¨μˆ˜κ°€ λ“±λ‘λ©λ‹ˆλ‹€.

ν•΄λ‹Ή 과정을 톡해 ꡬ독 쀑인 μƒνƒœκ°€ λ³€κ²½λ˜λ©΄ μ»΄ν¬λ„ŒνŠΈμ˜ λ¦¬λ Œλ”λ§μ„ λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

SPA λΌμš°ν„°

const routes = {
  '/': renderHome,
  '/calendar': renderCalendar,
  '/analytics': renderAnalytics,
};

function render(path) {
  const renderPage = routes[path];
  if (!renderPage) {
    render404();
    return;
  }

  renderPage();
}

λΌμš°ν„°μ˜ λŒ€λž΅μ μΈ κ΅¬μ‘°μž…λ‹ˆλ‹€. routes κ°μ²΄μ—λŠ” urlκ³Ό νŽ˜μ΄μ§€ λ Œλ”λ§ ν•¨μˆ˜λ₯Ό λ§€ν•‘μ‹œμΌœ ν˜„μž¬ pathκ°€ routes에 μžˆλ‹€λ©΄ ν•΄λ‹Ή νŽ˜μ΄μ§€λ₯Ό λ Œλ”λ§ν•˜κ³ , μ—†λ‹€λ©΄ 404 νŽ˜μ΄μ§€λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

ν˜„μž¬λŠ” '/'에 ν•΄λ‹Ήν•˜λŠ” urlμ—μ„œλ§Œ index.html을 μ „μ†‘ν•˜κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ νŽ˜μ΄μ§€μ—μ„œ μƒˆλ‘œκ³ μΉ¨μ„ ν•˜κ±°λ‚˜ url둜 직접 접근을 ν•  경우 앱을 뢈러올 수 μ—†μŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— ν”„λ‘ νŠΈμ—”λ“œ index.html을 λͺ¨λ“  μ£Όμ†Œμ— λŒ€μ‘μ‹œμΌœμ£ΌκΈ° μœ„ν•΄ express μ„œλ²„λ₯Ό μΆ”κ°€λ‘œ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

// app.js
const express = require('express');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 5500;

app.use('/static', express.static(path.resolve('./dist')));
app.get('*', (_req, res) => {
	res.sendFile(path.resolve('./dist/index.html'));
});

app.listen(PORT, () => {
	console.log('app is listening on PORT', PORT);
});

λͺ¨λ“  μ£Όμ†Œμ— index.html을 λŒ€μ‘μ‹œν‚€λŠ” μ„œλ²„λ‘œ λ‹¨μˆœνžˆ html을 μ „μ†‘ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©λ©λ‹ˆλ‹€.

✨ κ°œμ„ μ 

ν•΄λ‹Ή ꡬ쑰λ₯Ό λ§Œλ“€ λ•Œ κ°„κ³Όν•œ 뢀뢄이 μžˆμŠ΅λ‹ˆλ‹€. λ°”λ‘œ μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ—μ„œ μžμ‹ μ»΄ν¬λ„ŒνŠΈλ§Œ λ¦¬λ Œλ”λ§ μ‹œν‚¬ κ²½μš°μž…λ‹ˆλ‹€. μ»΄ν¬λ„ŒνŠΈ μ•ˆμ— μ»΄ν¬λ„ŒνŠΈκ°€ 있고, μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ μƒνƒœλ₯Ό ꡬ독 쀑이라면 ν•΄λ‹Ή μžμ‹μ„ μƒˆλ‘œμš΄ μžμ‹μœΌλ‘œ ꡐ체할 λ•Œ 기쑴에 있던 ꡬ독을 ν•΄μ œν•΄μ•Όν•©λ‹ˆλ‹€.

λ―Έμ…˜ 진행 μ΄ˆλ°˜μ—λŠ” 이런 뢀뢄을 μƒκ°ν•˜μ§€ λͺ»ν•΄μ„œ, 진행 도쀑 ꡬ쑰λ₯Ό λ°”κΏ”μ•Όν–ˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬ΈμΈμ§€ μ€‘ν›„λ°˜λΆ€μ— 진행 상황이 λ”λŽŒμ§€λŠ” ν˜„μƒμ΄ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μ΄ˆκΈ°μ— μΆ©λΆ„νžˆ λ§Žμ€ λ…Όμ˜λ₯Ό ν–ˆμ—ˆλ‹€λ©΄ 이런 상황을 방지할 수 μžˆμ—ˆμ„ 텐데 쑰금 μ•„μ‰½μŠ΅λ‹ˆλ‹€.

κ²°κ³Όμ μœΌλ‘œλŠ” λ‹€μŒκ³Ό 같은 core Componentλ₯Ό λ§Œλ“€κ³  ν•΄λ‹Ή Componentλ₯Ό μƒμ†λ°›λŠ” ꡬ쑰둜 μ»΄ν¬λ„ŒνŠΈλ₯Ό λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.

import store from '../store/store';

class Component {
	constructor() {
		this.childComponents = [];
		this.unsubscribe = [];
		this.keys = new Set();
	}

	subscribe(key, callback) {
		this.keys.add(key);
		this.unsubscribe.push(store.subscribe(key, callback));
	}

	getState(key) {
		if (!this.keys.has(key)) {
			throw new Error(`Doesn't have a key`);
		}

		return store.getState(key);
	}

	setChild(children) {
		this.childComponents.push(children);
	}

	clearChildren() {
		this.childComponents.forEach(clear);
		this.childComponents = [];
	}

	clearChild(childComponent) {
		clear(childComponent);
		this.childComponents = this.childComponents.filter(
			(component) => component !== childComponent
		);
	}

	clearSelf() {
		this.DOMElement.remove();
		this.unsubscribe.forEach((u) => u());
		this.clearChildren();
	}
}

function clear(childComponent) {
	childComponent.unsubscribe.forEach((u) => u());
	childComponent.clearChildren();
	childComponent.DOMElement.remove();
}

export default Component;

이 μ½”μ–΄ μ»΄ν¬λ„ŒνŠΈμ˜ ꡬ쑰도 이미 μ½”λ“œκ°€ μ–΄λŠ 정도 μž‘μ„±λœ μƒν™©μ—μ„œ λ§Œλ“€μ–΄μ‘ŒκΈ° λ•Œλ¬Έμ— κ΅¬ν˜„μ— μ’…μ†λ˜μ–΄λ²„λ¦° λŠλ‚Œμ΄ μžˆμŠ΅λ‹ˆλ‹€. μ’€ 더 μœ μ—°ν•œ 섀계λ₯Ό ν•˜μ§€ λͺ»ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€.

πŸŽ‰ λ°±μ—”λ“œ

πŸ”‘ DAO νŒ¨ν„΄

λ°±μ—”λ“œλ₯Ό κ΅¬ν˜„ν•  λ•Œ DAO νŒ¨ν„΄μ„ μ΄μš©ν–ˆμŠ΅λ‹ˆλ‹€. DAO(Data Access Object)λŠ” DB에 μ ‘κ·Όν•˜λŠ” 객체둜 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ—μ„œ ν•΄λ‹Ή 객체가 μ œκ³΅ν•˜λŠ” λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•΄ DB에 μ ‘κ·Όν•˜λŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€. DAO νŒ¨ν„΄μ˜ μž₯μ μœΌλ‘œλŠ” κ΄€μ‹¬μ‚¬μ˜ 뢄리와 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•œ ν”„λ‘œκ·Έλž˜λ°μ„ ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

각각의 관심사에 따라 λ‘œμ§μ„ λΆ„λ¦¬μ‹œμΌ°κΈ° λ•Œλ¬Έμ— μœ μ§€λ³΄μˆ˜μ— μš©μ΄ν•˜κ³ , μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•œ κ΅¬ν˜„μ΄ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— 가독성 μΈ‘λ©΄μ—μ„œλ„ λ›°μ–΄λ‚©λ‹ˆλ‹€.

import {
  addQuotesToString,
  timeConverter,
} from '../../utils/data_transformer.js';
import pool from '../loader.js';

const promisePool = pool.promise();

async function insertHistory(history) {
  try {
    const [rows] = await promisePool.execute(
      `INSERT INTO HISTORY (${Object.keys(history).join()})
      VALUES (${Object.values(history).map(addQuotesToString).join()})`
    );

    return rows;
  } catch (e) {
    console.error(e);
  }
}

.
.
.

async function deletePaymentMethodInHistory(value) {
  try {
    const [rows] = await promisePool.execute(
      `
      UPDATE HISTORY
      SET paymentMethod = ""
      WHERE paymentMethod = "${value}"
      `
    );

    return rows;
  } catch (e) {
    console.error(e);
  }
}

export default {
  insertHistory,
  readHistoryByYearMonth,
  deleteHistoryById,
  updateHistoryById,
  getRecentHistory,
  deletePaymentMethodInHistory,
};

ν•΄λ‹Ή ν˜•νƒœμ²˜λŸΌ API μ„œλ²„μ— DAO 객체λ₯Ό λ§Œλ“œλ‘ 그것을 exportν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. APIλ₯Ό λ‹΄λ‹Ήν•˜λŠ” λ‘œμ§μ€ DAOκ°€ μ œκ³΅ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν†΅ν•΄μ„œ DB에 μ ‘κ·Όν•©λ‹ˆλ‹€.

Connection Pool

connection pool은 κ΅¬ν˜„μ„ ν•œ 것은 μ•„λ‹ˆκ³ , node js mysql νŒ¨ν‚€μ§€μ—μ„œ μ œκ³΅ν•˜λŠ” κΈ°λŠ₯ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. μ‚¬μš©μž μΈ‘μ—μ„œ μš”μ²­μ„ 보내 API μ„œλ²„μ™€ DB μ‚¬μ΄μ—μ„œ 톡신을 ν•˜λ €λ©΄ 연결을 μˆ˜λ¦½ν•΄μ•Όν•©λ‹ˆλ‹€.

연결을 μ—°κ²°ν•˜λŠ” 것뢀터 그것을 μœ μ§€ν•˜λŠ” κ²ƒκΉŒμ§€ λͺ¨λ‘ λΉ„μš©μž…λ‹ˆλ‹€. λ§Œμ•½ λ‹€μˆ˜μ˜ μ‚¬μš©μžλΌλ©΄ κ·Έ λΉ„μš©μ€ μ—„μ²­λ‚œ λΆ€λ‹΄μœΌλ‘œ λ‹€κ°€μ˜΅λ‹ˆλ‹€.connection pool을 μ΄μš©ν•˜λ©΄ 그런 뢀담을 상당 λΆ€λΆ„ λœμ–΄λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

pool은 connection듀을 λͺ¨μ•„놓은 κ²ƒμž…λ‹ˆλ‹€. pool에 λ“±λ‘λœ connection을 μ‚¬μš©μžλ“€μ΄ ν•„μš”ν•  λ•Œλ§ˆλ‹€ κ°€μ Έλ‹€ μ“°κ³ , μ‚¬μš© ν›„ 그것을 λ‹€μ‹œ λ°˜ν™˜ν•©λ‹ˆλ‹€. κ·Έλ ‡κ²Œ λœλ‹€λ©΄ λ‹€μ‹œ 연결을 수립, ν•΄μ œν•  ν•„μš”κ°€ 없어지기 λ•Œλ¬Έμ— νš¨μœ¨μ„± μΈ‘λ©΄μ—μ„œ 도움이 λ©λ‹ˆλ‹€.

λ¬Όλ‘  미리 connection듀을 λ§Œλ“€μ–΄λ†”μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 그것을 μœ„ν•œ 초기 λΉ„μš©κ³Ό, pool을 κ΄€λ¦¬ν•˜λŠ” 좔가적인 λΉ„μš©μ΄ μƒκΉλ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ‹€μ œ μƒν™©μ—μ„œλŠ” μ„œλΉ„μŠ€μ˜ 규λͺ¨μ— 따라 pool의 크기와 κ·Έκ²ƒμ˜ ν•„μš”μ„±μ— λŒ€ν•΄ μΆ©λΆ„νžˆ λ…Όμ˜ν•΄μ•Ό ν•  것 κ°™μŠ΅λ‹ˆλ‹€.

✨ κ°œμ„ μ 

import pool from '../loader.js';

const promisePool = pool.promise();

async function getPaymentMethodById(id) {
  try {
    const [rows] = await promisePool.execute(`SELECT name FROM PAYMENT_METHOD
    WHERE id = ${id}`);

    return rows;
  } catch (e) {
    console.error(e);
  }
}

async function readPaymentMethod() {
  try {
    const [rows] = await promisePool.execute(`SELECT * FROM PAYMENT_METHOD`);

    return rows;
  } catch (e) {
    console.error(e);
  }
}

async function insertPaymentMethod(value) {
  try {
    const [rows] = await promisePool.execute(
      `INSERT INTO PAYMENT_METHOD (name)
      VALUES ("${value}")`
    );

    return rows;
  } catch (e) {
    console.error(e);
  }
}

async function deletePaymentMethodById(id) {
  try {
    const [rows] = await promisePool.execute(`
      DELETE FROM PAYMENT_METHOD
      WHERE id = ${id}
    `);

    return rows;
  } catch (e) {
    console.error(e);
  }
}

export default {
  readPaymentMethod,
  insertPaymentMethod,
  deletePaymentMethodById,
  getPaymentMethodById,
};

이번 λ―Έμ…˜μ—μ„œ μ‚¬μš©ν•œ DAO의 μΌλΆ€λΆ„μž…λ‹ˆλ‹€. 아직 SQL 문에 μ΅μˆ™ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬ΈμΌ μˆ˜λ„ μžˆκ² μ§€λ§Œ, μ€‘λ³΅μ μœΌλ‘œ νŠΉμ • SQL 문의 호좜이 λ°˜λ³΅λœλ‹€λŠ” λŠλ‚Œμ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€. μ—¬λŸ¬ 번 λ°˜λ³΅λ˜λŠ” 뢀뢄을 κ³΅ν†΅λœ 둜직으둜 λ§Œλ“€ 수 μžˆκ² λ‹€λŠ” 생각이 λ“­λ‹ˆλ‹€.

캠퍼 쀑 ν•œ 뢄은 ORM은 직접 λ§Œλ“œμ…¨λŠ”λ° 정말 λŒ€λ‹¨ν•˜λ‹€λŠ” 생각이 λ“­λ‹ˆλ‹€... πŸ™ƒ

πŸ’ˆ κ³ λ―Όκ³Ό 생각

μ΄λ²ˆμ€ 2μ£Ό 짜리 λ―Έμ…˜μ΄λΌ 크둱과 ν˜Έλˆ…μŠ€μ˜ 리뷰가 μ½”λ“œμ μΈ μΈ‘λ©΄μ—μ„œλŠ” 많이 μ—†μ—ˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜λ„ ν˜‘μ—…μ—μ„œ 이슈 κ΄€λ¦¬λ²•μ΄λ‚˜, λ²”μš©μ μΈ ν”„λ‘œκ·Έλž˜λ°μ— λŒ€ν•΄ λ§Žμ€ 것듀을 μ•Œ 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

1. 이슈 관리

μ΄μŠˆλŠ” κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” κΈ°λŠ₯κ³Ό κ·Έκ²ƒμ˜ μ™„λ£Œ 쑰건을 κΈ°λ‘ν•΄λ‘λŠ” 게 μ’‹μŠ΅λ‹ˆλ‹€. 사전에 버그λ₯Ό μΆ©λΆ„νžˆ λ°©μ§€ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— λ§Žμ€ λ…Όμ˜λ₯Ό κ±°μ³μ„œ 이슈λ₯Ό μ‹ μ€‘νžˆ μž‘μ„±ν•˜λŠ” 게 μ˜³μ€ 것 κ°™μŠ΅λ‹ˆλ‹€. 크둱은 보톡 μ‚¬μš©μžμ˜ μ‹œλ‚˜λ¦¬μ˜€λ₯Ό μƒκ°ν•˜λ©΄μ„œ 미리 μ„œλΉ„μŠ€μ˜ ν”Œλ‘œμš°λ₯Ό μ­‰ 적어내리면 μ΄μŠˆκ°€ μ €μ ˆλ‘œ 생긴닀고 ν•©λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” κ·Έμ •λ„λ‘œ κΉŠκ²ŒλŠ” 해보지 λͺ»ν–ˆμ§€λ§Œ λ‹€μŒ λ―Έμ…˜μ—μ„œλŠ” μ‹œλ„ν•΄λ΄μ•Όκ² μŠ΅λ‹ˆλ‹€ γ…Žγ…Ž

2. μ½”λ“œμ˜ μ˜λ„

회고λ₯Ό μž‘μ„±ν•  λ•Œλ§ˆλ‹€ 항상 λ‚˜μ˜€λŠ” 말인 것 κ°™μŠ΅λ‹ˆλ‹€. μ½”λ“œλŠ” μžμ‹ μ˜ λ™μž‘μ„ μΆ©λΆ„νžˆ ν‘œν˜„ν•˜κ³  μžˆμ–΄μ•Ό ν•œλ‹€. μ μ ˆν•œ λ³€μˆ˜λͺ…κ³Ό ν•¨μˆ˜λͺ…, 그리고 κΈ°λŠ₯의 뢄리λ₯Ό μ΄μš©ν•΄ μ΅œλŒ€ν•œ κ°„κ²°ν•˜κ³  λͺ…ν™•ν•˜κ²Œ μž‘μ„±ν•΄μ•Όν•©λ‹ˆλ‹€. ν‰μ†Œ 쒋은 μ½”λ“œλŠ” λ‹€λ₯Έ μ‚¬λžŒμ΄ 읽기 νŽΈν•œ μ½”λ“œλΌκ³  μƒκ°ν–ˆλŠ”λ°, 아직도 그런 뢀뢄은 λ―Έμˆ™ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€. 쑰금 μ‹œκ°„μ΄ 걸리더라도 항상 ν’λΆ€ν•œ ν‘œν˜„λ ₯을 κ°€μ§€λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•˜κΈ° μœ„ν•΄ λ…Έλ ₯ν•΄μ•Όκ² μŠ΅λ‹ˆλ‹€.

3. 쒋은 μΉ΄ν”Ό 방식

ν‰μ†Œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄μ„œ λ‹€λ₯Έ μ‚¬λžŒμ˜ μ½”λ“œλ₯Ό μ°Έμ‘°ν•˜λŠ” 일이 λ§ŽμŠ΅λ‹ˆλ‹€. 정닡지λ₯Ό λ¨Όμ € νŽΌμΉ˜λŠ” μŠ΅κ΄€μ΄ μ’‹μ§€λŠ” μ•Šμ§€λ§Œ, 슀슀둜 μƒκ°ν•˜λŠ” κ²ƒλ³΄λ‹€λŠ” λ‹€λ₯Έ μ‚¬λžŒμ˜ μ½”λ“œλ₯Ό λ¨Όμ € 보고 ν•΄λ‹Ή μ½”λ“œμ—μ„œ μ˜λ¬Έμ μ„ λ¨Όμ € μ°ΎλŠ” 것도 μ’‹λ‹€κ³  μƒκ°ν•˜κΈ° 떄문에 이런 νƒœλ„λ‘œ 코딩을 ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ ν˜Έλˆ…μŠ€μ˜ 말을 λ“£κ³  λ„ˆλ¬΄ 얕은 κ΄€μ μ—μ„œ νƒ€μΈμ˜ μ½”λ“œλ₯Ό μ°Έμ‘°ν–ˆλ‹€λŠ” 생각도 λ“€μ—ˆμŠ΅λ‹ˆλ‹€.

ν˜Έλˆ…μŠ€λŠ” νƒ€μΈμ˜ μ½”λ“œλ₯Ό μ°Έμ‘°ν•˜λŠ” 것도 μ’‹μ§€λ§Œ μΆ©λΆ„ν•œ 이해λ₯Ό μ„ ν–‰ν•˜κ³  μ°Έμ‘°ν•˜λΌλŠ” 말을 ν–ˆμŠ΅λ‹ˆλ‹€. 이것은 ν‰μ†Œμ— κ°€μ‘Œλ˜ νƒœλ„μ™€ μΌμΉ˜ν•˜κΈ°μ— 별 λ¬Έμ œλŠ” μ—†μŠ΅λ‹ˆλ‹€. λ¬Έμ œλŠ” κ·Έ λ‹€μŒμ˜ λ§μ΄μ—ˆμŠ΅λ‹ˆλ‹€. μ½”λ“œκ°€ 이런 νŒ¨ν„΄μ„ κ°€μ§€κ²Œ 된 역사λ₯Ό κ³΅λΆ€ν•˜λΌλŠ” λ§μž…λ‹ˆλ‹€. ν•΄λ‹Ή νŒ¨ν„΄μ΄ μ—†μ—ˆλ‹€λ©΄ μ–΄λ–€ λ¬Έμ œκ°€ 생기고, κ·Έ νŒ¨ν„΄μ΄ μ–΄λ–»κ²Œ 문제 해결에 도움이 λλŠ”μ§€κΉŒμ§€λŠ” 생각해 λ³Έ κ²½ν—˜μ΄ λ§Žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν”„λ‘œκ·Έλž˜λ°μ„ 역사적인 μΈ‘λ©΄μ—μ„œ μƒκ°ν•˜λŠ” 것도 μƒκ°μ˜ 폭을 λ„“νžˆλŠ”λ° 큰 도움이 될 것 κ°™μŠ΅λ‹ˆλ‹€.

4. μœ μ—°ν•œ μ½”λ“œ

변화와 ν™•μž₯에 μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•  수 μžˆλŠ” μ½”λ“œκ°€ 쒋은 μ½”λ“œλΌλŠ” 말을 λ“€μ—ˆμŠ΅λ‹ˆλ‹€. μƒκ°ν•΄λ³΄λ‹ˆ 이번 μš°ν…ŒμΊ  2μ°¨ κ³Όμ œν…ŒμŠ€νŠΈμ—μ„œλ„ μ»΄ν¬λ„ŒνŠΈμ˜ μž¬μ‚¬μš©μ„±μ΄ μš”κ΅¬μ‚¬ν•­μ— μžˆμ—ˆλ˜ 게 문득 λ– μ˜€λ¦…λ‹ˆλ‹€. λ²”μš©μ μΈ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄ 그것을 기반으둜 ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜λŠ” 것. 항상 머릿속에 μƒˆκ²¨λ‘¬μ•Όκ² μŠ΅λ‹ˆλ‹€. μΆ©λΆ„νžˆ μž‘μ€ λ‹¨μœ„λ‘œ 객체와 λ©”μ†Œλ“œλ₯Ό λΆ„λ¦¬ν•˜κ³  μ΅œλŒ€ν•œ μΆ©λŒμ„ λ°©μ§€ν•˜λŠ” 전체적인 ꡬ쑰λ₯Ό μ§€μ†μ μœΌλ‘œ λ– μ˜¬λ¦¬λ©° μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ² μŠ΅λ‹ˆλ‹€ :)

🌑 ν›„κΈ°

2μ£Όμ°¨ λ―Έμ…˜μ˜ 첫 μ£ΌλŠ” 섀계λ₯Ό μ€‘μ μœΌλ‘œ ν”„λ‘œκ·Έλž˜λ°μ„ μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€. API λͺ…μ„Έλ₯Ό μž‘μ„±ν•˜κ³ , μƒνƒœκ΄€λ¦¬, λΌμš°νŒ…μ˜ 틀을 μ„€κ³„ν•˜λŠ” 건 정말 μž¬λ―Έμžˆμ—ˆμŠ΅λ‹ˆλ‹€. ν‰μ†Œ 혼자 ν”„λ‘œκ·Έλž˜λ°μ„ ν•  λ•ŒλŠ” μ„€κ³„λŠ” μ „ν˜€ μ—†κ³  μ½”λ“œμ˜ μž‘μ„±μ„ λ¨Όμ € μ‹œμž‘ν–ˆμ—ˆλŠ”λ°, κ²½ν—˜ν•˜μ§€ λͺ»ν–ˆλ˜ μƒˆλ‘œμš΄ 방식은 μƒκ°μ˜ 관점과 톡찰λ ₯을 λ„“νž 수 μžˆλŠ” 쒋은 κΈ°νšŒμ˜€μŠ΅λ‹ˆλ‹€.

λ‹€λ§Œ μ£Όμ˜ν•΄μ•Όκ² λ‹€κ³  μƒκ°ν•œ 점이 ν•˜λ‚˜ μžˆλŠ”λ°, λ°”λ‘œ 섀계에 묢인 μ½”λ“œμ˜ μž‘μ„±μž…λ‹ˆλ‹€. μΆ©λΆ„νžˆ μœ μ—°ν•˜μ§€ λͺ»ν•œ μ„€κ³„λŠ” 였히렀 ν”„λ‘œκ·Έλž˜λ°μ— ν•΄λ₯Ό 끼칠 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— ν•¨κ»˜ν•˜λŠ” νŒ€μ›κ³Ό 쒋은 섀계 λ°©ν–₯에 λŒ€ν•΄ μΆ©λΆ„ν•œ λ…Όμ˜λ₯Ό κ±°μ³μ•Όν•©λ‹ˆλ‹€.

이번 λ―Έμ…˜μ„ 톡해 생각적인 μΈ‘λ©΄μ—μ„œ λ§Žμ€ 것듀을 배울 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€ γ…Žγ…Ž

profile
ν”„λ‘ νŠΈμ—”λ“œ 개발자둜 κ±Έμ–΄κ°€λŠ” μ€‘μž…λ‹ˆλ‹€.

2개의 λŒ“κΈ€

comment-user-thumbnail
2022λ…„ 7μ›” 31일

λ‹Ήμ‹ μ˜ 개발 μ‹€λ ₯을 ν›”μΉ˜κ³ μ‹Άμ–΄..

1개의 λ‹΅κΈ€