728x90

 


2024.11.22

_ 18:13

패키지 매니저 yarn v1 에서 pnpm으로 변경

https://springdream0406.tistory.com/230

 

yarn v1 => pnpm

변경 배경현재 진행중인 cmspp 프로젝트를 당장 끝내기는 힘들것 같아서 우선 데모 사이트를 배포하려고 생각했다.단지 당장 요금이 발생하는걸 막기 위해 NestJS 서버와 PostgreSQL을 Docker로 묶어서

springdream0406.tistory.com


2024.11.18

_ 14:01

테스트 코드 갈아 엎음..

https://springdream0406.tistory.com/227

 

Test Code 3 - 개선

https://springdream0406.tistory.com/224 Test Code 2통합테스트 코드를 작성해본 후, 대부분을 mock으로 처리해놓은 현재 유닛테스트에 대한 의문을 가지고 있던 중, https://tech.inflab.com/20230404-test-code/ 테스

springdream0406.tistory.com

 


2024.11.12

_ 15:04

회원탈퇴 softDelete를 Auth에서 User로 변경. 그에 따른 코드 변경과 테스트코드 수정, 회원 재가입에 대한 통합테스트 코드 작성


2024.11.11

_ 15:50

회원탈퇴 softDelete로 유지하고, Cron을 사용해서 탈퇴한지 7일 지난 회원을 매일 01:00에 삭제하도록 했으며, 이와 관련된하여 탈퇴회원 재가입 로직 추가하고,  수정/추가한 코드들의 유닛테스트를 작성했으며, Cron의 경우 실제 DB에서 잘 삭제되는지 테스트하기위해 통합 테스트 코드로 작성함.

cascade 때문에 고생함.

https://springdream0406.tistory.com/221

 

TypeORM CASCADE

현재 진행중인 프로젝트 CMSPP는 auth와 user테이블로 회원가입 정보와 유저정보가 분리되어있다.그리고 개인적으로 auth테이블의 정보가 조회되는걸 최소화하고 싶어서 auth에서 user로 단방향 관계

springdream0406.tistory.com

 

_ 08:54

유닛테스트와 e2e 테스트 작성 완료.


2024.11.08

_ 14:38

service에 너무 기본적인거 빼고 간단한 주석들 달아줌.

refreshToken 발급을 제외한 유닛테스트 코드 작성 완료.

"coveragePathIgnorePatterns": [
      "main.ts",
      "module.ts",
      "entity.ts",
      "dto.ts",
      "strategy.ts",
      "decorator.ts",
      "mockDatas.ts",
      "database.config.ts",
      "validation.schema.ts",
      "response-time.interceptor.ts"
    ]


2024.11.07

_ 20:29

myInfo 체크 후 없을 때 안내문 상세하게 변경.

등록 거절할 경우 안내하고 끝난거 메인페이지로 이동시켜서 이후에 데이터 등록가능한 경우를 차단함.


2024.11.02

_ 07:41

if문 중괄호 생략했던 코드들 중괄호 넣어줌.


2024.11.02

_ 07:41

if문 중괄호 생략했던 코드들 중괄호 넣어줌.


2024.11.01

_ 06:24

CustomAuth 코드를  commonService 만들어서 코드 기능별로 분리하고 가져와서 사용하게 바꿈.


2024.10.29

_ 18:42

controller req param 받는 대신 커스텀데코 param으로 변경하여 userId만 받음. 존재여부도 커스텀데코내에서 처리

 

구상 - 2024.10.18. _01:25 에 적어두었던 내용 (entity extends 하기) 적용

entity extends 하면서 id 통일되고 이에 따라 interface 변경, spp의 delete interface 통합

그에 따른 프론트 interface 변경 = 간소화됨.

 

db postgres로 변경

 

user entity에 role로 enum 추가하고, 회원가입시 enum 설정으로 user 테이블 만들어 연결하도록 변경


2024.10.29

_ 02:20

커스텀 가드를 만들어 전역 처리하고, accessToken과 refreshToken을 한번에 처리하도록 만듦

