반응형

다음은 이 글의 동영상 강의 입니다.

https://youtu.be/u39nqCfjYx4

 

가장 기본적인 아이디 / 패스워드를 체크하는 수준의 로그인을 만들어 봅니다.

이전 글 회원가입의 소스는 아래 url을 통해 받으실 수 있습니다.

https://github.com/CodeGearGit/nest-register-sample

 

GitHub - CodeGearGit/nest-register-sample

Contribute to CodeGearGit/nest-register-sample development by creating an account on GitHub.

github.com

 

auth/auth.service.ts에 아래와 같이 로그인 체크 로직을 추가합니다.

async validateUser(user: UserDTO): Promise<UserDTO | undefined> {
    let userFind: UserDTO = await this.userService.findByFields({ 
        where: { username: user.username }
    });
    if(!userFind || user.password !== userFind.password) {
        throw new UnauthorizedException();
    }
    return userFind;
}

auth/auth.controller.ts에 라우팅 메소드를 추가합니다.

@Post('/login')
async login(@Body() userDTO: UserDTO): Promise<any> {
    return await this.authService.validateUser(userDTO);
}

Postman을 이용해서 아래와 같이 login 테스트를 합니다.

결과 값은 다음과 같습니다.

password를 '1234' 입력하면 결과는 다음과 같습니다.

 

이상으로 가장 기초적인 로그인 체크에 대해 알아보았습니다.

반응형
반응형

다음은 이 글의 동영상 강의 입니다.

https://youtu.be/4mjd5P7cZIA

https://youtu.be/NCqCfyQoNz8

 

Nest로 로그인 기능을 구현하기 위해 우선적으로 회원 가입을 만들어봅니다.

 

이 예제의 소스는 아래 사이트에서 받으실 수 있습니다.

https://github.com/CodeGearGit/nest-register-sample

 

GitHub - CodeGearGit/nest-register-sample

Contribute to CodeGearGit/nest-register-sample development by creating an account on GitHub.

github.com

 

USER 테이블의 구조는 다음과 같습니다.

auth 모듈을 만듭니다.

nest g module auth

auth/entity/user.entity.ts 를 만듭니다.

import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity('user')
export class User{
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    username: string;
    
    @Column()
    password: string;
}

auth/user.repository.ts 를 만듭니다.

import { EntityRepository, Repository } from "typeorm";
import { User } from "./entity/user.entity";

@EntityRepository(User)
export class UserRepository extends Repository<User>{}

auth/dto/user.dto.ts 를 만듭니다.

export class UserDTO {
    username: string;
    password: string;
}

auth/user.servict.ts 를만듭니다.

import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { FindOneOptions } from "typeorm";
import { UserDTO } from "./dto/user.dto";
import { UserRepository } from "./user.repository";

@Injectable()
export class UserService{
    constructor(@InjectRepository(UserRepository) private userRepository: UserRepository){}

    async findByFields(options: FindOneOptions<UserDTO>): Promise<UserDTO | undefined> {
        return await this.userRepository.findOne(options);
    }

    async save(userDTO: UserDTO): Promise<UserDTO | undefined> {
        return await this.userRepository.save(userDTO);
    }
}

auth/auth.service.ts 를 만듭니다.

(nest g service auth)

import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { UserDTO } from "./dto/user.dto";
import { UserService } from "./user.service";

@Injectable()
export class AuthService {
    constructor(
        private userService: UserService
    ){}

    async registerNewUser(newUser: UserDTO): Promise<UserDTO> {
        let userFind: UserDTO = await this.userService.findByFields({ where: { username: newUser.username } });
        if(userFind){
            throw new HttpException('Username already used!', HttpStatus.BAD_REQUEST);
        }
        return this.userService.save(newUser);
    }
}

auth/auth.controller.ts를 만듭니다.

(nest g controller auth)

import { Body, Controller, Post, Req } from "@nestjs/common";
import { Response, Request } from 'express';
import { AuthService } from "./auth.service";
import { UserDTO } from "./dto/user.dto";

@Controller('api')
export class AuthController {
    constructor(private authService: AuthService){}

