아하 REST API 서버 개발 (7)

finallee
aha.official
Published in
8 min readJan 25, 2019

USER 모델 확장

자 이번 강좌는 저번 강좌에서 생성된 ordered UUIDuser 모델에 적용시키는 것으로 시작하겠습니다.

이렇게 Binary(16) 형식의 uuid 를 하나 붙여줄 건데요 migration 을 추가해보도록 합시다.

sequelize migration:generate --name add-uuid-to-users

마이그레이션을 추가하신 다음에는 src/models/user.model.js 를 아래와 같이 수정해주도록 합시다.

잘 보시면 uuiddefaultValueuuid() 로 부터 생성된 hex 문자열을 Byte Buffer 로 변환시켜서 넣는 걸 확인하실 수 있습니다. 이는 곧 mysql 에서 unhex() 하는 것과 같은 결과를 낳습니다.

그럼 이제 user.model이 잘 작동하는지 확인을 해봐야겠죠?

src/tests/functions/uuid.test.js

npm test 명령어를 입력하시기 전에, 매 테스트가 깔끔하게 진행될 수 있도록 package.json 의 스크립트 부분을 조금 추가하도록 하겠습니다.

수정한 내용은 매번 테스트마다 DB 를 날려줌으로써, 새로운 테스트에 생길 수 있는 여러가지 문제들을 차단하는 것입니다.

npm test

우후~ 아무런 문제 없이 잘 동작하고 있습니다!

그럼 이제 우리는 원하는대로 클라이언트에게 공개하는 user 의 정보는 uuid 로 대체하고 내부적으로 user 를 다룰때는 id 로 처리할 수 있게 되었습니다.

GET: /v1/users/:uuid?

자 이제 기존 사용자를 조회하는 라우트를 조금 수정하여 uuid 값을 주었을때는 해당 uuid 의 사용자를, 명시하지 않았을 경우에는 모든 사용자를 불러오게 확장해보도록 하겠습니다.

저번 강좌부터 말씀드렸지만 실제 서비스를 위한 개발은 테스트 기반으로 개발을 하셔야 합니다.

일단 무조건 테스트 파일부터 작성하도록 합시다.

강좌의 특성상 모든 테스트를 커버하지 못하고 함수와 통합 테스트만을 진행하겠습니다. (사실 두개 만으로도 충분합니다.)

통합 테스트를 진행하기 위해서는 supertest 모듈을 설치하셔야 합니다.

npm install --save-dev supertest

/src/tests/integrations/v1/users.test.js

/src/routes/v1/users.route.js

/src/controllers/v1/user.controller.js

npm test

요오시~! 일단 사용자 조회하는 라우트를 테스트하는데 성공하였습니다. 사실 테스트를 굉장히 간략하게 작성 하였지만, 실제로는 저것보다는 조금 더 상세하게 테스트를 진행하시는게 좋습니다.

얼마나 상세하게 작성 하실지는 자유지만 테스트가 상세하면 상세할 수록 code coverage 가 올라가고, 그로 인해 예측하지 못했던 버그 및 에러들을 제거할 수 있으니 최소한 모든 code coverage90% 이상 유지해주시는 것이 좋습니다.

User Repository

저는 좋은 코드는 single responsibility principle 을 지키는 코드라고 생각합니다.

가끔 controller 에서 요청을 받아서 DB 에 직접 CRUD 를 한 후, 데이터를 가공하고 응답까지 주는 종합 선물 세트 같은 코드들을 볼 수 있습니다.

저는 이런 코드들이 잘못됐다고는 생각하지 않습니다만, 과연 하루에도 많게는 수십번씩 뜯어 고쳐야하는 실제 서비스들의 코드들에 적용한다면 유지 보수면에서 얼마나 끔찍할까를 생각하곤 합니다.

다시 말씀드리지만 이것은 오로지 개인적인 견해 차이이므로 마음에 들지 않으시는 분들은 따라하지 않으셔도 됩니다!

