Wecode -Foundation 2 (부트캠프)/Layered Pattern 초입

Foundation 2- 좋은 코드란; 코드 분리

Queen Julia 2023. 9. 13. 10:43

깃허브가 아니라,

vscode에서 하는 것

 

 

app.js가 들어있는 폴더에, 

services라는 폴더를 만들고, 

1. 그 안에 userService 파일 만든다. 


이제 이  userService 파일 안에, 

1-1. 회원가입 함수를 넣을 건데, 

app.post("/users", async (req, res) => {
try {
// 1. user 정보를 frontend로부터 받는다. (프론트가 사용자 정보를 가지고, 요청을 보낸다)
const me = req.body;
console.log(me);

// 2. DATABASE 정보 저장.
const { password, email } = me; //구조분해할당 (위랑 같은 거)
// const password = req.body.password

// email, password가 다 입력되지 않은 경우
if (email === undefined || password === undefined) {
const error = new Error("KEY_ERROR");
error.statusCode = 400;
throw error;
}

// 이메일이 중복되어 이미 가입한 경우
// 1. 유저가 입력한 Email인 'shlee@wecode.co.kr'이 이미 우리 DB에 있는지 확인한다.
const existingUser = await myDataSource.query(`
SELECT id, email FROM users WHERE email='${email}';
`);

console.log("existing user:", existingUser); // existinguser:로 찍어봐라, 쿼리문으로 가져온 이메일로 한번 보자

// 2. 있으면, 즉, 이메일 중복이면 아래 if문 실행
if (existingUser.length > 0) {
// existing user 이용해서 판별`
const error = new Error("DUPLICATED_EMAIL_ADDRESS");
error.statusCode = 400;
throw error;
}

// 비밀번호가 너무 짧을 때
if (password.length < 8) {
const error = new Error("INVALID_PASSWORD");
error.statusCode = 400;
throw error;
}

//instert로 회원정보를 DB에 저장해라 (백엔드에는 저장되어 있음)
const userData = await myDataSource.query(`
INSERT INTO users (
name,
password,
email
)
VALUES (
'yj',
'${password}',
'${email}'
)
`);

//DB 저장 여부 확인
console.log("after insert into", userData);

// 회원가입 성공 // 성공 메세지를 프론트에게 보내라
return res.status(201).json({
message: "userCreated", 
});
} catch (error) {
console.log(error);
return res.status(error.statusCode).json({
message: error.message,
});
}
});

이 긴 회원가입 함수 중에서,

콜백함수를 옮길 거다. async가 열리는 { 부터 닫히는 }까지

 

 

userService폴더에

const signup = 를 치고, 

signup이라는 변수에, 회원가입 함수의 2번째 인자를 담아준다. 

=> 코드 분리. 

api 분리 (기능별)이다보니

 


1-2. 로그인 함수도, 

로그인을 완료하는 try catch 구문까지 다 옮기면 됨. 

 

userServices파일에 

const login = 

 

 

 

파일 봤을 때 어떤 파일이구나 알겠다는 것 

엄청 큰 프로젝트도 구역 구역 나뉜게

이해 쉽게 

이거는 아직 완성되지 않은 함수 /// 이후 과정 나옴 --> userService.를 붙여야 함

 

어떤 함수를 실행시킬지 연결만 시켜주고, 해당 함수는 servicesUser.js에서 써주는


[미리 보여주는 완성되면 보이는 함수]


그런데, 이게 마법이 아님.

함수 이름만 쓰다고 해서 다른 파일에서 연결 되는 게 아님.

그렇다면? 

export 이용! 


userServices 에서 만든 파일을, 

다른 파일에서 쓸 수 있게 해주는 것 =export 

 

 

ex.  엑셀 파일 2개 있을 때, 엑셀 파일 하나에서 만든 함수를 

다른 엑셀 파일에서 끌어다 쓰는 게 안 되는 거처럼 

--> export 해서 함수를 빼내주면, 

require해서 쓸 수 있는 것. 

 

 

require로 저 함수들을 가져와주는 것. 

 


파일을 module이라고 부름. 

 

module(파일)을 export 할 건데, 

==> module.export


 

"signUP" 함수를 signUp이라는 이름으로 내보내주고 (값을 함수로 내보내줘는 것) 