    @Post('/register')
    async registerAccount(@Req() req: Request, @Body() userDTO: UserDTO): Promise<any> {
        return await this.authService.registerNewUser(userDTO);
    }
}

auth/auth.module.ts를 아래와 같이 수정합니다.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UserRepository } from './user.repository';
import { UserService } from './user.service';

@Module({
    imports: [TypeOrmModule.forFeature([UserRepository])],
    exports: [TypeOrmModule],
    controllers: [AuthController],
    providers: [AuthService, UserService]
  })
export class AuthModule {}

서버를 start 합니다.

npm run start:dev

postman에서 다음과 같이 테스트를 합니다.

POST http://localhost:3000/api/register
Body-raw-JSON
{
    "username": "codegear",
    "password": "1111"
}

실행 결과는 다음과 같습니다.

user 테이블에서도 다음과 같이 확인하실 수 있습니다.

 

반응형
반응형

이 글은 업데이트 되었습니다. 아래 링크를 참조하세요.

https://codegear.tistory.com/116

 

NestJS - 20. TypeORM (2023)

목차 TypeORM이란? NestJS에서 TypeORM 사용법 TypeORM이란? ORM은 Object-Relational Mapping의 약자입니다. 여기서 Object는 객체지향언어에서 말하는 객체를 의미합니다. Relational은 관계형 데이터베이스(Relational

codegear.tistory.com

----------------------------------------------------------

이 내용의 동영상 강의 2편입니다.

https://youtu.be/OTz22O8-PkE

https://youtu.be/t5XyFhe3sPA

 

Nest에서 db를 연결하여 개발을 진행해야할 경우, 좋은 선택지 중 하나가 TypeORM을 사용하는 것입니다.

 

TypeORM연결을 위해서는 DB가 설치 되어 있어야 합니다.

우리는 Docker를 이용해서 MySQL을 빠르게 설치하고 사용해보겠습니다.

MySQL 설치는 이전 글을 참고해 주세요.

https://codegear.tistory.com/66

 

MySQL 쉽게 설치하기 - with Docker

이 글의 동영상 강의입니다. https://youtu.be/5e0axgEP8EE 우선 아래 사이트에 가서 Docker를 설치합니다. https://www.docker.com/get-started Get Started with Docker | Docker Learn about the complete cont..

codegear.tistory.com

MySQL Workbench를 이용해서 test schema를 생성합니다.

CREATE SCHEMA test DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

 

이전까지 진행한 Nestjs 소스는 github에서 받으실 수 있습니다.

https://github.com/CodeGearGit/nest-cats

 

GitHub - CodeGearGit/nest-cats

Contribute to CodeGearGit/nest-cats development by creating an account on GitHub.

github.com

 

먼저 TypeORM을 설치합니다.

npm install --save @nestjs/typeorm typeorm mysql2

설치가 완료되면 app.module.ts에 TypeORM 모듈을 import 합니다.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [],
      synchronize: true,
    }),
    CatsModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

* 주의 synchronize: true는 운영에서는 사용하지 마세요. 

 

다음과 같이 cats/entity/cats.entity.ts 파일을 만듭니다.

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Cat {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  age: number;

  @Column()
  breed: string;

  @Column({ default: true })
  isActive: boolean;
}

app.module.ts에 cats.entity를 추가합니다.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';
import { Cat } from './cats/entity/cats.entity';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [Cat],
      synchronize: true,
    }),
    CatsModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

cats.module.ts에서 cats.entity를 사용하기 위해 다음과 같이 소스를 추가합니다.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { Cat } from './entity/cats.entity';

@Module({
  imports: [TypeOrmModule.forFeature([Cat])],
  exports: [TypeOrmModule],
  controllers: [CatsController],
  providers: [CatsService]
})
export class CatsModule {}

cats.service.ts에 catsRepository를 생성하여 data를 핸들링할 수 있게 합니다.

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Cat } from './entity/cats.entity';
import { getConnection } from "typeorm";

@Injectable()
export class CatsService {
    constructor(
        @InjectRepository(Cat)
        private catsRepository: Repository<Cat>,
      ) {}
    
      findAll(): Promise<Cat[]> {
        return this.catsRepository.find();
      }
    
