-
2019-09-18 개발일지개발일지 2019. 9. 18. 15:36
오늘은 이슈 수정과 시퀄라이즈-타입스크립트 개인 공부를 하고 있다.
[이슈리스트]
- 공지사항 목록 응답 객체에 댓글 갯수 값 누락 이슈
- 게시판 목록 오늘 등록한 게시글 시간 표현이 HH:MM 문자로 표현되는 문제
①
어제 이슈 수정 전에는 잘 줬다고 하는거 보니 내가 수정 사항 반영하다가 지워버린거 같다. -_-
exports.list = async (req, res) => { try { const notices = await Model.findAndCountAll({ subQuery: false, attributes: [ ..., [ sequelize.literal('(SELECT COUNT(no) FROM comment_table WHERE "parentId" = parent.id)'), 'commentCount' ] ], order: [ [ 'no', 'DESC' ] ], }); const response = []; notices.rows.forEach(row => { response.push({ ... commentCount: row.getDataValue('commentCount'); }); }); ... } catch (error) { ... } }
literal()을 통해 서브쿼리로 조회했는데 forEach()로 가공할 때 누락되었다.
②
어제 작성한 코드에서 dateformat 적용이 누락되어 발생했다.
const dateFormat = require('dateformat'); exports.boardList = (req, res) => { ... date.forEach(row => { ... const viewDate = writeDate === thisDate ? dateFormat(row.getDataValue('date'), 'HH:MM') : writeDate; }); });
위 문제들을 해결하고 sequelize-typescript 패키지 사용법을 익히고 있는데 TS의 강력한 타입체킹 때문에 꽤 답답하다.
모델을 만들고 해당 모델을 export해서 controller에서 사용하려고 했는데 모델에 정의한 모든 필드에 다음과 같은 에러가 발생했다.
Property 'fieldname' has no initializer and is not definitely assigned in the constructor.
필드에 대해서 생성자에서 초기화를 하라는 내용이다.
아니 모델링인데 생성자를 만들고 초기화를 하라니 뭔 소리야...
처음 보는 에러라 검색도 해봤는데 tsconfig.json에 "strictPropertyInitialization" 옵션을 false로 설정하라는 것 이었다.
해당 속성은 속성 초기화에 대한 강력한 체킹을 하는 옵션인데, 요거를 false를 설정하면 모든 class에 대해 강력 체킹이 해제가 되니 이건 쓰지 않기로 했다.
결국 핸드북을 찾아보고 타입 단언 (Type Assertions)를 이용했다.
import { Model, Table, Column, PrimaryKey, AutoIncrement, Comment, AllowNull, Default, DataType, Is, Unique, DeleteAt } from 'sequelize-typescript' import CustomError from 'CustomError'; @Table({ timestamps: true, freezeTableName: true, underscored: true }) export default class User extends Model<User> { @PrimaryKey @AutoIncrement @Column(DataType.BIGINT) id!: number; @Unique @Comment('사용자 아이디') @Column userId!: string; @Is('pwValidate', v => { if (v && v.length < 8) { throw new CustomError(5); } else if (v && v.length > 12) { throw new CustomError(6); } }) @Comment('사용자 패스워드') @Column userPw!: string; @AllowNull @Comment('이전에 사용하던 패스워드') @Column beforePw!: string; @Unique @Is('emailValidate', v => { const emailReg = /^[0-9a-zA-Z]*@[0-9a-zA-Z]*\.[a-zA-Z]{2,3}$/; if (v && !emailReg.test(v)) { throw new CustomError(7); } }) @Comment('사용자 이메일') @Column userEmail!: string; @DeletedAt deleteAt!: Date; }
참고: https://typescript-kr.github.io/pages/Advanced%20Types.html
그리고 정의한 모델은 그냥 사용하는게 아니라 sequelize-typescript의 Sequelize 객체를 생성할 때 사용 선언을 해줘야한다.
import { Sequelize } from 'sequelize-typescript'; import config from './config'; import { Dialect } from 'sequelize/types'; import pg from 'pg'; import path from path; class PGSequelize { pgs: Sequelize; constructor() { this.pgs = new Sequelize({ database: config.db.database, username: config.db.username, password: config.db.password, host: config.db.host, port: config.db.port, dialect: config.db.dialect as Dialect, models: [path.join(__dirname + '/../app/models')] }); } }
models 속성에 정의한 모델의 위치를 지정해주면 Sequelize 객체가 생성될 때 모델들을 모두 읽어들인다.
참고: https://www.npmjs.com/package/sequelize-typescript#usage
정의한 모델을 controller에서 아래와 같이 import하고 사용할 수 있다.
import User from '/models/userModel'; export function syncTest( req: express.Request, res: express.Response ): express.Response { User.sync(); ... } export async function saveTest( req: express.Request, res: express.Response ): Promise<express.Response> { try { const user = User.build({ userId: 'hong', userPw: '12345678', userEmail: 'hong@gmail.com' }); await user.save(); ... } catch (error) { ... } } export async function findAndDestroyTest( req: express.Request, res: express.Response ): Promise<express.Response> { try { const user = await User.findByPk(1); if (user) { await user.destroy(); } ... } catch (error) { ... } }
'개발일지' 카테고리의 다른 글
2019-09-20 개발일지 (0) 2019.09.20 2019-09-19 개발일지 (0) 2019.09.19 2019-09-17 개발일지 (0) 2019.09.17 2019-09-16 개발일지 (0) 2019.09.16 2019-09-11 개발일지 (0) 2019.09.11