자 그럼 실제 모델의 CRUD 를 담당하는 레포지토리를 만들어 보도록 합시다.

일단 레포지토리를 작업하기 전에 src/models/index.js 파일의 마지막 부분을 아래와 같이 변경해 줍시다.

export default models

그리고 소스내에 존재하는 import { models } from ‘…’import models from 으로 변경해 주도록 합시다.

src/repositories/user.repository.js

그리고 src/controllers/v1/user.controller.js 에서 repository 를 사용하도록 변경하겠습니다.

변경 후 어김없이 테스트 진행합시다.

처음에 테스트를 작성하고 테스트를 통해서 개발하는것은 매우 귀찮고 어려운 일일지 모릅니다. 하지만 한번 테스트 잘 작성해 둔다면 코드를 변경하고 버그가 생길까, 에러가 생길까 두려움에 떨지 않아도 된다는 아주 큰 장점이 있습니다.

User Response

자 이제 실제로 사용자에 대한 응답이 어떻게 오는지 response.body 객체를 console.log 로 잠시 보도록 하겠습니다.

{
uuid: '4678784951e9d0fbb5ff3dc094a79f53',
id: 3,
email: '6vgpDnJg@test.com',
password: 'WhFQJFta',
createdAt: '2019-01-25T09:39:55.000Z',
updatedAt: '2019-01-25T09:39:55.000Z'
}

우리가 이 고생을 하며 uuid 를 사용자 테이블에 넣은 이유는 외부에 id 를 숨기기 위해서라고 말씀을 드렸습니다.

그리고 어떠한 상황에서도 password 는 외부에 노출되면 안되는 필드입니다. 따라서 이 부분을 숨겨주도록 하겠습니다.

sequelize 객체는 보통 toJSON() 함수가 이미 내장되어 모든 필드를 json 형태로 출력하도록 만들어져 있습니다. 다만 이렇다보니 원하지 않는 녀석들도 같이 따라올때가 많은데요, 이걸 숨기기 위해서는 sequelize 객체에 조금의 수정을 가해줘야 합니다.

src/models/user.model.js

맨 마지막에 toWeb() 이라는 함수를 지정해 줘서 idpassword 를 직접 제거해줘야 합니다.

그리고 src/controllers/v1/user.controller.js 를 아래와 같이 수정해 주는거죠!

자 그럼 response 가 어떻게 오는지 확인을 해보겠습니다.

{
uuid: '4830f7e01ce3c602b5c022bbb72b6894',
email: '8Yo530AY@test.com',
createdAt: '2019-01-25T09:55:47.000Z',
updatedAt: '2019-01-25T09:55:47.000Z'
}
크으…지려따

User Password

오늘 강좌를 마치기 전에 마지막으로 하나 더 해야 할 것이 있습니다.

바로 사용자의 비밀번호를 관리하는 일인데요. 현재 DB 에 데이터들이 어떻게 들어있는지 한번 확인을 해보도록 하겠습니다.

자세히 보시면 password 부분이 암호화된 것처럼 보이지만 random-string 모듈로 생성된 문자열이 평문으로 저장 되어있는 것입니다.

따라서 사용자가 생성 되었을때, 단방향 암호화가 가능한 bcrypt 모듈로 생성되는 암호가 생성되는 로직을 추가하여야 합니다.

npm i bcrypt

src/models/user.model.js

beforeSave 훅을 통해서 앞으로 password 필드가 변경되면 암호화되어 저장되게 되었습니다. 그러면 DB 필드를 한번 볼까요?

딱봐도 비밀번호가 암호화 된 것 처럼 보입니다.

자 오늘은 강좌가 꽤나 길었는데요, 다들 고생하셨고 다음 강좌에서는 JWT 를 이용한 사용자 인증에 대해서 다뤄볼까 합니다.

--

--