      findOne(id: string): Promise<Cat> {
        return this.catsRepository.findOne(id);
      }

      async create(cat: Cat): Promise<void> {
        await this.catsRepository.save(cat);
      }
    
      async remove(id: number): Promise<void> {
        await this.catsRepository.delete(id);
      }

      async update(id: number, cat: Cat): Promise<void> {
        const existCat = await this.catsRepository.findOne(id);
        if(existCat){
            await getConnection()
                .createQueryBuilder()
                .update(Cat)
                .set({ 
                    name: cat.name, 
                    age: cat.age,
                    breed: cat.breed
                })
                .where("id = :id", { id })
                .execute();
        }
      }
}

cats.controller.ts를 다음과 같이 작성합니다.

import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './entity/cats.entity';

@Controller('cats')
export class CatsController {
    constructor(private catsService: CatsService){};

    @Get()
    findAll(): Promise<Cat[]> {
        return this.catsService.findAll();
    }

    @Get(':id')
    findOne(@Param('id')id: string): string {
        return `This action returns a #${id} cat`;
    }

    @Post()
    create(@Body() cat: Cat){
        return this.catsService.create(cat);
    }

    @Put(':id')
    update(@Param('id')id: number, @Body() cat: Cat){
        this.catsService.update(id, cat);
        return `This action updates a #${id} cat`;
    }

    @Delete(':id')
    remove(@Param('id')id: number){
        this.catsService.remove(id);
        return `This action removes a #${id} cat`;
    }
}

이제 Postman을 이용해서 테스트를 합니다.

POST를 이용해 데이터를 생성합니다.

GET으로 조회를 하면 다음과 같습니다.

다시 POST 로 추가 데이터를 입력합니다.

다시 GET으로 전체 데이터를 조회합니다.

수정, 삭제등도 테스트 하시면 됩니다.

 

반응형
반응형

이 글의 동영상 강의입니다.

https://youtu.be/5e0axgEP8EE

 

우선 아래 사이트에 가서 Docker를 설치합니다.

https://www.docker.com/get-started

 

Get Started with Docker | Docker

Learn about the complete container solution provided by Docker. Find information for developers, IT operations, and business executives.

www.docker.com

 

다음은 프로젝트 루트 폴더에 다음과 같이 docker-compose.yml을 생성합니다.

version: '3'
services:
  local-db:
    image: library/mysql:5.7
    container_name: local-db
    restart: always
    ports:
      - 13306:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      TZ: Asia/Seoul
    volumes:
      - ./db/mysql/data:/var/lib/mysql
      - ./db/mysql/init:/docker-entrypoint-initdb.d
    platform: linux/x86_64

 아래 스크립트를 실행합니다.

docker-compose up -d

설치가 완료되면 Docker Dashboard에 아래와 같이 mysql 이 추가됩니다.

우측의 start 버튼을 클릭하여 서버를 실행합니다.

MySQL Workbench를 이용해서 db에 접속합니다.

접속 정보는 다음과 같습니다.

 

이후로는 MySQL Schema와 사용자를 생성하시면 됩니다.

 

반응형
반응형

맥북에서 무료 FTP 프로그램을 찾아보던 중 CyberDuck이란 프로그램이 있어 설치를 해 보았습니다.

AppStore에는 유료 버전이 올라와 있기 때문에 아래 URL을 통해 설치하였습니다.

https://cyberduck.softonic.kr/mac/download

 

Cyberduck

우아하고 효율적인 무료 FTP 클라이언트

cyberduck.softonic.kr

 

설치 후 실행을 하면 다음과 같은 화면이 나옵니다.

여기서 상단의 새연결을 클릭하면 연결 설정을 할 수 있습니다.

제일 상단의 Selectbox를 클릭하면 접속 형태를 변경할 수 있습니다.

SFTP를 선택할 경우 아래와 같이  SSH 개인키를 설정하는 부분이 추가적으로 보입니다.

AWS의 경우 .pem 형식의 개인키를 지정하시면 됩니다.

완료된 후에 연결 버튼을 클릭하면 접속이 완료됩니다.

반응형

+ Recent posts