1. 7달 전

    36 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.78 ~ 2.80

  2. 7달 전

    35 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.75 ~ 2.77

  3. 7달 전

    34 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.70 ~ 2.74

  4. 7달 전

    33 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.68 ~ 2.69

  5. 7달 전

    32 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.66 ~ 2.67

  6. 7달 전

    31 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.61 ~ 2.65

  7. 7달 전

    30 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.57 ~ 2.60

  8. 7달 전

    29 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.54 ~ 2.56

  9. 7달 전

    28 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.51 ~ 2.53

  10. 7달 전

    27 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.46 ~ 2.50

  11. 7달 전

    26 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.44 ~ 2.45

  12. 8달 전

    25 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.41 ~ 2.43

  13. 8달 전

    24 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.39 ~ 2.40

  14. 8달 전

    23 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.36 ~ 2.38

  15. 8달 전

    22 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.31 ~ 2.35

  16. 8달 전

    21 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.22 ~ 2.25

  17. 8달 전

    20 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.22 ~ 2.25

  18. 8달 전

    19 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.18 ~ 2.21

  19. 8달 전

    18 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.13 ~ 2.17

  20. 8달 전

    17 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.7 ~ 2.12

  21. 9달 전

    16 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.0 ~ 2.6

  22. 9달 전

    15 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.81 ~ 1.87

  23. 9달 전

    14 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.76 ~ 1.80

  24. 9달 전

    13 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.72 ~ 1.75

  25. 9달 전

    12 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.64 ~ 1.71

  26. 9달 전

    11 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.60 ~ 1.63

  27. 9달 전

    10 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.56 ~ 1.59

  28. 9달 전

    9 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.49 ~ 1.55

  29. 9달 전

    8 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.40 ~ 1.48

  30. 9달 전

    7 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.34 ~ 1.38

  31. 9달 전

    6 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.26 ~ 1.32

  32. 10달 전

    5 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.22 ~ 1.25

  33. 10달 전

    4 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.17 ~ 1.21

  34. 10달 전

    3 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.12 ~ 1.16

  35. 10달 전

    2 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.8 ~ 1.11

  36. 10달 전

    1 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.1 ~ 1.7

Tamm자바스크립트 웹 개발 환경을 좋아하고 사람들에게 재미를 주는 것에 관심이 많은 개발자 입니다.

10 우버 클론 코딩 (nomad coders)

우버 코딩 강의 로그 1.56 ~ 1.59

featured image thumbnail for post 10 우버 클론 코딩 (nomad coders)

이 포스트는 nomad coders의 우버 클론 코딩 시리즈를 듣고 정리한 글 입니다.

https://academy.nomadcoders.co/p/nuber-fullstack-javascript-graphql-course

#1.56 UpdateMyProfile Resolver part One

#1.56 UpdateMyProfile Resolver part Two

유저의 정보를 업데이트 하는 type과 mutation을 작성하자

  • src/api/User/UpdateMyProfile/UpdateMyProfile.graphql

    type UpdateMyProfileResponse {
      ok: Boolean!
      error: String
    }
    
    type Mutation {
      UpdateMyProfile(
        firstName: String, 
        lastName: String, 
        email: String, 
        password: String, 
        profilePhoto: String, 
        age: Int,
        phoneNumber: String
      ): UpdateMyProfileResponse!
    }
    
  • src/api/User/UpdateMyProfile/UpdateMyProfile.resolvers.ts

    import { Resolvers } from "src/types/resolvers";
    import User from "../../../entities/User";
    import privateResolver from "../../../utils/privateResolver";
    
    const resolvers: Resolvers = {
      Mutation: {
        UpdateMyProfile: privateResolver(async (_, args, { req }) => {
            const user: User = req.user;
            const notNull = {};
            Object.keys(args).forEach(key => {
              if(args[key] !== null) {
                notNull[key] = args[key];
              }
            });
            try {
              await User.update({ id: user.id }, { ...notNull });
              return {
                ok: true,
                error: null
              }
            } catch (error) {
              return {
                ok: false,
                error: error.message
              }
            }
          }
        )
      }
    };
    
    export default resolvers;
    

동작을 바로 확인 해보자.

http://localhost:4000/playground 에서 다음의 쿼리를 날리자. 헤더에 유저 토큰을 포함하는 것을 잊지말자.

query {
  GetMyProfile {
    user {
      id
      fullName
    }
  }
}

잘 출력 되었다면

mutation {
  UpdateMyProfile(firstName: "dev") {
    ok
    error
  }
}

이름에 dev가 잘 찍인다. 유저 정보가 잘 업데이트 됐다.

#1.57.1 UpdateMyProfile Resolver Bug Fixing