@Injectable()
export class CustomAuthGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
  ) {}
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // Public 데코 pass
    const isPublic = this.reflector.get(Public, context.getHandler());
    if (isPublic && isPublic !== 'refresh') return true;

    // 토큰과 타입 가져오기
    const req: Request = context.switchToHttp().getRequest();
    let token: string;

    if (isPublic === 'refresh') {
      const [auth, refreshToken] = req.headers.cookie?.split('=');
      if (!auth || auth != 'refreshToken' || !refreshToken) return false;
      token = refreshToken;
    } else {
      const [auth, accessToken] = req.headers.authorization?.split(' ');
      if (!auth || auth !== 'Bearer' || !accessToken) return false;
      token = accessToken;
    }

    // 토큰 검증, req에 user 넣기
    const secretKey =
      isPublic === 'refresh' ? envKeys.refreshTokenSecret : envKeys.accessTokenSecret;

    try {
      const playload = await this.jwtService.verifyAsync(token, {
        secret: this.configService.get<string>(secretKey),
      });
      req.user = { userNumber: playload.sub };
      return true;
    } catch (error) {
      //   if (error.name === 'TokenExpiredError')
      //     throw new UnauthorizedException('토큰이 만료되었습니다');
      throw new UnauthorizedException();
    }
  }
}

2024.10.28

_ 21:58

발전량에 맞춰서 rec 판매 수수료 추가,

rec 발급, rec 판매 수수료 tax에 반영


2024.10.22

_ 12:56

env 이름들 enum으로 만들어서 오타 줄이기 적용

 

_ 02:48

// 회원 추가
  async saveUser({ user }: IOAuthUser): Promise<Auth> {
    const queyRunner = this.dataSource.createQueryRunner();
    await queyRunner.connect();
    await queyRunner.startTransaction();
    try {
      const userData = await queyRunner.manager.save(User, { recWeight: 1.0 });
      const auth = await queyRunner.manager.save(Auth, {
        ...user,
        user: { userNumber: userData.userNumber },
      });
      await queyRunner.commitTransaction();
      return auth;
    } catch (error) {
      //   console.log(error);
      await queyRunner.rollbackTransaction();
      throw new InternalServerErrorException('회원 가입 실패(DB)');
    } finally {
      queyRunner.release();
    }
  }

기존에 회원가입시 쿼리러너로 Auth와 User에 데이터를 넣었던걸

 

  @OneToOne(() => User, {
    cascade: true,
  })
  @JoinColumn()
  user: User;
// 회원 추가
  async saveUser({ user }: IOAuthUser): Promise<Auth> {
    const auth = await this.authRepository.save({
      ...user,
      user: { kWh: 1.0 },
    });
    return auth;
  }

cascade 설정한 후, 한번에 만드는 방식으로 변경

 

_ 00:33

DB 환경변수 configModule로 변경, Joi로 환경변수 검사 추가


2024.10.21

_ 10:04

spp entity의 date들 @IsDateString()으로 변경

 

_ 04:43

Auth entity에 @Exclude() 설정


2024.10.18

_ 05:30

spp 데이터의 delete 요청 들어오는 것들 param 검증을 위해 @Param 들에게 ParseIntPipe 추가함.

@Delete('solar/:solarNumber')
  @UseGuards(AuthGuard('access'))
  deleteSolar(
    @Req() req: Request & IAuthUser,
    @Param('solarNumber', ParseIntPipe) solarNumber: number,
  ): Promise<Solar[]> {
    return this.sppService.deleteSolar({ ...req.user, solarNumber });
  }

2024.10.17

_ 07.52

이전 Nest강의를 듣고 적용했던 OneToMany, ManyToOne 관계를 코드팩토리에서 알려준 방식(공식문서 스타일)로 변경함.

 

User에 있던 JoinColumn을 Auth로 옮기고 단방향을 유지함으로서, User에서 Auth로 데이터 조회가 안되게하여 Auth의 독립성을 높였다.

