오늘은 class와 객체지향에 대해 배웠다
학교 다닐때부터 어려웠던 개념인데 새롭게 배우게돼서 뜻깊었다.
객체지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태와 메서드(함수)
로 구성됨
class Monster{ //설명서라고 할 수 있음
power = 10
constructor(aaa){//new Monster()안에 들어가는것과 같은것을 받음//여기는 함수
this.power = aaa // 안에서는 this로 받아야 함
}
attack=()=>{//메서드
console.log('공격하자')
console.log('내 공격력은' + this.power+'이야')
}
run =( )=>{//메서드
console.log('도망가자')
}
}
const myMonster1 = new Monster(50) //new연산자와 생성자 함수를 사용해 새로운 객체 생성
myMonster1.attack()
myMonster1.run()
index.js
에 상품 구매하는 API를 작성해봤다.
import express from 'express'
const app = express()
//상품 구매하기
app.post('/products/buy', (req, res) => {
res.send('상품을 구매합니다')
})
//상품 환불하기
app.post('/products/refund', (req, res)=> {
res.send('상품을 환불합니다')
})
app.listen(3000)
에 코드를 입력한다면,
1. 가진 돈 검증하는 코드(10줄)
...
...
...
2. 판매여부 검증하는 코드(10줄)
...
...
...
3. 상품 구매하는 코드
if(돈ㅇ && 판매중){
상품구매
res.send('상품을 구매합니다')
}
1. 판매여부 검증하는 코드(10줄)
...
...
...
2. 상품 환불하는 코드
if(!판매중){
res.send('상품을 환불합니다')
}
처럼 가독성이 떨어진 코드가 된다.
이것을 객체지향프로그래밍(OOP)를 해야한다.
판매여부 검증하는 코드(10줄) 를 새로운 클래스에 넣어준다면,
export class ProductService {
checkSoldout() {
// 판매여부 검증하는 코드(10줄)
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
}
}
이렇게 ProductService클래스의 checkSoldout() 객체 메서드가 된다.
같은 방법으로 가진돈 검증하는 코드를 만든다.
export class CashService {
checkValue(){
// 1. 가진돈 검증하는 코드(10줄)
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
// ...
}
}
product.js
와 cash.js
가 생성되었다.
이를 바탕으로 index.js
를 수정해 준다면,
import { ProductService } from './product.js'
import { CashService } from './cash.js'
각각 클래스를 import해주고
//상품 구매하기
app.post('/product/buy', (req, res) => {
// 1. 가진돈 검증하는 코드(10줄 => 2줄)
const cashService = new CashService()
const hasMoney = cashService.checkValue() // true 또는 false
// 2. 판매여부 검증하는 코드(10줄 => 2줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout() // true 또는 false
// 3. 상품 구매하는 코드
if(hasMoney && !isSoldout) {
res.send('상품을 구매합니다.')
}
})
//상품 환불하기
app.post('/products/refund', (req, res)=> {
//1. 판매여부 검증하는 코드(10줄->2줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout()
//2. 상품 환불하는 코드
if(!isSoldout){
res.send('상품을 환불합니다')
}
})
처럼 바꿀 수 있다.
각각의 클래스에서 새로운 객체를 new로 사용해서 선언해주고, 그 안의 매서드를 불러와서 다시 값을 넣어주는 식으로 짧게 사용된다
model, view, controller 의 모음으로, 구성요소를 세가지 역할로 구분한 패턴이다.
사용자가 보는 페이지, 데이터처리, 그리고 중간에서 제어하는 컨트롤 이렇게 3가지로 구성되는 하나의 애플리케이션을 만들면 효율적인 프로그래밍이 완성된다.
각자의 역할에 집중해 개발하여 유지보수성, 애플리케이션 확장성, 유연성이 증가하고, 중복코딩의 문제가 사라진다.
cash.js
와 product.js
는 상품 검증과 가진 돈 검증을 진행했으므로 비즈니스 로직이라 하고, service라고 칭해진다. mvc에서는 controller에 해당한다.
cash.service.js
와 product.service.js
로 파일명을 변경해주고, 경로도 재설정한다.
import { ProductService } from './services/product.service.js'
import { CashService } from './services/cash.service.js'
ìndex.js
파일의 class도 controller로 만들어서 productController
로 묶어준다.
export class ProductController{
buyProduct=(req, res)=>{ //직관적인 이름->> 동사-명사순으로 이름 설정 함수에서 한개기능만
//1. 가진 돈 검증하는 코드(10줄->2줄)
const cashService = new CashService()
const hasMoney = cashService.checkValue()
//판매여부 검증하는 코드(10줄 -> 2줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout()
//3. 상품 구매하는 코드
if(hasMoney && !isSoldout){
//상품구매
res.send('상품을 구매합니다')
}
}
refundProduct=(req, res)=> {
//1. 판매여부 검증하는 코드(10줄->2줄)
const productService = new ProductService()
const isSoldout = productService.checkSoldout()
//2. 상품 환불하는 코드
if(!isSoldout){
res.send('상품을 환불합니다')
}
}
}
여기에서 buyProduct는 cashService와 productService를 변수로 생성하고 직접 사용하는데 이런 관계를 의존관계(dependency)라고 한다.
controller 내부에서 비즈니스 로직을 변수로 선언하여 사용함에 따라 강하게 결합(Tight Coupling)하며 높은 의존성을 갖고 있다.
코드를 만들어 product.controller.js
파일을 생성한다.
이렇게 되면 index.js
파일에 남는것은
import express from 'express'
import { ProductController } from './model/product.controller.js'
const app = express()
//상품 API
const productController = new ProductController()
app.post('/products/buy',productController.buyProduct)
app.post('/products/refund', productController.refundProduct)
app.listen(3000)
처럼 간단한 내용만을 갖게된다.
endPoint별로 분리하여 라우팅을 핸들링한다. 즉, endPoint별로 분리하여 controller를 실행시킨다.