니콜라스가 버그 픽스로 찍은 강의다. 이 강의는 매우 중요한 내용을 다룬다. 일단 코드를 보면 password에 대해 예외 처리하는 부분이 추가가 되었다.

  • src/api/User/UpdateMyProfile/UpdateMyProfile.resolvers.ts

    ...
            Object.keys(args).forEach(key => {
              if(args[key] !== null) {
                notNull[key] = args[key];
              }
            });
            
            if(notNull.hasOwnProperty('password')) {
              user.password = notNull['password'];
              user.save();
              delete notNull['password'];
            }
    
            try {
              await User.update({ id: user.id }, { ...notNull });
              return {
                ok: true,
                error: null
              }
    ...
    

이전에 User entity를 작성할 때 유저가 생성되거나 업데이트가 될 때 @BeforeInsert, @BeforeUpdate트기거를 달아준 것을 기억할 것이다.

 2019 04 23  9 0adaefe3 b685 498d aaaa 03052cbb8112 47 01

아래 코드는 저 트리거를 타지 않는다.

await User.update({ id: user.id }, { ...notNull });

업데이트 할 때 트리거를 타는 경우는 아래처럼 인스턴스로 업데이트 할 때다.

user.save()

그래서 추가된 코드를 보면 변경할 내용중 password가 있으면 password만 따로 저장하고 나머지 로직을 태우도록 했다. 이런 내용은 모르고 있으면 삽질하기 좋다.

여기서 드는 의문점.. 그냥 모든 데이터를 업데이트할 때 user.save()에서 해주면 되지 않을까???

#1.58 ToggleDrivingMode Resolver

사용자는 우버 앱을 켜서 근처에서 운행하는 차를 확인할 수 있다. 사용자는 드라이빙 모드로 전환해서 운행 정보를 주변에 알린다. 또 드라이빙 모드를 중단하면 이런 정보도 주변에 알려야 한다.

  • src/api/User/ToggleDrivingMode/ToggleDrivingMode.graphql

    type ToggleDrivingModeResponse {
      ok: Boolean!
      error: String
    }
    
    type Mutation {
      ToggleDrivingMode: ToggleDrivingModeResponse!
    }
    
  • src/api/User/ToggleDrivingMode/ToggleDrivingMode.resolvers.ts

    import { Resolvers } from "src/types/resolvers";
    import User from "../../../entities/User";
    import privateResolver from "../../../utils/privateResolver";
    
    const resolvers: Resolvers = {
      Mutation: {
        ToggleDrivingMode: privateResolver(async (_, __, { req }) => {
          const user: User = req.user;
          user.isDriving = !user.isDriving;
          user.save();
          return {
            ok: true,
            error: null
          }
        })
      }
    }
    
    export default resolvers;
    

#1.59 ReportMovement Resolver

이번엔 자신의 이동을 사용자에게 알리는 ReportMovement 의 type과 Mutation을 정의할텐데.

그전에 UpdateMyProfile에서 null값으로 들어온 args 를 제거 하여 다시 객체로 만든 코드를 util 함수로 만들자. 이 코드는 다른 곳에서도 사용되기 때문이다.

  • src/utils/cleanNullArgs.ts 파일을 생성해서

    const cleanNullArgs = (args: object) : object => {
      const notNull = {};
      Object.keys(args).forEach(key => {
        if(args[key] !== null) {
          notNull[key] = args[key];
        }
      });
      return notNull;
    }
    
    export default cleanNullArgs;
    
  • src/api/User/UpdateMyProfile/UpdateMyProfile.resolvers.ts

    import { Resolvers } from "src/types/resolvers";
    import cleanNullArgs from "../../../utils/cleanNullArgs";
    import privateResolver from "../../../utils/privateResolver";
    import User from "../../../entities/User";
    
    ...
    Mutation: {
        UpdateMyProfile: privateResolver(async (_, args, { req }) => {
            const user: User = req.user;
            const notNull: any = cleanNullArgs(args);
            if(notNull.password) {
              user.password = notNull.password;
              user.save();
              delete notNull.password;
            }
    ...
    

이제 ReportMovement의 type과 Mutation을 정의하자.

  • src/api/User/ReportMovement/ReportMovement.graphql

    type ReportMovementResponse {
      ok: Boolean!
      error: String
    }
    
    type Mutation {
      ReportMovement(
        orientation: Float
        lastLat: Float
        lastLng: Float
      ): ReportMovementResponse!
    }
    
  • src/api/User/ReportMovement/ReportMovement.resolvers.ts

    import { ReportMovementMutationArgs, ReportMovementResponse } from 'src/types/graph'; 
    import { Resolvers } from "src/types/resolvers"; 
    import User from "../../../entities/User"; 
    import cleanNullArgs from "../../../utils/cleanNullArgs"; 
    import privateResolver from "../../../utils/privateResolver"; 
    
    const resolvers: Resolvers = { 
      Mutation: { 
        ReportMovement: privateResolver(
          async (
            _, 
            args: ReportMovementMutationArgs, 
            { req }
          ): Promise<ReportMovementResponse> => { 
            const user: User = req.user; 
            const notNull = cleanNullArgs(args); 
            try { 
              await User.update({ id: user.id }, { ...notNull }); 
              return { 
                ok: true, 
                error: null 
              } 
            } catch (error) { 
              return { 
                ok: false, 
                error: error.message 
              }; 
            } 
          }
        ) 
      } 
    } 
          
    export default resolvers;