[프로그래머스] 백엔드기초(9)

Lina Hongbi Ko·2024년 9월 9일
0

Programmers_BootCamp

목록 보기
18/76
post-thumbnail

2024년 9월 9일

✏️ 로그인

📍 로그인 기본 로직

  • 정보 조회를 위해 GET HTTP메서드를 쓰면 id, pwd가 노출되기 때문에 POST를 선택해야함
app.post('/login', function(req, res) {
	console.log(req.body) // userId, pwd
	// userId가 DB에 저장된 회원인지 확인해봐야함
	// pwd도 맞는지 비교해야함
	
	const { userId } = req.body;
	db.forEach((user, id)=> {
		console.log(user.userId);
	})
})

POSTMAN) POST + lcalhost:7777/join 에 user 3개 등록 시키고나서, POST + localhost:7777/login


{}는 req.body에 빈 값을 보내서 나온 결과임!

  • 이제, userId가 DB에 저장된 데이터와 맞는지 확인해보자
app.post('/login', function(req, res) {
	console.log(req.body);
	
	const { userId } = req.body;
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			console.log('userId 같음')
		}
	})
})

한 명 가입 시키고 → POSTMAN) POST + localhost:7777/login + (raw body) { ”userId” : “userId1”, "password" : 1234, "name" : "user1" }

  • 그 다음, pwd도 비교해보자
app post('/login', function(req, res) {
	console.log(req.body);
	
	const { userId, password } = req.body;
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			console.log('userId 같음')
			
			// pwd 확인
			if(user.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
		}
	})
})

한명 가입시키고 → POSTMAN) POST + localhost:7777/login + (raw body) { ”userId” : “userId1”, “password” : 1234} 입력 후 확인 하고, 다시 틀린 비밀번호(문자열) { ”userId” : “userId1”, “password” : "1234"} 보내보기

📍 로그인 예외 처리

: userId가 다를 때 예외 처리하기

app.post('/login', function(req, res) {
	console.log(req.body);
	const { userId, password } = req.body;
    
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			console.log('userId 같음')
			if(user.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
		} else {
			console.log("같은 아이디가 없음");
		}
	})
})

그러나, 위처럼 코드를 작성하면 forEach 안에 if문이 있기 때문에, 데이터를 계속 하나하나 돌아가면서 확인한다. 한번에 찾으면 끝나도록 하는게 성능에 더 좋기 때문에 바꿔보자.

app.post('/login', function(req, res) {
	console.log(req.body);
	
	let hasUserId = false;
	
	const { userId, password } = req.body;
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			console.log('userId 같음')
			hasUserId = true;
			
			// pwd 확인
			if(user.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
		} else {
			console.log("같은 아이디가 없음");
		}
	})
	
	// 만약 userId 값을 못찾았으면
	if(!hasUserId) {
		console.log("입력한 아이디는 없는 아이디에요");
	}
})

회원 가입 한명 시키고 → POSTMAN) POST+localhost:7777/login + (raw body) {”userId” : “userId2”, “password” : “1234”}

그런데 자세히 보면, if문이 반복되었고 또 더욱 간결하게 바꿔줄 수 있다

app.post('/login', function(req, res) {
	console.log(req.body);

	const { userId, password } = req.body;
	let loginUser = {};
    
	db.forEach((user, id)=> {
		if(user.userId === userId) {

			loginUser = user;
		}
	})

	if(loginUser) {
		console.log('userId 같음')
		
		if(loginUser.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
	} else {
		console.log("입력한 아이디는 없는 아이디에요");
	}
})

하지만 또 문제점이 있다. loginUser가 있어야 if문을 실행해야 하는데 회원가입을 시키지도 않았는데 콘솔창이 찍힌다.

user을 등록하지 않았는데도 위와 같은 결과가 나타나는 것은 loginUser가 {}로 할당 되었기 때문이다. 자바스크립트는 {}이 텅텅 비어도 값이 있는 것이라고 인식하기 때문!

💡 자바스크립트 Object.keys()

: 빈 객체를 확인하는 방법 3가지

  1. 객체.keys()
  2. for in 사용해서 프로퍼티가 있는지 확인
  3. lodash(라이브러리) : isEmpty

가장 추천한 객체.keys()를 사용해서 빈 객체를 확인해보자

// empty-demo.js

const obj1 = {}
const obj2 = { message : "hello" }
const num = 1;
const str1 = "one";
const str2 = "";

console.log(Object.keys(obj1)); // [] // length === 0
console.log(Object.keys(obj1).length === 0); // true 
console.log(Object.keys(obj2)); // [ 'message' ] // length === 1
console.log(Object.keys(obj2).length === 0); // false

console.log(Object.keys(num).length === 0); // ture
// 숫자 불가능

console.log(Object.keys(str1).length === 0); // false
console.log(Object.keys(str2).length === 0); // true
// 문자열 가능 (문자열도 결국 객체이기 때문)

// 함수로 바꾸기
function isEmpty(obj) {
	if (Object.keys(obj).length === 0) {
		return true;
	} else {
		return false;
	}
}

console.log(isEmpth(obj1)); // true
console.log(isEmpth(obj2)); // false

// 빈 객체 찾기를 함수로 만들어 어디서든 써먹을 수 있다
// 그런데 숫자가 들어갈 수 도 있으니, 객체 인지 먼저 확인해야함
function isEmpty(obj) {
	if (obj.constructor === Object) // 나중에 이부분 구글링해보자
	if (Object.keys(obj).length === 0) {
		return true;
	} else {
		return false;
	}
}

📍 로그인 고도화

: loginUser 빈객체 체크 넣기

app.post('/login', function(req, res) {
	console.log(req.body);

	let loginUser = {};
	const { userId, password } = req.body;
	
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			loginUser = user;
		}
	})

	if(Object.keys(loginUser).length) {
		console.log('userId 같음')
		res.status(200).json({
      		message: `로그인 되었습니다`,
    	});
		if(loginUser.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
	} else { // length === 0
		console.log("입력한 아이디는 없는 아이디에요");
	}
})

