728x90
Node.js 심화 1주차_3
응집도 ↑ 결합도 ↓
/** OCP Before **/
function calculator(nums, option) {
let result = 0;
for (const num of nums) {
if (option === "add") result += num; // option이 add일 경우 덧셈 연산을 합니다.
else if (option === "sub") result -= num; // option이 sub일 경우 뺄셈 연산을 합니다.
// 새로운 연산(기능)을 추가 하기 위해서는 함수 내부에서 코드 수정이 필요합니다.
}
return result;
}
console.log(calculator([2, 3, 5], "add")); // 10
console.log(calculator([5, 2, 1], "sub")); // -8
/** OCP After **/
function calculator(nums, callBackFunc) {
// option을 CallbackFunc로 변경
let result = 0;
for (const num of nums) {
result = callBackFunc(result, num); // option으로 분기하지 않고, Callback함수를 실행하도록 변경
}
return result;
}
const add = (a, b) => a + b; // 함수 변수를 정의합니다.
const sub = (a, b) => a - b;
const mul = (a, b) => a * b;
const div = (a, b) => a / b;
console.log(calculator([2, 3, 5], add)); // add 함수 변수를 Callback 함수로 전달합니다.
console.log(calculator([5, 2, 1], sub)); // sub 함수 변수를 Callback 함수로 전달합니다.
SOLID의 종류
- 단일 책임의 원칙 (Single Responsibility Principle, SRP)
- 개방-폐쇄 원칙 (Open-Closed Principle, OCP)
- 리스코프 치환 원칙 (Liskov substitution principle, LSP)
- 인터페이스 분리 원칙 (Interface segregation principle, ISP)
- 의존성 역전 원칙 (Dependency Inversion Principle, DIP)
📌 설치(Terminal)
npm init -y
npm install -g typescript
tsc --init
tsc oop-for-ts.ts
node oop-for-ts.js
📄oop-for-ts.ts
/** Encapsulation **/
class User {
private name: string;
private age: number;
setName(name: string) { // Private 속성을 가진 name 변수의 값을 변경합니다.
this.name = name;
}
getName() { // Private 속성을 가진 name 변수의 값을 조회합니다.
return this.name;
}
setAge(age: number) { // Private 속성을 가진 age 변수의 값을 변경합니다.
this.age = age;
}
getAge() { // Private 속성을 가진 age 변수의 값을 조회합니다.
return this.age;
}
}
const user = new User(); // user 인스턴스 생성
user.setName("이용우");
user.setAge(28);
console.log(user.getName()); // 이용우
console.log(user.getAge()); // 28
// console.log(user.name); // Error: User클래스의 name 변수는 private로 설정되어 있어 바로 접근할 수 없습니다.
📄oop-for-ts.js
/** Encapsulation **/
var User = /** @class */ (function () {
function User() {
}
User.prototype.setName = function (name) {
this.name = name;
};
User.prototype.getName = function () {
return this.name;
};
User.prototype.setAge = function (age) {
this.age = age;
};
User.prototype.getAge = function () {
return this.age;
};
return User;
}());
var user = new User(); // user 인스턴스 생성
user.setName("이용우");
user.setAge(28);
console.log(user.getName()); // 이용우
console.log(user.getAge()); // 28
console.log(user.name); // Error: User클래스의 name 변수는 private로 설정되어 있어 바로 접근할 수 없습니다.
/** Inheritance **/
class Mother { // Mother 부모 클래스
constructor(name, age, tech) { // 부모 클래스 생성자
this.name = name;
this.age = age;
this.tech = tech;
}
getTech(){ return this.tech; } // 부모 클래스 getTech 메서드
}
class Child extends Mother{ // Mother 클래스를 상속받은 Child 자식 클래스
constructor(name, age, tech) { // 자식 클래스 생성자
super(name, age, tech);
}
}
const child = new Child("이용우", "28", "Node.js");
console.log(child.name); // 이용우
console.log(child.age); // 28
console.log(child.getTech()); // 부모 클래스의 getTech 메서드 호출: Node.js
쇼핑몰 프로젝트 코드 분리
📌 코드 분리하는 이유
- 가독성 향상(추상화, 코드을 이해하기 쉽도록 함수로 분리)
- 관리(유지보수) 용이
📄 원래코드
io.on('connection', (sock) => {
console.log('새로운 소켓이 연결됐어요!');
sock.on('BUY', (data) => {
const emitData = {
...data,
date: new Date().toISOString(),
};
io.emit('BUY_GOODS', emitData);
});
... // 생략
sock.on('disconnect', () => {
console.log(sock.id, '연결이 끊어졌어요!');
});
});
📄app.js
// 4. 소켓 연결 이벤트 핸들링
io.on('connection', (sock) => {
const { watchBuying, watchByebye } = initSocket(sock);
watchBuying();
watchByebye();
});
function initSocket(sock) {
console.log('새로운 소켓이 연결됐어요!');
// 특정 이벤트가 전달됐는지 감지할 때 사용될 함수
function watchEvent(event, func) {
sock.on(event, func);
}
// 연결된 모든 클라이언트에 데이터를 보낼때 사용될 함수
function sendMessageAll(event, data) {
io.emit(event, data);
}
return {
watchBuying: () => {
watchEvent('BUY', (data) => {
const emitData = {
...data,
date: new Date().toISOString(),
};
sendMessageAll('BUY_GOODS', emitData);
});
},
watchByebye: () => {
watchEvent('disconnect', () => {
console.log(sock.id, '연결이 끊어졌어요!');
});
},
};
}
sendMessageAll 라는 함수를 호출하면
"지금 서버와 소켓으로 연결된 모든 클라이언트에 메세지를 보내는 기능"을 수행하는것만 알고 있으면 됨!
📄app.js
module.exports = http;
📄socket.js
const socketIo = require("socket.io"); // 1. 모듈 불러오기
const http = require("./app");
const io = socketIo(http); // 3. http 객체를 Socket.io 모듈에 넘겨서 소켓 핸들러 생성
// 4. 소켓 연결 이벤트 핸들링
io.on('connection', (sock) => {
const { watchBuying, watchByebye } = initSocket(sock);
watchBuying();
watchByebye();
});
function initSocket(sock) {
console.log('새로운 소켓이 연결됐어요!');
// 특정 이벤트가 전달됐는지 감지할 때 사용될 함수
function watchEvent(event, func) {
sock.on(event, func);
}
// 연결된 모든 클라이언트에 데이터를 보낼때 사용될 함수
function sendMessageAll(event, data) {
io.emit(event, data);
}
return {
watchBuying: () => {
watchEvent('BUY', (data) => {
const emitData = {
...data,
date: new Date().toISOString(),
};
sendMessageAll('BUY_GOODS', emitData);
});
},
watchByebye: () => {
watchEvent('disconnect', () => {
console.log(sock.id, '연결이 끊어졌어요!');
});
},
};
}
📄server.js
const http = require("./app");
require("./socket");
// 5. app 대신 http 객체로 서버 열기
http.listen(8080, () => {
console.log("서버가 요청을 받을 준비가 됐어요");
});
📌 test(Terminal)
node server
'JavaScript' 카테고리의 다른 글
Node.js 숙련주차 숙제 최종 제출 (0) | 2022.12.28 |
---|---|
Node.js 심화 1주차_4 (0) | 2022.12.28 |
Node.js 심화 1주차_2 (0) | 2022.12.26 |
Node 숙련 개인과제 ER다이어그램 (0) | 2022.12.26 |
Node.js 심화 1주차_1 (0) | 2022.12.26 |