"logIn" 함수를 logIn이라는 이름으로 내보내주고 (값을 함수로 내보내줘는 것) 

이하 동일 

 

내보낼 함수를 사용할 파일  --> app3.js 여기에서 

userServices.js 라는 파일을 통째로 받아올 것

const userService = require ("./services/userService.js");

service라는 폴더가 있고, userService.js 라는 파일이 있는데, 

그 파일을 불러와서,

userService라는 이름을 쓸 거야 

 

그 파일 안이 객체들, 함수들을

userService라는 이름에 담겠다. 


한번에 보면, 

//module= 파일 , 파일은 exports (함수를 다른 곳에서 require로 끌어다 쓸 수 있게)

 

 

근데 나는 저장하면 이렇게 따옴표 없어지는데 괜찮은가?


 

그리고 app3.js에 있는, 변수로 만든 함수 이름들은,

userService.js의 module 객체의 

key 값임. 

 

 

함수 내보내는 파일: 객체를 통째로 내보내주는 것 

 

함수 사용할  파일: serviceUser.파일을 통째로 가져오는 것, 객체를 통채로 받아오는 것. 

 


console.log('signup function: ', signup) 

signup function을 찍어내면, signup이 defined 안 되는 이유(signup 함수가 정의된 적 없다)는, 

 

app3.js 의 const userService라는 변수 안에, 

그 안의 module 이라는 객체 안에,

그 안에 signup이 들어있는거지~ 

그렇기에, console.log('signup function: ', signup)이 아니라

console.log('signup function: ', userService.signup)이라고 찍어야 함. 

원래 동작 시키고 싶었던 signup 함수에 다 붙이면 됨 

 

 


[보완된 함수]


[datasource 관련 코드 이동] 1 

그런데 말입니다..

userService.js 파일에서 쓰고 있는 'myDataSource'가 

userService.js 파일에 변수 정의가 안 돼 있다! 

그렇기에, app.js의 myDatasource 코드를 가져가준다 

app.js에서는 더이상 안 쓰기에 아예 빼가는 것 (myDatasource를 쓰는 ,initialize portnumber코드까지 다 옮기는) 


근데 나의 경우엔, .env에 넣어두고, app.js에는 typeorm으로 빼놓아서,     ?????

typeorm은 app.js에 남겨두고, 

.env에 있던 것을 serviceUser.js에 넣어두어야 한다 

그렇기에 우리는 app3.js에서 끌어와야한다.  (require로 써도 되지만, 그대로 끌어다 써도 됨) 

 


계속 app.js에 뭐가 남았는지 스크롤 하며 보면서, 또 옮길 것을 파악


토큰 이동

jwt도 로그인에서 쓰이는 거, 

논리 1) app.js에서는 쓰이지 않으니, 옮겨줘야 하는 것이고. 

 

논리 2) 토큰은 로그인에 쓰이니

로그인함수 있는 곳으로 빼준 곳 ( =userService.js에)

 


[datasource 관련 코드 이동] 2 

const { DataSource } = require("typeorm"); 

1. 위와 같은 typeorm 코드와

2. 아래의 datasource 도 옮겼다. 

 

 

  • .env 파일에 환경변수를 빼지 않은 경우에는, userServices.js 에 dataSource 관련 코드를 바로 빼서 가져가면 되는데,
  • 나처럼, .env 파일에 환경변수를 담고, app.js에는 typeorm으로 썼을 경우에는  ?  

app.js 

const myDataSource = new DataSource({
type: process.env.TYPEORM_CONNECTION,
host: process.env.TYPEORM_HOST,
port: process.env.TYPEORM_PORT,
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
});

app.js에 있는 http, express 에 해당되는  아래 코드는 옮기기 않는다

const http = require("http");
const express = require("express");

 

 

3. 아래의 datasource 도 userService.js 로 옮겼다. 


정리 

코드 분리한 2개의 파일을 보면, 

  • app.js : 연결하고 싶은 함수 
  • userService.js: 내가 진짜 원하는 함수 

 


vscode가 자동으로 app.js의 함수가 어디에서 선언되었는지 알려줌 

--> command/ ctrl 누른채로 , 선언된 함수 누르면, 
       그 파일에 정의돼서 export 된 함수로 넘어감