등록 안하고 -> POSTMAN) POST+localhost:7777/login + (raw) body {”userId” : “userId2”, “password” : "1234"}

그리고 함수로 추출하기(다른 사람들이 잘 알아볼 수 있도록+if문은 긍정문으로 클린코드로 만들기)

app.post('/login', function(req, res) {
	console.log(req.body);

	let loginUser = {};
	const { userId, password } = req.body;
	
	db.forEach((user, id)=> {
		if(user.userId === userId) {
			loginUser = user;
		}
	})

	if(isExisted(loginUser)) {
		console.log('userId 같음')
		res.status(200).json({
      		message: `로그인 되었습니다`,
    	});
		if(loginUser.password === password) {
				console.log("pwd도 같음");
			} else {
				console.og("pwd는 틀렸음");
			}
	} else {
		console.log("입력한 아이디는 없는 아이디에요");
	}
})

function isExisted(obj) {
	if (Object.keys(obj).length) {
		return true;
	} else {
		return false;
	}
}

똑같은 console 출력확인

POSTMAN 결과 화면

✏️ 채널 API 설계 1

: URL, HTTP method/status, res/req

  • 채널 생성

    • POST /channels
    • req : (body) channelTitle
    • res 201 : ${channelTitle}님 채널이 만들어졌어요!
  • 채널 수정

    • PUT /channels/:id
    • req : (url) id, (body) channelTitle
    • res 200 : 채널 명이 ${oldTitle}에서 ${newTitle}로 바뀌었어요
  • 채널 개별 삭제

    • DELETE /channels/:id
    • req : (url) id
    • res 200 : ${channelTitle}님, 삭제되었어요
  • 채널 전체 조회

    • GET /channels
    • req : X
    • res 200 : 채널 전체 데이터(list)
  • 채널 개별 조회

    • GET /channels/:id
    • req : (url) id
    • res 200 : 채널 개별 데이터

✏️ 채널 API 설계 2

: 화면 그림을 그려서 API를 추론해보자

  • 마이페이지

  • 채널 관리 페이지
    : 마이페이지에서 채널 관리 버튼 누른 후, (1) 화면 출력 → '특정 회원이 소유한 전체 채널 조회 API' (2) 삭제 버튼 클릭시 → '개별 채널 삭제 API'

  • 채널 생성 페이지
    : 채널 관리 페이지에서 생성 버튼 누른 후, 입력받은 채널명을 받아와서 '채널 생성(등록) API'

  • 개별 채널 수정 페이지
    : 채널 관리 페이지에서 수정 버튼 누른 후, (1) 화면 출력 → 기존 '개별 채널 정보 조회 API' (2) 수정 완료 버튼 클릭시 → '개별 채널 수정 API'

  • 개별 채널 삭제 페이지
    : 채널 관리 페이지에서 삭제 버튼 누른후, '개별 채널 삭제 API'

✏️ 채널 API 코드틀 route

: route를 이용해서 같은 url끼리 묶기

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

app
	.route('/channels')
	.get((req, res) => {
		res.send("전체 조회")
	}) // 채널 전체 조회
	.post((req, res) => {
		res.send("개별 생성")
	}) // 채널 개별 생성


app
	.route('/channels/:id')
	.get((req, res) => {
		res.send("개별 조회")
	}) // 채널 개별 조회
	.put((req, res) => {
		res.send("개별 수정")
	}) // 채널 개별 수정
	.delete((req, res) => {
		res.send("개별 삭제")
	}) // 채널 개별 삭제

POSTMAN) GET + localhost:7777/channels → 전체 조회

✏️ 채널 생성, 조회, 삭제, 수정

📍 채널 생성

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