또한, 회원 탈퇴를 하려면 UserNumber로 Auth의 데이터를 찾아야하는데, User에서 userNumber로 UID를 찾고, 이를 Auth에서 다시 검색해야 했던걸, Auth에서 관계 설정된 user의 userNumber를 바로 조회할 수 있어서, 2번 조회하던 걸 1번으로 줄였다.


2024.09.22 ~ 10.12

- 10.12

entity extends 사용해서 spp의 @PrimaryGeneratedColumn('increment')와 @CreateDateColumn()을 extends 함.

테이블 별로 pk의 이름을 다 다르게 했고, 구분을 위해서 그리고 프론트도 구분된 이름으로 받아서  처리하다보니 pk의 이름은 겹치지 않기위해 @PrimaryGeneratedColumn('increment')를 빼다보니 @CreateDateColumn() 만을 위해서 extends할 필요 없고, 직관성을 위해 다시 되돌림.


- 10.10

총합 추가


- 09.26

// 데이터 보내기 체크
  static sendDataCheck(inputs: ISendDataRefInputs[]): boolean {
    let isOk = true;
    for (let input of inputs) {
      // 빈값 체크
      if (!input.ref.current || !input.ref.current.value) {
        alert(`${input.name}을(를) 입력해주세요.`);
        isOk = false;
        break;
      }
      // 숫자데이터 인지 체크
      const numberValue = Number(input.ref.current.value);
      if (isNaN(numberValue)) continue; // 문자라면 건너띄기
      // 0 미만 체크
      if (numberValue < 0) {
        alert(`${input.name}이(가) 0 미만입니다.`);
        isOk = false;
        break;
      }
    }
    return isOk;
  }

프론트에 input 값 0 미만 체크 코드 추가

 

@Column({ type: 'varchar', length: 10 })
  @IsNotEmpty()
  @IsString()
  date: string;

  @Column()
  @IsNotEmpty()
  @IsNumber()
  @Min(0)
  sVolume: number;

백에 프론트에서 오는 데이터 검증(빈값/0이상) 체크

spp와 관련된 date는 string으로 통일


- 09.23

가독성을 위해 분기별 데이터에 배경색을 넣음.

특별한 상황 빼고는 중복되는 발전량 x SMP 데이터를 보여주는 항목에서 제거 (비교는 계속하고 값 다르면 빨간 배경 기능 역시 유지).

input칸 위에 어떤 값인지 표시해주는거 추가함.


- 09.22

날짜 데이터 년,월 or 년,월,일 따로따로 저장하던거 년-월 or 년-월-일 한번에 저장하는 식으로 바꿈.

덕분에 프론트에서 년-월-일 로 오는 데이터 분리하는 코드, 따로따로 저장되는 DB 없어짐.

백에는 년,월,일로 분리된 데이터를 주다보니 프론트에서 보내는 데이터와 받는 데이터의 양식이 달라서 처리해야되는 것들 없어짐.


2024.09.11

_16:53

일단 get,post로만 동작하던 api를 put, delete 추가해서 변경했다.

변경 중간에 number 없이 삭제했다가 내용 전부가 삭제되는걸 보고, 쿼리러너 사용해서 affected !== 1 에 대한 체크하고 롤백 넣을까 했는데, 그러기에는 코드가 너무 길어지고 해서 삭제시도전에 요청에 number가 있는지 체크하는걸로 처리했다.


2024.07.12

_16:34

일단 태양광, rec발급/판매까지 끝냈다.

실제 과거 데이터 넣어보고 데이터 비교해보면서 이상있나 체크해보았다.

사업자번호의 경우 처음 가볍게 알아보았을 때는 사업자번호로 주소까지 조회가 되는 사이트를 보고 나도 사업자번호로 주소까지 체크한다음에 이를 다른발전소 조회할 때 사용하면 되겠다 싶었는데, 실제로 사업자번호로 제공하는 공공데이터는 사업자번호가 유효한지 체크해주는 정도까지다..

사업자번호로 주소까지 조회되는 사이트는 해당 사업을 신청하고 해서 받는다는 내용이 검색내용에 있던데 확실하진 않다..

무튼 그래서 사업자번호는 유효한지, db중복못하도록 유니크 걸어두고, 지역은 등록자의 양심에 맡기도록 해야한다..

