728x90
반응형

전 포스트에서 NextJS 프론트에서 데이터를 요청하는것 까지 해보았다. 이번엔 백엔드를 설계해보자.

먼저 해당 포스트로 접속해 mongoose 까지 설치해준다.

 

https://typo.tistory.com/entry/Nestjs-MongoDB-Schema?category=895068 

 

Nest.js | MongoDB | Schema

이 글은 NestJS document 사이트 기반으로 작성했습니다. https://docs.nestjs.kr/techniques/mongodb 네스트JS 한국어 매뉴얼 사이트 네스트JS 한국, 네스트JS Korea 한국어 매뉴얼 docs.nestjs.kr 몽고DB설치하..

typo.tistory.com

 

- mongoose 설치

 

$ npm install --save @nestjs/mongoose mongoose

 

혹시 기존에 생성했던 apple 리소스가 있다면 삭제해준다.

app.module.ts 를 다음과 같이 수정한다.

 

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
  imports: [MongooseModule.forRoot('mongodb://test:test1234@localhost:27017/admin')],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

 

user 리소스를 생성해준다.

$ nest g res apple

 

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { UserModule } from './user/user.module';

@Module({
  imports: [MongooseModule.forRoot('mongodb://test:test1234@localhost:27017/admin'), UserModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

그럼 이렇게 파일들과 자동으로 import되는것을 볼 수 있다.

 

schemas 폴더를만들고 user.schema.ts 파일을 작성해준다.

 

/src/user/schemas/user.schemas.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type UserDocument = User & Document;

@Schema()
export class User {
  @Prop()
  id: string;
  
  @Prop()
  pw: string;
  
  @Prop()
  email: string;

  @Prop()
  address: string;
}

export const UserSchema = SchemaFactory.createForClass(User);

 

user.module.tsuserSchema에 관한 내용을 import해준다. 여기서 id부분은 자동으로 1씩 더해서 추가해주기위해 임의로 정의한 것이다.

 

user.module.ts

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { User, UserSchema } from './schemas/user.schema';

@Module({
  imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])],
  controllers: [UserController],
  providers: [UserService]
})
export class UserModule {}

 

우리는 일단 아이디 중복 확인을 위해 다음 @Get(':id') 데코레이터만 쓸 것이다. 우리는 사용자 id를 string으로 받을 것이기 때문에 수정해주자.

 

user.controller.ts

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.userService.findOne(id);
  }

 

service 부분에 mongoose schema를 추가한다.

 

user.service.ts

import { Injectable } from '@nestjs/common';
//mongoose
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { User, UserDocument } from './schemas/user.schema';
//dto
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UserService {
  constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}

  findOne(id: string) {
    return `This action returns a #${id} user`;
  }

}

 

 

findOne 함수를 async 함수로 바꿔주고( mongoose Query은 Promise 함수입니다. ) 지금은 중복확인으로 result 값만 필요하지만 나중에 로그인 할 때 이 함수를 써서 유저의 정보를 받아와야하기 때문에 id에 맞는 유저의 data가 존재할 때 user도 result와 함께 반환해준다.

 

user.service.ts

import { Injectable } from '@nestjs/common';
//mongoose
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { User, UserDocument } from './schemas/user.schema';
//dto
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UserService {
  constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}

  async findOne(id: string) {
    const userOne = await this.userModel.findOne({id});
    if(userOne)
      return {result : false, user : userOne}
    else
      return {result : true}
  }

}

 

 

이제 npm start dev로 백엔드를 실행하고 중복확인 버튼을 눌러보자.

 

 

 

정상적으로 중복확인 버튼이 disabled가 되었다.

728x90
반응형
728x90
반응형

 

SignupComponent 부분에 더 입력해야 될 값들을 추가해서 화면구성을 하자.

 

SignupComponent.tsx

import type { NextPage } from 'next'
import { UserState } from "../../store/interfaces/"
import { useDispatch, useSelector } from "react-redux";
import { actionTypesUser } from "../../store/interfaces/user/userAct.interfaces"
import { RootStateInterface } from "../../store/interfaces/RootState";

interface Props {
    userChangeHandler : (event : any) => void;
    userState : UserState;
}

const Signup:NextPage<Props> = ({userChangeHandler,userState}) => {
    const dispatch = useDispatch();
    const submitHandler = (event : any) => {
        event.preventDefault()
    }
    return (
        <div className="signup">
            <form onSubmit={submitHandler}>
                <div>
                    <input 
                        name="id"
                        type="text"
                        placeholder="Enter ID"
                        onChange={userChangeHandler} />
                    <button>
                    중복확인     
                    </button>
                </div>
                <div>
                    <input 
                        name="pw"
                        type="password"
                        placeholder="Enter PW"
                        onChange={userChangeHandler} />
                </div>
                <div>
                    <input 
                        name="pw2"
                        type="password"
                        placeholder="Verify password"/>
                </div>
                <div>
                    <input 
                        name="email"
                        type="email"
                        placeholder="Enter Email"
                        onChange={userChangeHandler} />
                    <button>
                    보내기    
                    </button>
                </div>
                <div>
                    <input 
                        name="address"
                        type="text"
                        placeholder="Enter Address"
                        onChange={userChangeHandler} />
                    <button>
                    주소검색    
                    </button>
                </div>
                <div className="signbutton">
                    <button
                        type="submit">
                    Signup       
                    </button>
                </div>
            </form>
        </div>
        )
}