app
	.route('/channels')
	.get((req, res) => {
		res.send("전체 조회")
	})
	.post((req, res) => {
		if(req.body.channelTitle) {
			db.set(id++, req.body);
		
			res.status(201).json({
				message : `${db.get(id-1).channelTitle}님 채널이 만들어졌어요!`
			})
		} else {
			res.status(400).json({
				meesage : `요청 값을 다시 보내주세요`
			})
		}
	}) // 채널 개별 생성 = db에 저장
// ... 생략 ...

POSTMAN ) POST + localhost:7777/channels + (raw body) { “channelTitle” : “쨍순이”}

📍 채널 개별 조회

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

// ... 생략 ...
app
	.route('/channels:id')
	.get((req, res) => {
		let {id} = req.params;
		id = parseInt(id);
		
		const channel = db.get(id);
		if(channel) {
			res.status(200).json(channel)
		}else {
			res.status(404).json({
				message : `채널 정보를 찾을 수 없어요`
			})
		}
	})
//... 생략 ...

POSTMAN) POST 후, GET + localhost:7777/channels/1

📍 채널 개별 삭제

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

// ... 생략 ...
app
	.route('/channels/:id')
	// .. 생략 ...
	.delete((req, res) => {
		let {id} = req.params;
		id = parseInt(id);
		
		const channel = db.get(id);
		if(channel) {
			db.delete(id)
			res.status(200).json({
				message: `${channel.channelTitle}님, 삭제되었어요`
			})
		} else {
			res.status(404).json({
				message : `채널 정보를 찾을 수 없어요!`
			})
		}
	}) // 채널 개별 삭제

POSTMAN) POST 후, DELETE + localhost:7777/channels/1

📍 채널 수정

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

// ... 생략 ...
app
	.route('/channels/:id')
	.put((req, res) => {
		let {id} = req.params;
		id = parseInt(id);
		
		const channel = db.get(id);
		const oldTitle = channel.channelTitle;
	
		if(channel) {
			const newTitle = req.body.channelTitle;
			channel.channelTitle = newTitle;
			db.set(id, channel);
			
			res.status(200).json({
				message : `채널 명이 ${oldTitle}에서 ${newTitle}로 바뀌었어요`
			})
		} else {
			res.status(404).json({
				message : `채널 정보를 찾을 수 없어요`
			})
		}
		
	}) // 채널 개별 수정
// ... 생략 ...

POSTMAN) POST 등록 후, PUT + localhost:7777/channels/1

📍 채널 전체 조회

// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

app
	.route('/channels')
	.get((req, res) => {
		let channels = [];
		db.forEach((vlaue, key) => {
			channels.push(value);
			// 배열을 이용해서 value를 넣어주면
			// [{"channelTitle" : " "}, {"channelTitle" : " "}]
			// 이런식으로 받아올 수 있다.
            // channels = {} 일 때는 받아오는 결과가
            // { 
            // 	  '1': {"channelTitle" : "쨍순이"},
            //    '2': {"channelTitle" : "쨍돌이"},
            //    '3': {"channelTitle" : "쨍이"}
            // }
            // 이랬음
			// 그럼 key와 value를 묶으면 프론트엔드는 어떻게 받아올 수 있을까?
			// channels[0], channels[1], channels[2]
			// 이렇게 인덱스를 통해서 가져온다
			
			res.satatus(200).json(channels);
			// 배열 형태인데 json()을 사용해도 될까?
			// 배열 형태로 지켜서 보내줌
			// json을 배열 형태로 만든 것 뿐이기 때문에 json array로 보내도됨
		})
	}) // 채널 전체 조회
// ... 생략 ...

POSTMAN) POST 3개 등록 후, GET + localhost:7777/channels

  • 예외 처리 + 고도화
// channel-demo.js

const express = require('express');
const app = express();
app.listen(7777);
app.use(express.json());

let db = new Map();
let id = 1;

app
	.route('/channels')
	.get((req, res) => {
		if(db.size) {
        	let channels = [];
			db.forEach((vlaue, key) => {
				channels.push(value);
			})
            res.status(200).json(channels);
		} else {
			res.status(404).json({
				message: `조회할 채널이 없어요`
			})
		}
	}) // 채널 전체 조회
// ... 생략 ...

POST 등록 안하고 -> POSTMAN) GET + localhost:7777/channels

🍎🍏 오늘 로그인 API 설계와 channel API 설계를 연습해보았다. 분명 바로 전에 했을 때 바로 이해돼서 멈추고 혼자서 시도하려고 하니깐 잘 안된다 ㅠㅠ 역시.. 연습만이 살길인가.. 예외처리를 할 때, 생각을 좀 더 깊게 해야 편리하게 해 줄 수 있을 것 같았다. 많이 사용해봐야 감을 알고 잘 쓸 것 같다. 무튼 오늘 많은 실습들로 인해서 머리가 좀 아프지만, 그래도 하나하나 결과로 확인하면서 체크해보니 뿌듯하다.

profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글