Vue.js 3 & NodeJS/NodeJS

Node.js 레스트 API 업데이트 (회원) - Node.js REST API, Member-API, Profile

carrotweb 2022. 5. 22. 14:46
728x90
반응형

블로그처럼 회원의 프로필과 별명(애칭)을 사용하여 게시물을 표현하기 위해서 프로필 이미지와 별명(애칭)을 추가하도록 하겠습니다.

 

 

회원 데이터 업데이트 및 회원 정보 함수 추가

 

1. 회원 정보에 추가될 프로필 이미지들이 저장되는 폴더를 생성합니다.
C:\workspaces\nodeserver\testrestapi\public\asset 폴더에 member 폴더와 member 폴더 안에 profile 폴더를 생성합니다.

 

생성된 폴더에 회원 정보에서 사용할 프로필 이미지를 추가합니다.

 

2. C:\workspaces\nodeserver\testrestapi\memberapi.js 파일을 오픈하여 회원 배열에 있는 초기 데이터에 정보와 회원을 추가합니다.
초기 데이터에 프로필 이미지를 profile로 추가하고 별명(애칭)을 nickname으로 추가합니다.

let memberList = [
{id:"testid1", password:"testpwd1", name:"홍길동", refreshToken:"", nickname:"나혼자", profile:"testid1.jpg"},
{id:"testid2", password:"testpwd2", name:"김철수", refreshToken:"", nickname:"댕댕이맘", profile:"testid2.jpg"},
{id:"testid3", password:"testpwd3", name:"이영희", refreshToken:"", nickname:"만물상", profile:"testid3.jpg"},
{id:"testid4", password:"testpwd4", name:"박동수", refreshToken:"", nickname:"하트비트", profile:"testid4.jpg"},
{id:"testid5", password:"testpwd5", name:"정하늘", refreshToken:"", nickname:"스카이", profile:"testid5.jpg"},
{id:"testid6", password:"testpwd6", name:"한아름", refreshToken:"", nickname:"아름이", profile:"testid6.jpg"},
{id:"testid7", password:"testpwd7", name:"강백호", refreshToken:"", nickname:"슬램덩크", profile:"testid7.jpg"}
];

 

3. require() 메서드로 authmiddleware를 불러옵니다.

const authMiddleware = require('./authmiddleware');

 

4. HTTP GET 메서드로 회원 아이디(memberId)가 포함되어서 요청(Request)이 들어오면 회원 배열에서 회원  아이디로 검색하여 회원 객체를 리턴합니다. authmiddleware를 추가하여 인증된 본인만 사용하게 합니다.

router.get('/:memberId', authMiddleware, function(req, res, next) {
	console.log("REST API Get Method - Member Read " + req.params.memberId);
	const memberId = req.params.memberId;
	if (memberId == req.tokenInfo.memberId) {
		var memberItem = memberList.find(object => object.id == memberId);
		if (memberItem != null) {
			var member = {};
			member.id = memberItem.id;
			member.name = memberItem.name;
			member.nickname = memberItem.nickname;
			member.profile = "/asset/member/profile/" + memberItem.profile;
			res.json({success:true, data:member});
		} else {
			res.status(404);
			res.json({success:false, errormessage:'not found'});
		}
	} else {
		res.status(403);
		res.json({success:false, errormessage:'id are not identical'});
	}
});

회원 아이디(id)가 회원 배열에 없으면 404 에러와 에러 메시지를 리턴합니다.

5. 회원 정보를 다른 모듈에서 검색하여 사용할 수 있게 함수를 생성합니다.

const getMember = function(memberId) {
	var member = null;
	var memberItem = memberList.find(object => object.id == memberId);
	if (memberItem != null) {
		member = {};
		member.id = memberItem.id;
		member.name = memberItem.name;
		member.nickname = memberItem.nickname;
		member.profile = "/asset/member/profile/" + memberItem.profile;
	}
	return member;
};

 

 

6. module.export로 라우터와 함수를 묶어서 내보냅니다.

// module.exports = router;

module.exports = {
	router,
	getMember
};

module.export로 라우터와 함수를 묶어서 내보내기 때문에 라우터를 사용하는 app.use()를 수정해 줘야 합니다.