지역의 경우 https://www.laiis.go.kr/lips/mlo/wco/wholeCountryList.do

 

내고장알리미

행정구역 현황 대한민국의 현재 행정구역 현황을 확인할 수 있습니다.

www.laiis.go.kr

위 사이트에 나오는 행정구역들로 리스트를 만들어서 넣었다.

DB의 경우 기존 user 테이블의 uid로 다른 테이블과 연관 시키던것을 user 테이블의 pk로, 변경했다.


2024.07.08

_01:29

년도 선택을 하나로 통합하고, 년도가 많아지면 전체 보기가 밑으로 많이 밀릴것 같기도하고, 년도 배열에 string 넣으니 복잡해져서 따로 뻈다.

데이터들의 년도를 추려서 보여주기 때문에, 년도에 맞는 데이터 필터링을 해당 컴포넌트에서 실행해서 뿌려주는 식으로 바꿨다.

REC 발급은 태양광 발전량에 비례하기 때문에 태양광 데이터에 따라 자동으로 계산되어 뜨도록 변경, 차기이월분 계산처리하는것 때문에 고생좀 했지만 잘 구현되었다. 단지 걱정은 차기이월이 누적되어서 발급량에 영향을 끼치는 데이터다보니 입력하는 사람이 태양광 데이터를 전부 입력안하면 REC발급 쪽의 데이터가 계속 미세하게 안맞을 것이라는 것이다.


2024.07.05

_12:46

태양광 부분 작업을 완료했다.

우선 내발전소로 들어올 때 태양광, REC, 지출이 합쳐진 데이터를 받아와서 보여준다.

현재는 모든 데이터를 처음부터 띄우는건 나중에 데이터가 쌓였을 때 보기 불편하다 판단하여, 처음에는 가장 최근년의 데이터만 띄우도록 해놓았다.

 

추가하기 기능으로 년-월, 발전량, SMP, 공급가액을 입력하고 추가하기를 누르면(빈값 front에서 먼저 검증), 서버에 데이터를 저장하고, 태양광 값만 리턴 받아서 태양광 부분만 업데이트하여 보여준다.

 

태양광 옆에는 년도를 선택할 수 있는 select가 있는데, 받아온 데이터의 년도들을 넣어준다.

근데 이게 좀 문제가 되는게, 데이터가 업데이트 되면, 다른걸 선택하고 있었더라도 제일 최근의 년도로 text가 바뀐다.

이는 데이터가 업데이트 되면서 년도 데이터가 바뀌기 때문인데, 이를 해결하기가 좀 어렵다. 일단 문제는 앞서 말한대로 예를 들어 전체가 선택된 상태에서 데이터를 추가하게 되면 태양광 데이터가 업데이트 되면서 데이터에 있는 년도들도 갱신되게 된다. 근데 이게 필요한게 만약 2024년 데이터가 한개 있고 이를 삭제해버리면 2024년의 데이터는 없으므로 해당 년도 역시 없어져야 하기 때문이다.

 

이부분에 대해서는 좀 생각을 해봐야할듯 싶다.


2024.06.20

_18:25

구상에 글을 쓰고 오래걸렸네..

일단 바로 시작을 안하기도 했고, 소셜로그인기능 만들어야지 라고만 생각했었는데 일반 회원가입 기능도 넣을건지 고민하고, 강의와 다르게 구글을 제외하면 이메일 주소를 주지 않아서 id로 변경하고 기타 서비스 흐름도 생각하고 이것저것 생각하고, 엑세스토큰이랑 리프래시토큰 사용하는거 구현하고 하다보니 오래걸렸다.

우선 소셜 회원가입/로그인, 로그아웃, 회월탈퇴, ERD 등 작성하고 기본적인 흐름도는 구상해둔 상태이다.

 

728x90

'Projects > CMSPP(CM Solar Power Plant)' 카테고리의 다른 글

4. 오류/에러  (2) 2024.11.18
2. 구상  (5) 2024.11.11
1. 발상  (0) 2024.06.10

+ Recent posts