export default Signup

 

 나중에 중복확인이 완료되고 id 입력칸을 비활성화로 만들어주기 위해 state를 만들어준다.

    //idDuple
    const [idDupleOK,setIdDupleOK] = useState<boolean>(false)

 

 

화면 부분도 바꿔준다.

<div>
    <input 
        name="id"
        type="text"
        placeholder="Enter ID"
        onChange={userChangeHandler}
        disabled={idDupleOK} />
    <button
    	type="button"
        onClick={IdDuplicate}
        disabled={userState.idDuple}
        >
    중복확인
    </button>
</div>

 

 

 화면으로 확인해보자.

 

 

참고로 기능위주로 구현하고 CSS는 나중에 다룰것이다. ( div에 className을 하나씩 추가한 이유 )

 

로그를 확인해보면 userState 값이 정상적으로 바뀌는것을 확인할 수 있다.

axios 모듈이 없으면 npm i axios 로 설치하면 된다.

id를 파라미터로 받아 백엔드에 GET 메소드로 데이터를 요청해 반환값을 전달하는 userIdDuplicate 함수를 작성했다.

 

이제 userAct.interfaceuser_reducer부분에 ID중복확인 부분을 추가해준다.

 

user.interface.ts

export enum actionTypesUser {
    USER_INIT = "USER_INIT", // state 초기화
    USER_STATE = "USER_STATE", // userState 변경
    USER_INFO = "USER_INFO",  // userInfo 변경 
    USER_ID_DUPLICATE = "USER_ID_DUPLICATE" // ID 중복 검사
}

export type ActionsUser = UserInit | UserState | UserInfo | UserIdDuplicate

export interface UserInit {
    type : actionTypesUser.USER_INIT;
    data : any;
}

export interface UserState {
    type : actionTypesUser.USER_STATE;
    data : any;
}

export interface UserInfo {
    type : actionTypesUser.USER_INFO;
    data : any;
}

export interface UserIdDuplicate {
    type : actionTypesUser.USER_ID_DUPLICATE;
    payload: any;
}

 

user_reducer.ts

        case actionTypesUser.USER_ID_DUPLICATE:
            return {
                ...state, data : action.payload
            }

 

ID중복확인을 위한 함수를 작성하기 전에 우리가 USER_STATE, USER_INFO 액트를 쓸 땐 백엔드(NestJS)와의 통신이 없어도 상관없었지만 ID 중복확인을 위한 과정에는 백엔드(NestJS)와의 통신이 필요하다.

 

때문에 dispatch에 사용될 Action을 정의할 것이다.

store 밑에 user_action.ts 파일을 생성한다.

/store/user_action.ts

import Axios from 'axios'
import { actionTypesUser } from '../interfaces'

export async function userIdDuplicate (id : string) {
    const request = Axios.get('/api/user/'+id)
    .then(response => response.data)
    
    return {
        type : actionTypesUser.USER_ID_DUPLICATE,
        payload: request
    }
}

 

이제 컴포넌트에서 dispatch로 axios의 결과값에 따른 로직을 만들어준다.

SignupComponent.tsx

import {userIdDuplicate} from '../../store/actions/user_action'

    (...)
    
    //idDuple
    const [idDupleOK,setIdDupleOK] = useState<boolean>(false)
    }
    const IdDuplicate = () => {
        if(userState.userInfo.id !=='') { // 입력된 값이 존재할 경우
            dispatch(userIdDuplicate(userState.userInfo.id)).then((req : any)=> {
                if(!req.payload.result) { // 아이디가 이미 존재할 때
                    alert('해당 아이디가 이미 존재합니다.');
                }else {
                    alert('중복된 아이디가 없습니다.');
                    dispatch({type : actionTypesUser.USER_STATE, data: ['idDuple',true]});
                    setIdDupleOK(true);
                }
            })
        }
    }
    
    (...)
    
    <input 
      name="id"
      type="text"
      placeholder="Enter ID"
      onChange={userChangeHandler}
      disabled={idDupleOK} />
    <button
      type="button"
      onClick={IdDuplicate}
      disabled={userState.idDuple}
    >
    중복확인     
    </button>
    
    (...)

 

  1. 만들어두었던 action을 가져온다.
  2. 버튼을 클릭할 경우 동작될 함수를 선언한다.
  3. 함수에선 dispatchdata에 입력한 ID를 전달한다.
  4. 반환값에 따라 조건문을 써준다. 만약 중복된 아이디가 없을 경우 UserStateidDuple값을 바꿔준다.

 

여기까지 중복확인 버튼을 눌렀을 때 dispatch로 백엔드에 데이터를 요청해서 원하는 값을 받아오고,

받아온 값에 따라 어떻게 처리할지 조건문으로 써주었다. 

 

다음 포스트에서는 백엔드(NestJS)를 구성해보겠다.

 

 

728x90
반응형

+ Recent posts