7. C:\workspaces\nodeserver\testrestapi\index.js 파일을 오픈하여 app.use()를 수정합니다.

// app.use('/boards', require('./memberapi'));

const memberapi = require('./memberapi');
app.use('/members', memberapi.router);

memberapi의 getMember() 함수를 사용하여 boardapi에 회원 정보를 추가합니다.

8. C:\workspaces\nodeserver\testrestapi\boardapi.js 파일을 오픈하여 memberapi의 getMember() 함수를 require()로 불러옵니다.

const { getMember } = require('./memberapi');

 

그리고 라우터에 회원 정보를 추가합니다.

router.get('/', function(req, res, next) {
	console.log("REST API Get Method - Read All");
	
	// 필터된 게시판
	var filteredBoardList = filter.filtering(req.query, boardList);
	if (filteredBoardList.length == 0) {
		res.status(404);
		res.json({success:false, errormessage:'not found'});
	} else {
		// 정렬
		var sortby = req.query.sortby;
		sort.sortBy(filteredBoardList, sortby);
		
		// 전체 크기
		var totalCount = filteredBoardList.length;
		
		// 페이지네이션 정보
		var paginationInfo = pagination(totalCount, req.query.countperpage, req.query.pagesize, req.query.pageno);
		
		// 시작 번호
		var startItemNo = ((paginationInfo.pageNo - 1) * paginationInfo.countPerPage);
		// 종료 번호
		var endItemNo = (paginationInfo.pageNo * paginationInfo.countPerPage) - 1;
		// 종료 번호가 전체 크기보다 크면 전체 크기로 변경
		if (endItemNo > (totalCount - 1)) {
			endItemNo = totalCount - 1;
		}
		
		var boardPageList = [];
		if (startItemNo < totalCount) {
			for (var index = startItemNo; index <= endItemNo; index++) {
				var filteredBoardItem = filteredBoardList[index];
				
				var boardPageItem = {};
				boardPageItem.no = filteredBoardItem.no;
				boardPageItem.subject = filteredBoardItem.subject;
				if (filteredBoardItem.content.length > 100) {
					boardPageItem.content = filteredBoardItem.content.substr(0, 100);
				} else {
					boardPageItem.content = filteredBoardItem.content;
				}
				boardPageItem.writer = filteredBoardItem.writer;
				var memberInfo = getMember(filteredBoardItem.writer);
				boardPageItem.writerName = memberInfo.name;
				boardPageItem.writerNickname = memberInfo.nickname;
				boardPageItem.writerProfile = memberInfo.profile;
				boardPageItem.writedate = filteredBoardItem.writedate;
				boardPageItem.poster = "/asset/board/files/" + filteredBoardItem.poster;
				boardPageItem.viewcount = filteredBoardItem.viewcount;
				boardPageItem.categoryText = categoryList[filteredBoardItem.category];
				boardPageItem.likecount = filteredBoardItem.likecount;
				boardPageList.push(boardPageItem);
			}
		}
		
		res.json({success:true, data:boardPageList, pagination:paginationInfo});
	}
});

router.get('/:no', function(req, res, next) {
	console.log("REST API Get Method - Read " + req.params.no);
	var boardItem = boardList.find(object => object.no == req.params.no);
	if (boardItem != null) {
		var boardViewItem = {};
		boardViewItem.no = boardItem.no;
		boardViewItem.subject = boardItem.subject;
		boardViewItem.content = boardItem.content;
		boardViewItem.writer = boardItem.writer;
		var memberInfo = getMember(boardItem.writer);
		boardViewItem.writerName = memberInfo.name;
		boardViewItem.writerNickname = memberInfo.nickname;
		boardViewItem.writerProfile = memberInfo.profile;
		boardViewItem.writedate = boardItem.writedate;
		boardViewItem.poster = "/asset/board/files/" + boardItem.poster;
		boardViewItem.viewcount = boardItem.viewcount;
		boardViewItem.categoryText = categoryList[boardItem.category];
		boardViewItem.likecount = boardItem.likecount;
		res.json({success:true, data:boardViewItem});
	} else {
		res.status(404);
		res.json({success:false, errormessage:'not found'});
	}
});

 

9. npm run 명령어로 실행합니다.

npm run start

 

