1. npm install express nunjucks sequelize sequelize-cli mysql2 설치하기
nodemon - 편하고 좋은 것 (server 껏다 켰다 연습하기 때문에 지금은 안쓸 것!)
2. npx sequelizes init (폴더, 폴더 안 파일들을 줌)
npm - 우리가 다운을 받지 않은 상태 - 폴더를 다운받은 것 - 기본적인 틀 제공
npx - install 해서 다운받은 폴더를 실행시켜서 세팅해준 것
* config 폴더 안 config 파일 존재, models 폴더 안 index.js 파일 존재
config - 접속 정보를 저장해주는 객체
실 서버의 정보를 development
연습(test server)은 test
상품 정보는 production에 담아 달라
3. config - config 파일 안 development 정보 내 컴퓨터 정보로 바꾸기
{
"development": {
"username": "root",
"password": "d", //변경
"database": "joinn", //변경
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
4. models- index.js 분석
'use strict'; //없어도 상관 없다.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize'); //Sequelize
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development'; //test할 때 development를 test로 바꿔
const config = require(__dirname + '/../config/config.json')[env]; // env 위에 정의되어 있음. 우리는env 설정안했음. 지금 env = development 값 / config는 요걸 가져옴
// config = config파일 안 development 의 객체 값이 된다.
const db = {}; //빈 객체로 선언
let sequelize; //sequelize
if (config.use_env_variable) { // config에 use_env_variable이라는 정보가 있으면 ~
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else { //요게 우리가 실행될 것
sequelize = new Sequelize(config.database, config.username, config.password, config);
} // new = 함수가 객체로 변한다 / 결과적으로 요 값이 객체로 변하겠구나~ 알 수 있음. config 어디서 가져왓냐면 위에 8번줄
// development 객체 안의 내용을 내 db 내용과 같도록 정보 바꾸기
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize; //sequelize, Sequelize 두가지 속성 값을 db에 넣었다.
db.Sequelize = Sequelize;
module.exports = db; // db라는 변수를 결과적으로 넘기는구나
//db라는 파일을 불러왔을 때 객체로 받는구나 알 수 있음.
//팁 : 얘는 결국 무엇을 넘기나 아랫줄에 module을 쳌! 그거에 대한 결과값이 무엇인가 무언가를 담아서 보냈는가 를 쳌
5. app.js 파일 생성 & 기본구조 코드 작성 (서버 실행할 때 이걸로 실행하겠다.
const express = require('express');
const app = express();
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
6. index.js 파일을 가져오기
const express = require('express');
const app = express();
const sequelize=require('./models') //index생략가능 요것만 추가함
console.log(sequelize)
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
console.log로 sequelize 내용 쳌
{
sequelize: <ref *1> Sequelize { //요기 sequelize안에 들어감 sequelize는 Sequeliz의 객체로 된
options: {
dialect: 'mysql',
dialectModule: null,
dialectModulePath: null,
host: '127.0.0.1',
protocol: 'tcp',
define: {},
query: {},
sync: {},
timezone: '+00:00',
clientMinMessages: 'warning',
standardConformingStrings: true,
logging: [Function: log],
omitNull: false,
native: false,
replication: false,
ssl: undefined,
pool: {},
quoteIdentifiers: true,
hooks: {},
retry: [Object],
transactionType: 'DEFERRED',
isolationLevel: null,
databaseVersion: 0,
typeValidation: false,
benchmark: false,
minifyAliases: false,
logQueryParameters: false,
username: 'root',
password: 'd',
database: 'joinn'
},
config: {
database: 'joinn',
username: 'root',
password: 'd',
host: '127.0.0.1',
port: 3306,
pool: {},
protocol: 'tcp',
native: false,
ssl: undefined,
replication: false,
dialectModule: null,
dialectModulePath: null,
keepDefaultTimezone: undefined,
dialectOptions: undefined
},
dialect: MysqlDialect {
sequelize: [Circular *1],
connectionManager: [ConnectionManager],
queryGenerator: [MySQLQueryGenerator],
queryInterface: [MySQLQueryInterface]
},
queryInterface: MySQLQueryInterface {
sequelize: [Circular *1],
queryGenerator: [MySQLQueryGenerator]
},
models: {},
modelManager: ModelManager { models: [], sequelize: [Circular *1] },
connectionManager: ConnectionManager {
sequelize: [Circular *1],
config: [Object],
dialect: [MysqlDialect],
versionPromise: null,
dialectName: 'mysql',
pool: [Pool],
lib: [Object]
}
},
Sequelize: <ref *5> [class Sequelize] { //Sequelize는 class 다
version: '6.6.2',
options: { hooks: {} },
Utils: {
classToInvokable: [Function: classToInvokable],
joinSQLFragments: [Function: joinSQLFragments],
useInflection: [Function: useInflection],
camelizeIf: [Function: camelizeIf],
underscoredIf: [Function: underscoredIf],
isPrimitive: [Function: isPrimitive],
mergeDefaults: [Function: mergeDefaults],
merge: [Function: merge],
spliceStr: [Function: spliceStr],
camelize: [Function: camelize],
underscore: [Function: underscore],
singularize: [Function: singularize],
pluralize: [Function: pluralize],
format: [Function: format],
formatNamedParameters: [Function: formatNamedParameters],
cloneDeep: [Function: cloneDeep],
mapFinderOptions: [Function: mapFinderOptions],
mapOptionFieldNames: [Function: mapOptionFieldNames],
mapWhereFieldNames: [Function: mapWhereFieldNames],
mapValueFieldNames: [Function: mapValueFieldNames],
isColString: [Function: isColString],
canTreatArrayAsAnd: [Function: canTreatArrayAsAnd],
combineTableNames: [Function: combineTableNames],
toDefaultValue: [Function: toDefaultValue],
defaultValueSchemable: [Function: defaultValueSchemable],
removeNullValuesFromHash: [Function: removeNullValuesFromHash],
now: [Function: now],
TICK_CHAR: '`',
addTicks: [Function: addTicks],
removeTicks: [Function: removeTicks],
flattenObjectDeep: [Function: flattenObjectDeep],
SequelizeMethod: [class SequelizeMethod],
Fn: [class Fn extends SequelizeMethod],
Col: [class Col extends SequelizeMethod],
Cast: [class Cast extends SequelizeMethod],
Literal: [class Literal extends SequelizeMethod],
Json: [class Json extends SequelizeMethod],
Where: [class Where extends SequelizeMethod],
getOperators: [Function: getOperators],
getComplexKeys: [Function: getComplexKeys],
getComplexSize: [Function: getComplexSize],
isWhereEmpty: [Function: isWhereEmpty],
generateEnumName: [Function: generateEnumName],
camelizeObjectKeys: [Function: camelizeObjectKeys],
defaults: [Function: defaults],
nameIndex: [Function: nameIndex],
intersects: [Function: intersects]
},
Op: {
eq: Symbol(eq),
ne: Symbol(ne),
gte: Symbol(gte),
gt: Symbol(gt),
lte: Symbol(lte),
lt: Symbol(lt),
not: Symbol(not),
is: Symbol(is),
in: Symbol(in),
notIn: Symbol(notIn),
like: Symbol(like),
notLike: Symbol(notLike),
iLike: Symbol(iLike),
notILike: Symbol(notILike),
startsWith: Symbol(startsWith),
endsWith: Symbol(endsWith),
substring: Symbol(substring),
regexp: Symbol(regexp),
notRegexp: Symbol(notRegexp),
iRegexp: Symbol(iRegexp),
notIRegexp: Symbol(notIRegexp),
between: Symbol(between),
notBetween: Symbol(notBetween),
overlap: Symbol(overlap),
contains: Symbol(contains),
contained: Symbol(contained),
adjacent: Symbol(adjacent),
strictLeft: Symbol(strictLeft),
strictRight: Symbol(strictRight),
noExtendRight: Symbol(noExtendRight),
noExtendLeft: Symbol(noExtendLeft),
and: Symbol(and),
or: Symbol(or),
any: Symbol(any),
all: Symbol(all),
values: Symbol(values),
col: Symbol(col),
placeholder: Symbol(placeholder),
join: Symbol(join),
match: Symbol(match)
},
TableHints: {
NOLOCK: 'NOLOCK',
READUNCOMMITTED: 'READUNCOMMITTED',
UPDLOCK: 'UPDLOCK',
REPEATABLEREAD: 'REPEATABLEREAD',
SERIALIZABLE: 'SERIALIZABLE',
READCOMMITTED: 'READCOMMITTED',
TABLOCK: 'TABLOCK',
TABLOCKX: 'TABLOCKX',
PAGLOCK: 'PAGLOCK',
ROWLOCK: 'ROWLOCK',
NOWAIT: 'NOWAIT',
READPAST: 'READPAST',
XLOCK: 'XLOCK',
SNAPSHOT: 'SNAPSHOT',
NOEXPAND: 'NOEXPAND'
},
IndexHints: { USE: 'USE', FORCE: 'FORCE', IGNORE: 'IGNORE' },
Transaction: <ref *2> [class Transaction] {
Transaction: [Circular *2],
default: [Circular *2]
},
QueryTypes: {
SELECT: 'SELECT',
INSERT: 'INSERT',
UPDATE: 'UPDATE',
BULKUPDATE: 'BULKUPDATE',
BULKDELETE: 'BULKDELETE',
DELETE: 'DELETE',
UPSERT: 'UPSERT',
VERSION: 'VERSION',
SHOWTABLES: 'SHOWTABLES',
SHOWINDEXES: 'SHOWINDEXES',
DESCRIBE: 'DESCRIBE',
RAW: 'RAW',
FOREIGNKEYS: 'FOREIGNKEYS',
SHOWCONSTRAINTS: 'SHOWCONSTRAINTS'
},
Validator: <ref *3> {
version: '10.11.0',
toDate: [Function],
toFloat: [Function],
toInt: [Function],
toBoolean: [Function],
equals: [Function],
contains: [Function: contains],
matches: [Function],
isEmail: [Function],
isURL: [Function],
isMACAddress: [Function],
isIP: [Function],
isIPRange: [Function],
isFQDN: [Function],
isBoolean: [Function],
isAlpha: [Function: isAlpha],
isAlphaLocales: [Array],
isAlphanumeric: [Function: isAlphanumeric],
isAlphanumericLocales: [Array],
isNumeric: [Function],
isPort: [Function],
isLowercase: [Function],
isUppercase: [Function],
isAscii: [Function],
isFullWidth: [Function: isFullWidth],
isHalfWidth: [Function: isHalfWidth],
isVariableWidth: [Function],
isMultibyte: [Function],
isSurrogatePair: [Function],
isInt: [Function],
isFloat: [Function: isFloat],
isFloatLocales: [Array],
isDecimal: [Function: isDecimal],
isHexadecimal: [Function],
isDivisibleBy: [Function],
isHexColor: [Function],
isISRC: [Function],
isMD5: [Function],
isHash: [Function],
isJWT: [Function],
isJSON: [Function],
isEmpty: [Function],
isLength: [Function],
isByteLength: [Function],
isUUID: [Function],
isMongoId: [Function],
isAfter: [Function],
isBefore: [Function],
isIn: [Function],
isCreditCard: [Function],
isIdentityCard: [Function],
isISIN: [Function],
isISBN: [Function],
isISSN: [Function],
isMobilePhone: [Function: isMobilePhone],
isMobilePhoneLocales: [Array],
isPostalCode: [Function: _default],
isPostalCodeLocales: [Array],
isCurrency: [Function],
isISO8601: [Function],
isRFC3339: [Function],
isISO31661Alpha2: [Function],
isISO31661Alpha3: [Function],
isBase64: [Function],
isDataURI: [Function],
isMagnetURI: [Function],
isMimeType: [Function],
isLatLong: [Function],
ltrim: [Function],
rtrim: [Function],
trim: [Function],
escape: [Function],
unescape: [Function],
stripLow: [Function],
whitelist: [Function],
blacklist: [Function],
isWhitelisted: [Function],
normalizeEmail: [Function],
toString: [Function],
default: [Circular *3],
isImmutable: [Function (anonymous)],
notNull: [Function (anonymous)],
extend: [Function: extend],
notEmpty: [Function: notEmpty],
len: [Function: len],
isUrl: [Function: isUrl],
isIPv6: [Function: isIPv6],
isIPv4: [Function: isIPv4],
notIn: [Function: notIn],
regex: [Function: regex],
notRegex: [Function: notRegex],
min: [Function: min],
max: [Function: max],
not: [Function: not],
notContains: [Function: notContains],
is: [Function: is],
isNull: [Function],
isDate: [Function (anonymous)]
},
Model: Model,
DataTypes: {
ABSTRACT: [Function],
STRING: [Function],
CHAR: [Function],
TEXT: [Function],
NUMBER: [Function],
TINYINT: [Function],
SMALLINT: [Function],
MEDIUMINT: [Function],
INTEGER: [Function],
BIGINT: [Function],
FLOAT: [Function],
TIME: [Function],
DATE: [Function],
DATEONLY: [Function],
BOOLEAN: [Function],
NOW: [Function],
BLOB: [Function],
DECIMAL: [Function],
NUMERIC: [Function],
UUID: [Function],
UUIDV1: [Function],
UUIDV4: [Function],
HSTORE: [Function],
JSON: [Function],
JSONB: [Function],
VIRTUAL: [Function],
ARRAY: [Function],
ENUM: [Function],
RANGE: [Function],
REAL: [Function],
'DOUBLE PRECISION': [Function],
DOUBLE: [Function],
GEOMETRY: [Function],
GEOGRAPHY: [Function],
CIDR: [Function],
INET: [Function],
MACADDR: [Function],
CITEXT: [Function],
TSVECTOR: [Function],
postgres: [Object],
mysql: [Object],
mariadb: [Object],
sqlite: [Object],
mssql: [Object]
},
ABSTRACT: [class ABSTRACT] { types: {}, key: 'ABSTRACT' },
STRING: [class STRING extends ABSTRACT] { types: [Object], key: 'STRING' },
CHAR: [class CHAR extends STRING] { types: [Object], key: 'CHAR' },
TEXT: [class TEXT extends ABSTRACT] { types: [Object], key: 'TEXT' },
NUMBER: [class NUMBER extends ABSTRACT] { types: {}, key: 'NUMBER' },
TINYINT: [class TINYINT extends INTEGER] { types: [Object], key: 'TINYINT' },
SMALLINT: [class SMALLINT extends INTEGER] {
types: [Object],
key: 'SMALLINT'
},
MEDIUMINT: [class MEDIUMINT extends INTEGER] {
types: [Object],
key: 'MEDIUMINT'
},
INTEGER: [class INTEGER extends NUMBER] { types: [Object], key: 'INTEGER' },
BIGINT: [class BIGINT extends INTEGER] { types: [Object], key: 'BIGINT' },
FLOAT: [class FLOAT extends NUMBER] { types: [Object], key: 'FLOAT' },
TIME: [class TIME extends ABSTRACT] { types: [Object], key: 'TIME' },
DATE: [class DATE extends ABSTRACT] { types: [Object], key: 'DATE' },
DATEONLY: [class DATEONLY extends ABSTRACT] {
types: [Object],
key: 'DATEONLY'
},
BOOLEAN: [class BOOLEAN extends ABSTRACT] {
parse: [Function: _sanitize],
types: [Object],
key: 'BOOLEAN'
},
NOW: [class NOW extends ABSTRACT] { types: {}, key: 'NOW' },
BLOB: [class BLOB extends ABSTRACT] { types: [Object], key: 'BLOB' },
DECIMAL: [class DECIMAL extends NUMBER] { types: [Object], key: 'DECIMAL' },
NUMERIC: [class DECIMAL extends NUMBER] { types: [Object], key: 'DECIMAL' },
UUID: [class UUID extends ABSTRACT] { types: [Object], key: 'UUID' },
UUIDV1: [class UUIDV1 extends ABSTRACT] { types: {}, key: 'UUIDV1' },
UUIDV4: [class UUIDV4 extends ABSTRACT] { types: {}, key: 'UUIDV4' },
HSTORE: [class HSTORE extends ABSTRACT] { types: [Object], key: 'HSTORE' },
JSON: [class JSONTYPE extends ABSTRACT] { types: [Object], key: 'JSON' },
JSONB: [class JSONB extends JSONTYPE] { types: [Object], key: 'JSONB' },
VIRTUAL: [class VIRTUAL extends ABSTRACT] { types: {}, key: 'VIRTUAL' },
ARRAY: [class ARRAY extends ABSTRACT] { types: {}, key: 'ARRAY' },
ENUM: [class ENUM extends ABSTRACT] { types: [Object], key: 'ENUM' },
RANGE: [class RANGE extends ABSTRACT] { types: [Object], key: 'RANGE' },
REAL: [class REAL extends NUMBER] { types: [Object], key: 'REAL' },
'DOUBLE PRECISION': [class DOUBLE extends NUMBER] {
types: [Object],
key: 'DOUBLE PRECISION'
},
DOUBLE: [class DOUBLE extends NUMBER] {
types: [Object],
key: 'DOUBLE PRECISION'
},
GEOMETRY: [class GEOMETRY extends ABSTRACT] {
types: [Object],
key: 'GEOMETRY'
},
GEOGRAPHY: [class GEOGRAPHY extends ABSTRACT] {
types: [Object],
key: 'GEOGRAPHY'
},
CIDR: [class CIDR extends ABSTRACT] { types: [Object], key: 'CIDR' },
INET: [class INET extends ABSTRACT] { types: [Object], key: 'INET' },
MACADDR: [class MACADDR extends ABSTRACT] { types: [Object], key: 'MACADDR' },
CITEXT: [class CITEXT extends ABSTRACT] { types: [Object], key: 'CITEXT' },
TSVECTOR: [class TSVECTOR extends ABSTRACT] {
types: [Object],
key: 'TSVECTOR'
},
postgres: {
DECIMAL: [class DECIMAL extends DECIMAL],
BLOB: [class BLOB extends BLOB],
STRING: [class STRING extends STRING],
CHAR: [class CHAR extends CHAR],
TEXT: [class TEXT extends TEXT],
CITEXT: [class CITEXT extends CITEXT],
TINYINT: [class TINYINT extends TINYINT],
SMALLINT: [class SMALLINT extends SMALLINT],
INTEGER: [Function],
BIGINT: [class BIGINT extends BIGINT],
BOOLEAN: [Function],
DATE: [class DATE extends DATE],
DATEONLY: [class DATEONLY extends DATEONLY],
REAL: [class REAL extends REAL],
'DOUBLE PRECISION': [class DOUBLE extends DOUBLE],
FLOAT: [class FLOAT extends FLOAT],
GEOMETRY: [class GEOMETRY extends GEOMETRY],
GEOGRAPHY: [class GEOGRAPHY extends GEOGRAPHY],
HSTORE: [class HSTORE extends HSTORE],
RANGE: [class RANGE extends RANGE],
ENUM: [class ENUM extends ENUM]
},
mysql: {
ENUM: [class ENUM extends ENUM],
DATE: [class DATE extends DATE],
DATEONLY: [class DATEONLY extends DATEONLY],
UUID: [class UUID extends UUID],
GEOMETRY: [class GEOMETRY extends GEOMETRY],
DECIMAL: [class DECIMAL extends DECIMAL],
JSON: [class JSONTYPE extends JSONTYPE]
},
mariadb: {
ENUM: [class ENUM extends ENUM],
DATE: [class DATE extends DATE],
DATEONLY: [class DATEONLY extends DATEONLY],
UUID: [class UUID extends UUID],
GEOMETRY: [class GEOMETRY extends GEOMETRY],
DECIMAL: [class DECIMAL extends DECIMAL],
JSON: [class JSONTYPE extends JSONTYPE]
},
sqlite: {
DATE: [class DATE extends DATE],
DATEONLY: [class DATEONLY extends DATEONLY],
STRING: [class STRING extends STRING],
CHAR: [class CHAR extends CHAR],
NUMBER: [class NUMBER extends NUMBER],
FLOAT: [Function],
REAL: [Function],
'DOUBLE PRECISION': [Function],
TINYINT: [class TINYINT extends TINYINT],
SMALLINT: [class SMALLINT extends SMALLINT],
MEDIUMINT: [class MEDIUMINT extends MEDIUMINT],
INTEGER: [class INTEGER extends INTEGER],
BIGINT: [class BIGINT extends BIGINT],
TEXT: [class TEXT extends TEXT],
ENUM: [class ENUM extends ENUM],
JSON: [class JSONTYPE extends JSONTYPE],
CITEXT: [class CITEXT extends CITEXT]
},
mssql: {
BLOB: [class BLOB extends BLOB],
BOOLEAN: [class BOOLEAN extends BOOLEAN],
ENUM: [class ENUM extends ENUM],
STRING: [class STRING extends STRING],
UUID: [class UUID extends UUID],
DATE: [class DATE extends DATE],
DATEONLY: [class DATEONLY extends DATEONLY],
NOW: [class NOW extends NOW],
TINYINT: [class TINYINT extends TINYINT],
SMALLINT: [class SMALLINT extends SMALLINT],
INTEGER: [class INTEGER extends INTEGER],
BIGINT: [class BIGINT extends BIGINT],
REAL: [class REAL extends REAL],
FLOAT: [class FLOAT extends FLOAT],
TEXT: [class TEXT extends TEXT]
},
Deferrable: {
INITIALLY_DEFERRED: [class INITIALLY_DEFERRED extends ABSTRACT],
INITIALLY_IMMEDIATE: [class INITIALLY_IMMEDIATE extends ABSTRACT],
NOT: [class NOT extends ABSTRACT],
SET_DEFERRED: [class SET_DEFERRED extends ABSTRACT],
SET_IMMEDIATE: [class SET_IMMEDIATE extends ABSTRACT]
},
Association: <ref *4> [class Association] {
BelongsTo: [Function],
HasOne: [class HasOne extends Association],
HasMany: [Function],
BelongsToMany: [Function],
default: [Circular *4],
Association: [Circular *4]
},
useInflection: [Function: useInflection],
_setupHooks: [Function: _setupHooks],
runHooks: [AsyncFunction: runHooks],
addHook: [Function: addHook],
removeHook: [Function: removeHook],
hasHook: [Function: hasHook],
hasHooks: [Function: hasHook],
beforeValidate: [Function (anonymous)],
afterValidate: [Function (anonymous)],
validationFailed: [Function (anonymous)],
beforeCreate: [Function (anonymous)],
afterCreate: [Function (anonymous)],
beforeDestroy: [Function (anonymous)],
afterDestroy: [Function (anonymous)],
beforeRestore: [Function (anonymous)],
afterRestore: [Function (anonymous)],
beforeUpdate: [Function (anonymous)],
afterUpdate: [Function (anonymous)],
beforeSave: [Function (anonymous)],
afterSave: [Function (anonymous)],
beforeUpsert: [Function (anonymous)],
afterUpsert: [Function (anonymous)],
beforeBulkCreate: [Function (anonymous)],
afterBulkCreate: [Function (anonymous)],
beforeBulkDestroy: [Function (anonymous)],
afterBulkDestroy: [Function (anonymous)],
beforeBulkRestore: [Function (anonymous)],
afterBulkRestore: [Function (anonymous)],
beforeBulkUpdate: [Function (anonymous)],
afterBulkUpdate: [Function (anonymous)],
beforeFind: [Function (anonymous)],
beforeFindAfterExpandIncludeAll: [Function (anonymous)],
beforeFindAfterOptions: [Function (anonymous)],
afterFind: [Function (anonymous)],
beforeCount: [Function (anonymous)],
beforeDefine: [Function (anonymous)],
afterDefine: [Function (anonymous)],
beforeInit: [Function (anonymous)],
afterInit: [Function (anonymous)],
beforeAssociate: [Function (anonymous)],
afterAssociate: [Function (anonymous)],
beforeConnect: [Function (anonymous)],
afterConnect: [Function (anonymous)],
beforeDisconnect: [Function (anonymous)],
afterDisconnect: [Function (anonymous)],
beforeSync: [Function (anonymous)],
afterSync: [Function (anonymous)],
beforeBulkSync: [Function (anonymous)],
afterBulkSync: [Function (anonymous)],
beforeQuery: [Function (anonymous)],
afterQuery: [Function (anonymous)],
Error: [class BaseError extends Error],
BaseError: [class BaseError extends Error],
AggregateError: [class AggregateError extends BaseError],
AsyncQueueError: [class AsyncQueueError extends BaseError],
AssociationError: [class AssociationError extends BaseError],
BulkRecordError: [class BulkRecordError extends BaseError],
ConnectionError: [class ConnectionError extends BaseError],
DatabaseError: [class DatabaseError extends BaseError],
EagerLoadingError: [class EagerLoadingError extends BaseError],
EmptyResultError: [class EmptyResultError extends BaseError],
InstanceError: [class InstanceError extends BaseError],
OptimisticLockError: [class OptimisticLockError extends BaseError],
QueryError: [class QueryError extends BaseError],
SequelizeScopeError: [class SequelizeScopeError extends BaseError],
ValidationError: [class ValidationError extends BaseError] {
ValidationErrorItem: [Function]
},
ValidationErrorItem: [class ValidationErrorItem] {
Origins: [Object],
TypeStringMap: [Object]
},
AccessDeniedError: [class AccessDeniedError extends ConnectionError],
ConnectionAcquireTimeoutError: [class ConnectionAcquireTimeoutError extends ConnectionError],
ConnectionRefusedError: [class ConnectionRefusedError extends ConnectionError],
ConnectionTimedOutError: [class ConnectionTimedOutError extends ConnectionError],
HostNotFoundError: [class HostNotFoundError extends ConnectionError],
HostNotReachableError: [class HostNotReachableError extends ConnectionError],
InvalidConnectionError: [class InvalidConnectionError extends ConnectionError],
ExclusionConstraintError: [class ExclusionConstraintError extends DatabaseError],
ForeignKeyConstraintError: [class ForeignKeyConstraintError extends DatabaseError],
TimeoutError: [class TimeoutError extends DatabaseError],
UnknownConstraintError: [class UnknownConstraintError extends DatabaseError],
UniqueConstraintError: [class UniqueConstraintError extends ValidationError],
Sequelize: [Circular *5],
default: [Circular *5]
}
}
변수sequelize에 { } 치고 나서 console.log 찍어보기
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능
console.log(sequelize)
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
<ref *1> Sequelize {
options: { //option
dialect: 'mysql',
dialectModule: null,
dialectModulePath: null,
host: '127.0.0.1',
protocol: 'tcp',
define: {},
query: {},
sync: {},
timezone: '+00:00',
clientMinMessages: 'warning',
standardConformingStrings: true,
logging: [Function: log],
omitNull: false,
native: false,
replication: false,
ssl: undefined,
pool: {},
quoteIdentifiers: true,
hooks: {},
retry: { max: 5, match: [Array] },
transactionType: 'DEFERRED',
isolationLevel: null,
databaseVersion: 0,
typeValidation: false,
benchmark: false,
minifyAliases: false,
logQueryParameters: false,
username: 'root',
password: 'd',
database: 'joinn'
},
config: { //config 존재
database: 'joinn',
username: 'root',
password: 'd',
host: '127.0.0.1',
port: 3306,
pool: {},
protocol: 'tcp',
native: false,
ssl: undefined,
replication: false,
dialectModule: null,
dialectModulePath: null,
keepDefaultTimezone: undefined,
dialectOptions: undefined
},
dialect: <ref *2> MysqlDialect {
sequelize: [Circular *1],
connectionManager: ConnectionManager {
sequelize: [Circular *1],
config: [Object],
dialect: [Circular *2],
versionPromise: null,
dialectName: 'mysql',
pool: [Pool],
lib: [Object]
},
queryGenerator: MySQLQueryGenerator {
sequelize: [Circular *1],
options: [Object],
dialect: 'mysql',
_dialect: [Circular *2],
OperatorMap: [Object],
typeValidation: undefined
},
queryInterface: MySQLQueryInterface {
sequelize: [Circular *1],
queryGenerator: [MySQLQueryGenerator]
}
},
queryInterface: MySQLQueryInterface {
sequelize: [Circular *1],
queryGenerator: MySQLQueryGenerator {
sequelize: [Circular *1],
options: [Object],
dialect: 'mysql',
_dialect: [MysqlDialect],
OperatorMap: [Object],
typeValidation: undefined
}
},
models: {},
modelManager: ModelManager { models: [], sequelize: [Circular *1] },
connectionManager: <ref *3> ConnectionManager {
sequelize: [Circular *1], //class 가 빠졌넹
config: {
database: 'joinn',
username: 'root',
password: 'd',
host: '127.0.0.1',
port: 3306,
pool: [Object],
protocol: 'tcp',
native: false,
ssl: undefined,
replication: false,
dialectModule: null,
dialectModulePath: null,
keepDefaultTimezone: undefined,
dialectOptions: undefined
},
dialect: <ref *2> MysqlDialect {
sequelize: [Circular *1],
connectionManager: [Circular *3],
queryGenerator: [MySQLQueryGenerator],
queryInterface: [MySQLQueryInterface]
},
versionPromise: null,
dialectName: 'mysql',
pool: Pool {
log: false,
idleTimeoutMillis: 10000,
acquireTimeoutMillis: 60000,
reapIntervalMillis: 1000,
maxUsesPerResource: Infinity,
_factory: [Object],
_count: 0,
_draining: false,
_pendingAcquires: [],
_inUseObjects: [],
_availableObjects: [],
_removeIdleScheduled: false
},
lib: {
createConnection: [Function (anonymous)],
connect: [Function (anonymous)],
Connection: [class Connection extends EventEmitter],
createPool: [Function (anonymous)],
createPoolCluster: [Function (anonymous)],
createQuery: [Function: createQuery],
Pool: [class Pool extends EventEmitter],
createServer: [Function (anonymous)],
PoolConnection: [Function],
escape: [Function: escape],
escapeId: [Function: escapeId],
format: [Function: format],
raw: [Function: raw],
createConnectionPromise: [Getter],
createPoolPromise: [Getter],
createPoolClusterPromise: [Getter],
Types: [Getter],
Charsets: [Getter],
CharsetToEncoding: [Getter],
setMaxParserCache: [Function (anonymous)],
clearParserCache: [Function (anonymous)]
}
}
}
server start 3000
-> { } 를 쓰게되면 require안에 있는 models안 index.js 파일 가져오면 db를 가져오는데 그 결과값을 소문자sequelize만 가져오기 위해 { } sequelize {sequelize} 만 가져오겠다. 함축어
-----------------------------------------------------------------2교시---------------------------------------------------------
7. 사용해보기
db접속 test코드 작성
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능
sequelize.sync({force:false,}) //sequelize=객체 sync를 method로 사용해보기 -> console.log찍었던거에서 찾아보기
//sync 비동기 통신 사용할 때 sync()를 사용했었음. 얘 결과값 -> new Promise객체
//force -> 접속했을 때 테이블이 존재하냐, 안하냐에 따라 table을 새로 만들거야? 를 세팅해주는 부분
//force:false 생성하지 않음 / force:true 생성함
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
sequelize.sync{{force:false}}) -> new Promise 객체 =>.then(), .catch() 사용가능
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능
//sequelize=객체 sync를 method로 사용해보기 -> console.log찍었던거에서 찾아보기
//sync 비동기 통신 사용할 때 sync()를 사용했었음. 얘 결과값 -> new Promise객체
//force -> 접속했을 때 테이블이 존재하냐, 안하냐에 따라 table을 새로 만들거야? 를 세팅해주는 부분
//force:false 생성하지 않음 / force:true 생성함
sequelize.sync({force:false,})
.then(()=>{
console.log('db접속 성공')
})
.catch(()=>{
console.log('db접속 실패')
})
//여기서는 반환값을 만들어주지 않고 resolve가 호출되었을 떄
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
-> console.log - node app.js 입력
-> config 비밀번호 잘못입력해서 오류가 떴었음
-> 다시해보니 잘 작동함
orm 의 기능은 tables 생성까지 가능
8. models폴더 안 user.js파일 만들기 - 책 320p 내용 작성
sequelize db 접속까지 한 상태
sequelize - table생성, 수정, 삭제도 가능
user.js 작성
const Sequelize=require('sequelize'); //sequelize가져오기
module.exports=class User extends Sequelize.Model{ //class 던져주기
static init(sequelize){
//User라는 class에서 정적으로 사용하는 , 쉽게 말하면constructor
//처음 생성할 때 요기가 실행된다~
//User라는class가 객체 생성없이 바로 사용 가능하다~ 라는 뜻 / 모르겠다.
return super.init({
name:{ //name varchar(20) NOT NULL UNIQUE
type:Sequelize.STRING(20), //부모로부터 받아 Sequelize.STRING 이라고 적기
//== varchar(20)
allowNull:false, // == not null 무적권 이름은 null값이 있으면 안된다.
unique:true, // unique 사용하겠다 ~
},
age:{ // age라는 field를 만들거고 sql 구문 = age INT UNSIGNED NOT NULL
type:Sequelize.INTEGER.UNSIGNED, // 숫자만 사용할건데 양수만 사용할거야 + 값만
allowNull:false, // NOT NULL
},
married:{ // married TINYINT(1) NOT NULL
type:Sequelize.BOOLEAN, // tinyint 한자리수 정수 숫자 받는 뜻
allowNull:false, //not null
},
comment:{ /// comment TEXT NOT NULL
type:Sequelize.TEXT,
allowNull:true,
},
created_at:{ // created_at DATETIME NOT NULL default NOW()
type:Sequelize.DATE,
allowNull:false,
defaultValue:Sequelize.NOW,
},
},{
sequelize,// 사용할 때 인자값 내용 넣는거
timestamps:false,
underscored:false,
modelName:'User', // express에서 JS 사용하기위한 이름 설정
tableName:'users', // 실제 table 이름 요걸로 사용하겠다.
paranoid:false,
charset:'utf8', //
collate:'utf8_general_ci', //or utf8mb4쓰기
});
}
static associate(db){} // 아직은 사용안함
};
class test{
constructor(){
this.name="a"
}
}
console.log(test);
class test{
constructor(){
this.name="a"
}
}
console.log(new test);
class test{
constructor(){
this.name="a"
}
static init(){
this.age='20'
console.log('30')
}
}
console.log(test);
console.log(new test);
test.init() // 30 이 나옴
-> undefined는 무시!
static 설명 = 객체를 변환하지 않고도 바로 사용 가능
class test{
constructor(){
this.name="a"
}
init(){
console.log('29')
}
static init(){ //객체로 생성하고나서 사용할 경우 x
this.age='20' // class 생성하지않고도 바로 class method 안에 사용 가능
console.log('30')
}
}
console.log(test);
console.log(new test);
test.init();
let a = new test();
a.init();
요 부분 이해가 잘 안가서 연습하기 !
부모에 있는 method를 가져오는게 super
부모에 있는 init이라는 method를 가져오려고
super.init은 2가지의 객체를 받음
return super.init ( { 필드 내용 } , { 테이블에 대한 설정값 } )
index.js 파일에서 user.js 사용하기
index.js
'use strict'; //없어도 상관 없다.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize'); //Sequelize
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development'; //test할 때 development를 test로 바꿔
const config = require(__dirname + '/../config/config.json')[env]; // env 위에 정의되어 있음. 우리는env 설정안했음. 지금 env = development 값 / config는 요걸 가져옴
// config = config파일 안 development 의 객체 값이 된다.
const User=require('./user'); //models/index.js에서 user.js를 사용하기 위해 가져옴 result= class
//USer의 결과물은 CLASS
const db = {}; //빈 객체로 선언
let sequelize; //sequelize
if (config.use_env_variable) { // config에 use_env_variable이라는 정보가 있으면 ~
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else { //요게 우리가 실행될 것
sequelize = new Sequelize(config.database, config.username, config.password, config);//접속정보를 담은 객체
} // new = 함수가 객체로 변한다 / 결과적으로 요 값이 객체로 변하겠구나~ 알 수 있음. config 어디서 가져왓냐면 위에 8번줄
// development 객체 안의 내용을 내 db 내용과 같도록 정보 바꾸기
/* 여기는 일단 주석처리!
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
*/
db.User=User; //db라는 객체에 user라는 property를 만들어서 User를 넣음 / app.js에서 User라는 calss를 가져올 수 있도록
User.init(sequelize); // User라
//class User에서 바로 init 사용 (static으로 선언했기때문)
//sequelize = 접속 정보를 담은 객체 init의 첫번째 인자값으로 넣음
//user.js에가서 확인해봐
db.sequelize = sequelize; //sequelize, Sequelize 두가지 속성 값을 db에 넣었다.
db.Sequelize = Sequelize;
// db.associate(db);
module.exports = db; // db라는 변수를 결과적으로 넘기는구나
//db라는 파일을 불러왔을 때 객체로 받는구나 알 수 있음.
//팁 : 얘는 결국 무엇을 넘기나 아랫줄에 module을 쳌! 그거에 대한 결과값이 무엇인가 무언가를 담아서 보냈는가 를 쳌
user.js
const Sequelize=require('sequelize'); //sequelize가져오기
module.exports=class User extends Sequelize.Model{ //class 던져주기
static init(sequelize){
//User라는 class에서 정적으로 사용하는 , 쉽게 말하면constructor
//처음 생성할 때 요기가 실행된다~
//User라는class가 객체 생성없이 바로 사용 가능하다~ 라는 뜻 / 모르겠다.
return super.init({
name:{ //name varchar(20) NOT NULL UNIQUE
type:Sequelize.STRING(20), //부모로부터 받아 Sequelize.STRING 이라고 적기
//== varchar(20)
allowNull:false, // == not null 무적권 이름은 null값이 있으면 안된다.
unique:true, // unique 사용하겠다 ~
},
age:{ // age라는 field를 만들거고 sql 구문 = age INT UNSIGNED NOT NULL
type:Sequelize.INTEGER.UNSIGNED, // 숫자만 사용할건데 양수만 사용할거야 + 값만
allowNull:false, // NOT NULL
},
married:{ // married TINYINT(1) NOT NULL
type:Sequelize.BOOLEAN, // tinyint 한자리수 정수 숫자 받는 뜻
allowNull:false, //not null
},
comment:{ /// comment TEXT NOT NULL
type:Sequelize.TEXT,
allowNull:true,
},
created_at:{ // created_at DATETIME NOT NULL default NOW()
type:Sequelize.DATE,
allowNull:false,
defaultValue:Sequelize.NOW,
},
},{
sequelize,// 사용할 때 인자값 내용 넣는거 // 결국 config의 접속 정보를 받기위함
timestamps:false,
underscored:false,
modelName:'User', // express에서 JS 사용하기위한 이름 설정
tableName:'users', // 실제 table 이름 요걸로 사용하겠다.
paranoid:false,
charset:'utf8', //
collate:'utf8_general_ci', //or utf8mb4쓰기
});
}
static associate(db){} // 아직은 사용안함
};
app.js
수정 force : false -> true
sequelize.sync({force:true,})
->
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능
//sequelize=객체 sync를 method로 사용해보기 -> console.log찍었던거에서 찾아보기
//sync 비동기 통신 사용할 때 sync()를 사용했었음. 얘 결과값 -> new Promise객체
//force -> 접속했을 때 테이블이 존재하냐, 안하냐에 따라 table을 새로 만들거야? 를 세팅해주는 부분
//force:false 생성하지 않음 / force:true 생성함
sequelize.sync({force:true,}) //sequelize가 뭘 새로 만들겟다 모르겠음.
.then(()=>{
console.log('db접속 성공')
})
.catch(()=>{
console.log('db접속 실패')
})
//여기서는 반환값을 만들어주지 않고 resolve가 호출되었을 떄
app.get('/',(req,res)=>{
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
내용 잘 읽어보기
table을 생성하는 create문 만들어줌
-----------------------------------------------------------------------------------------------------------------------------------
9. create 작성해보기 책 page 329
table만들어놓은 상태라 요거 다시 false로 바꾸기
sequelize.sync({force:false,})
app.js 추가
app.get('/',(req,res)=>{
User.create({
name:'zero1',
age:'24',
married:false,
comment:'자기소개1',
})
res.send('hello world');
})
mysql에서 잘 들어갔는지 확인
??
-> get '/' 이어ㅣ서 localhost:3000 한번 들어갔다가 나와야 db가 나옴
sequelize 장점 : 셋팅하는데 오래걸리지만 if(error)~ 뭔가 복잡한게 없음.
셋팅(코드)이 길수록 사용하기 쉽고
셋팅이 짧을 수록 사용하기 어렵다고 함..
mvc 패턴 중 model 에 대한 부분.
무조건 orm은 필요하다 라고 하는 파가 있음.
---------------------------------------------------------------------------------------------------------------------------------
app.js
sequelize.sync({force:false,}) //sequelize가 뭘 새로 만들겟다 모르겠음.
.then(()=>{
console.log('db접속 성공')
})
.catch(()=>{
console.log('db접속 실패')
})
이 부분은 server접속 확인을 위한거라 삭제 ㄱㄱ
이제 select 해보기
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능 //model의 index를 가져옴
const {User}=require('./models')
app.get('/',(req,res)=>{
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
console.log(User.findAll({}));
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
-> server 키고 -> localhost:3000 하고
console.log 결과
결과 : promise 객체로 떨어짐.
이번엔 async & await 적어서 console.log 해보기
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능 //model의 index를 가져옴
const {User}=require('./models')
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
console.log(await User.findAll({}));
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
이걸 변수로 담아보기
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능 //model의 index를 가져옴
const {User}=require('./models')
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
const userList=await User.findAll({});
console.log(userList);
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
결과물은 배열로 줌.
User라는 객체에 dataValues가 있고
해당 결과의 배열 [0] 첫번째 객체의 name 값을 가져오기
console.log(userList[0].name);
User.findAll({}) -> 비동기이다. 를 알 수 있다. ( 결과치가 Promise 객체 값이기 때문)
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
const userList=await User.findAll({});
console.log(userList[0].name); //연습삼아 찍어봄
res.send('hello world');
})
User.findAll({}) 은 Promise 객체로 반환한다 ***
await 를 쓰려면 async 를 적어야함. User.findAll({}) 이 실해되기까지 기다리고 그 다음에 console.log가 실행되게
name, married만 뽑아오기
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
const userList=await User.findAll({
attributes:['name','married']
});
console.log(userList);
res.send('hello world');
})
이 외의 사용 스킬은 230-231p 책 보고 공부
----------------------------------------------지금까지 Model 부분만 했음 --------------------------------------------------
View, Controller
MVC 구조 할 수 있는걸 공부
VIEW - nunjucks의 활용, nunjucks를 쓰면 MVC 패턴 중 View부분
views 폴더, index.html 파일 추가
nunjucks 추가
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능 //model의 index를 가져옴
const {User}=require('./models')
const nunjucks = require('nunjucks');
nunjucks.configure('views',{
express:app,
})
app.set('view engine' , 'html');
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
/* insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})*/
//Select 문
const userList=await User.findAll({
attributes:['name','married']
});
console.log(userList);
res.send('hello world');
})
app.listen(3000,()=>{
console.log('server start 3000')
})
controller data 조작 router를 통해 코드를 분류할 뿐
routers 폴더 만들기, index.js 파일 추가
app.js에
app.use('/',indexRouter); 추가 ,
index.js에 router 사용 위해 express, router 코드 작성
어떤 폴더에는 고 내용에 대한 작업만 router 관리 파일을 만들꺼야
routers 폴더 안에 main 폴더 만들기 index.js 파일 만들기
router - index.js
const express=require('express');
const router=express.Router();
const mainRouter=require('./main/index.js')
// router.use('/',(req,res)=>{}) // = > 예전에 했던 방법
router.use('/',mainRouter);
module.exports=router; // router 보낼꺼야 저 멀리
router- main - index.js
const express=require('express');
const router = express.Router();
router.get('/', (req,res)=>{
res.render('index.html')
});
module.exports=router;
app.js
const express = require('express');
const app = express();
const {sequelize}=require('./models') //index생략가능 //model의 index를 가져옴
const {User}=require('./models')
const nunjucks = require('nunjucks');
const indexRouter = require('./routers')
nunjucks.configure('views',{
express:app,
})
app.set('view engine' , 'html');
app.use('/', indexRouter);
/*
app.get('/', async (req,res)=>{ //요 익명함수를 async로 해놓고
//insert문
User.create({ //User의 부모에 create를 가지고 있어서 사용 가능
name:'zero',
age:24,
married:false,
comment:'자기소개1',
})
//Select 문
const userList=await User.findAll({
attributes:['name','married']
});
console.log(userList);
res.send('hello world');
})*/
app.listen(3000,()=>{
console.log('server start 3000')
})
헷갈리는 파일들.................
여기까지 따라 쓰긴했는데 사실 잘 모르겠다
내일 쉬는 날이니까 열공해야겟다..
이제 business logic controller 부분을 또 나눌꺼야
routers - main - index
const express=require('express');
const router = express.Router();
const controller = require('./main.controller')
router.get('/',);
module.exports=router;
main 폴더에 main.controller.js 파일 만들기
main.controller.js
let main = (req,res)=>{
res.render('index.html');
}
exports.main=main;
// 보낼 명 , 보낼 함수
----------------> 여기까지 하면 db control 하는게 쉬워짐
main.controller.js
const {User} = require('../../models');
//비동기니깐 async await 쓰기
let main = async (req,res)=>{
let user = await User.findAll({})
console.log(user)
res.render('index.html');
}
exports.main=main;
// 보낼 명 , 보낼 함수
요렇게 적고 log 확인
하나만 사용해서는 왜 파일만 여러개 만드나 불편함
게시판 기준으로 파일 나누기
routers-> index.js 추가
const express=require('express');
const router=express.Router();
const mainRouter=require('./main/index');
const boardRouter=require('./board/index');
// router.use('/',(req,res)=>{}) // = > 예전에 했던 방법
router.use('/',mainRouter);
router.use('/board', boardRouter)
module.exports=router; // router 보낼꺼야 저 멀리
router안에 board 폴더 - 그 안에 index.js 파일 만들기
const express=require('express');
const router=express.Router();
const controller = require('./board.controller');
router.get('/list', controller.list);
router.get('/view', controller.view);
router.get('/write', controller.write);
router.get('/modify', controller.modify);
//routers-index에서 가져올 수 있게
module.exports = router;
/board/view
일때 실행되는 거 !
routers - board 폴더 안 새 파일 board.controller.js 만들기
let list = (req,res)=>{
res.render('list.html')
}
let view = (req,res)=>{
res.render('view.html')
}
let write = (req,res)=>{
res.render('write.html')
}
let modify = (req,res)=>{
res.render('modify.html')
}
module.exports={
list:list,
view:view,
modify:modify, //modify 라는 속성값을 modify 라는 method로
write:write
}
-> 이제 views 폴더 안에 list, ... 만들기
전체적인 흐름
routers-board-board.controller.js ㅇㅔ 이제 async, await 적용
const {User} = require('../../models')
//요걸 가져오면
let list = async (req,res)=>{
//select
let UserList = await User.findAll({})
res.render('list.html')
}
let view = (req,res)=>{
//select
let UserList = await User.findAll({})
res.render('view.html')
}
//board/write POST
let write = (req,res)=>{
//insert
let rst = await User.create({
//....req 요청값에 나왔던 부분을 넣어주면 됨
})
res.render('write.html')
}
let modify = (req,res)=>{
//update
let rst = await User.update({
//필드 : '바뀔내용'..
},{
where: { //필드:값} 이런 nunjucks의 결과를 떤져주면됨
})
res.render('modify.html')
}
module.exports={
list:list,
view:view,
modify:modify, //modify 라는 속성값을 modify 라는 method로
write:write
}
Controllers - model에서 받은 걸 조작해서 -> VIew로 보냄 (Model & View를 연결하는 곳)
Model - 데이터를 받고 저장 (DB에 있던 내용, 내가 사용할 DB를 객체로 저장하는 곳)
데이터를 저장한 객체 - 그 데이터만으로 모든걸 표현할 수 없다. 게시판의 paging etc. ->controllers 가 필요한 로직을 추가해서 View로 보낸다.
View - 화면에 뿌려주는 (실질적으로 Client가 보는 쪽)
최소한의 코드들만 따로 뽑아서 business logic 만 처리할 수 있게 만든게 Controller
* 팁 뭔가 데이터가 잘못된거같애 -> model 쪽 췤
뭔가 화면이 이상해 -> view 췤
paging이 이상해 -> controller 췤
내일 쉬는날 푹 쉬라고 숙제를 안내주셨다.
이제 숙제같은 복습이 남았다..