10. Postman(포스트맨)를 실행하여 회원 정보를 가져오기 위해 GET Method로 호출합니다.
먼저 로그인 처리를 진행한 후 헤더 KEY에 "Access-Token"으로 생성된 JWT를 추가하고 호출해야 합니다. 

http://localhost:9000/members/testid1

리턴 값에 success가 true이고 data에 회원 정보를 가져옵니다.

{
    "success": true,
    "data": {
        "id": "testid1",
        "name": "홍길동",
        "nickname": "나혼자",
        "profile": "/asset/member/profile/testid1.jpg"
    }
}

 

반응형

 

게시판 리스트를 가져오기 위해 GET Method로 호출합니다.

http://localhost:9000/boards?countperpage=3&pageno=1&sortby=writedate.desc,writer.desc

{
    "success": true,
    "data": [
        {
            "no": 12,
            "subject": "혼자하는 에어컨 청소법",
            "content": "에어컨 커버없이 관리되는 에어컨들은 냉기가 나오는 입구에 먼지가 많이 쌓이게 됩니다.\n이런 먼지들을 쉽고 간편하게 청소하는 방법이 있어 알려드립니다.",
            "writer": "testid3",
            "writerName": "이영희",
            "writerNickname": "만물상",
            "writerProfile": "/asset/member/profile/testid3.jpg",
            "writedate": "2022-03-27 00:30:00",
            "poster": "/asset/board/files/12.png",
            "viewcount": 20,
            "categoryText": "노하우",
            "likecount": 50
        },
        {
            "no": 11,
            "subject": "애견동반 가능한 카페",
            "content": "이번에는 전주에 갔을 때 반련견과 함께 갈 수 있는 카페를 몇 군데 다녀왔습니다.\n오늘 방문한 곳 중 하나인데요.\n제 마음에 쏙 꽂혀버린 카페입니다.",
            "writer": "testid2",
            "writerName": "김철수",
            "writerNickname": "댕댕이맘",
            "writerProfile": "/asset/member/profile/testid2.jpg",
            "writedate": "2022-03-27 00:30:00",
            "poster": "/asset/board/files/11.png",
            "viewcount": 15,
            "categoryText": "애견/반려동물",
            "likecount": 80
        },
        {
            "no": 13,
            "subject": "푸짐하고 맛이 괜찮았던 국물 라뽁이",
            "content": "안녕하세요. 저는 우리나라에서 파는 모든 국물 라뽁이를 먹고 소개드리고자 하는 라짱입니다.\n저는 주말을 맞아 국물맛 괜찮은 라뽁이를 리뷰해 드리고자 합니다.",
            "writer": "testid1",
            "writerName": "홍길동",
            "writerNickname": "나혼자",
            "writerProfile": "/asset/member/profile/testid1.jpg",
            "writedate": "2022-03-27 00:30:00",
            "poster": "/asset/board/files/13.png",
            "viewcount": 25,
            "categoryText": "쇼핑",
            "likecount": 40
        }
    ],
    "pagination": {
        "totalCount": 13,
        "countPerPage": 3,
        "pageSize": 10,
        "startPageNo": 1,
        "endPageNo": 5,
        "lastPageNo": 5,
        "pageNo": 1,
        "enablePrevPageNo": false,
        "enableNextPageNo": true,
        "prevPageSizeNo": 0,
        "enablePrevPageSizeNO": false,
        "nextPageSizeNo": 6,
        "enableNextPageSizeNO": false
    }
}

 

게시판 내용을 가져오기 위해 GET Method로 호출합니다.

http://localhost:9000/boards/1

{
    "success": true,
    "data": {
        "no": 1,
        "subject": "나의 일상 정리",
        "content": "요즘 뭔가 평소보다 이상하게 시간이 더 빠르게 지나간것 같기도 하고 날씨도 좋아진것 같기도 하고 뭐 빠르게 지나가는 것 같습니다.\n아무튼 내 일상을 간만에 끄적여봅니다.",
        "writer": "testid1",
        "writerName": "홍길동",
        "writerNickname": "나혼자",
        "writerProfile": "/asset/member/profile/testid1.jpg",
        "writedate": "2021-08-09 13:00:00",
        "poster": "/asset/board/files/1.png",
        "viewcount": 10,
        "categoryText": "일상",
        "likecount": 10
    }
}

 

728x90
반응형