Version : Unity 2021.3.5f1
MDN
The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps.
웹 사이트와 프로그레시브 웹 앱 모두에 대한 HTML, CSS 및 API를 포함한 개방형 웹 기술에 대한 정보를 제공하는 사이트
https://developer.mozilla.org/ko/docs/Web/JavaScript
![](https://lycos7560.com/wp-content/uploads/image-135.png)
EXPRESS
https://ninjaggobugi.tistory.com/9 <- 자세한 설명
Express란?
Express는 웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 웹 애플리케이션 프레임 워크
Node.js는 Chrome의 V8엔진을 이용하여 javascript로 브라우저가 아니라 서버를 구축하고, 서버에서 JavaScript가 작동되도록 해주는 런타임 환경(플랫폼)
Express는 이런 Nodejs의 원칙과 방법을 이용하여 웹애플리케이션을 만들기 위한 프레임워크이다.
![](https://lycos7560.com/wp-content/uploads/image-137.png)
NPM
npm(node package manager)은 자바스크립트 패키지 매니저이다. Node.js에서 사용할 수 있는 모듈들을 패키지화하여 모아둔 저장소 역할과 패키지 설치 및 관리를 위한 CLI(Command line interface)를 제공한다.
자신이 작성한 패키지를 공개할 수도 있고 필요한 패키지를 검색하여 재사용할 수도 있다.
![](https://lycos7560.com/wp-content/uploads/image-138.png)
Mysql
Mysql용 node.js 드라이버
https://www.npmjs.com/package/mysql
![](https://lycos7560.com/wp-content/uploads/image-139.png)
Mysql2
async/await을 사용하기 위해선 mysql2를 설치 해야 한다.
콜백 방식이 싫다면 사용하자
https://www.npmjs.com/package/mysql2
![](https://lycos7560.com/wp-content/uploads/image-140.png)
npm init 해주기
https://www.dailysmarty.com/posts/npm-init-y-explanation
![](https://lycos7560.com/wp-content/uploads/image-141.png)
$npm init -y
npm(Node Package Manager) 에서 express설치
$ npm install express
npm(Node Package Manager) 에서 mysql2 설치
npm install --save mysql2
postman 다운로드
Postman은 개발한 API를 테스트하고, 테스트 결과를 공유하여 API 개발의 생산성을 높여주는 플랫폼
![](https://lycos7560.com/wp-content/uploads/image-142.png)
![](https://lycos7560.com/wp-content/uploads/image-143.png)
![](https://lycos7560.com/wp-content/uploads/image-144.png)
![](https://lycos7560.com/wp-content/uploads/image-145.png)
const express = require(`express`); const app = express(); app.get(`/`, function (req, res) { res.send(`hello World`); }) app.listen(포트);
공유기 포트 포워딩
![](https://lycos7560.com/wp-content/uploads/image-146.png)
포스트맨 확인
![](https://lycos7560.com/wp-content/uploads/image-147.png)
![](https://lycos7560.com/wp-content/uploads/image-148.png)
![](https://lycos7560.com/wp-content/uploads/image-149.png)
const express = require(`express`); const app = express(); const port = ; app.get(`/`, function (req, res) { res.send(`hello World`); }); app.listen(port, () => { console.log(`Rest API SERVER 실행됨 port : ${port}`); });
GET POST 차이점
https://noahlogs.tistory.com/35 <- 자세한 설명
GET 이란?
GET 은 클라이언트에서 서버로 어떠한 리소스로부터 정보를 요청하기 위해 사용되는 메서드이다.
예를 들면 게시판의 게시물을 조회할 때 쓸 수 있다.
GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링 (query string)이라고 부른다.
방식은 URL 끝에 “? “를 붙이고 그다음 변수명 1=값 1&변수명 2=값 2… 형식으로 이어 붙이면 된다.
예를 들어 다음과 같은 방식이다.
www.example.com/show?name1=value1&name2=value2
서버에서는 name1과 name2라는 파라미터 명으로 각각 value1과 value2의 파라미터 값을 전달받을 수 있다.
GET의 특징
- GET 요청은 캐시가 가능하다. : GET을 통해 서버에 리소스를 요청할 때 웹 캐시가 요청을 가로채 서버로부터 리소스를 다시 다운로드하는 대신 리소스의 복사본을 반환한다. HTTP 헤더에서 cache-control 헤더를 통해 캐시 옵션을 지정할 수 있다.
- GET 요청은 브라우저 히스토리에 남는다.
- GET 요청은 북마크 될 수 있다.
- GET 요청은 길이 제한이 있다. : GET 요청의 길이 제한은 표준이 따로 있는건 아니고 브라우저마다 제한이 다르다고 한다.
- GET 요청은 중요한 정보를 다루면 안된다. ( 보안 ) : GET 요청은 파라미터에 다 노출되어 버리기 때문에 최소한의 보안 의식이라 생각하자.
- GET은 데이터를 요청할때만 사용 된다.
POST 란?
POST는 클라이언트에서 서버로 리소스를 생성하거나 업데이트하기 위해 데이터를 보낼 때 사용되는 메서드다. 예를 들면 게시판에 게시글을 작성하는 작업 등을 할 때 사용할 된다.
POST는 전송할 데이터를 HTTP 메시지 body 부분에 담아서 서버로 보낸다. ( body 의 타입은 Content-Type 헤더에 따라 결정된다.)
GET에서 URL의 파라미터로 보냈던 name1=value1&name2=value2 가 body에 담겨 보내진다 생각하면 된다.
POST로 데이터를 전송할 때 길이 제한이 따로 없어 용량이 큰 데이터를 보낼 때 사용하거나 GET처럼 데이터가 외부적으로 드러나는 건 아니라서 보안이 필요한 부분에 많이 사용된다.
( 하지만 데이터를 암호화하지 않으면 body의 데이터도 결국 볼 수 있는 건 똑같다. )
POST를 통한 데이터 전송은 보통 HTML form을 통해 서버로 전송된다.
POST의 특징
- POST 요청은 캐시되지 않는다.
- POST 요청은 브라우저 히스토리에 남지 않는다.
- POST 요청은 북마크 되지 않는다.
- POST 요청은 데이터 길이에 제한이 없다.
GET 과 POST 의 차이점
GET과 POST의 특징만 보아도 차이가 나긴하지만 추가적으로 차이점을 정리해보면 다음과 같다.
- 사용목적 : GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다.DB로 따지면 GET은 SELECT 에 가깝고, POST는 Create 에 가깝다고 보면 된다.
- 요청에 body 유무 : GET 은 URL 파라미터에 요청하는 데이터를 담아 보내기 때문에 HTTP 메시지에 body가 없다. POST 는 body 에 데이터를 담아 보내기 때문에 당연히 HTTP 메시지에 body가 존재한다.
- 멱등성 (idempotent) : GET 요청은 멱등이며, POST는 멱등이 아니다.
멱등이란?
멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것 이다. 반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다. (POST 요청이 발생하면 서버가 변경될 수 있다.)
GET과 POST는 이런 차이들이 있기 때문에 사용하려는 목적에 맞는 확인한 후에 사용해야한다.
GET과 POST 이외에도 PUT , DELETE 등을 적절히 사용하는게 좋은데 예를들어 봇의 경우에 사이트를 돌아다니면서 GET 요청을 날린다. 이럴 때 DELETE 등을 GET으로 처리하면 봇에 의해 서버에 있는 리소스들이 삭제 되는 상황이 일어 날수 있다! 항상 기술을 사용할 때 왜 를 잊지말자.
![](https://lycos7560.com/wp-content/uploads/image-150.png)
citysRouter.js
const express = require(`express`); const citysDBC = require(`./citysDBC`); const router = express.Router(); router.get('/getCitys', async (req, res)=>{ let res_get_citys = { status : 500, citys : [] }; try{ const rows = await citysDBC.getCitys(); res_get_citys.status = 200; if(rows.length > 0){ rows.forEach((city)=>{ res_get_citys.citys.push(city); }); }else{ console.log('도시 없음'); } }catch(error) { console.log(error.message); }finally { //응답 res.json(res_get_citys); } }); module.exports = router;
app.js
const express = require(`express`); const citysRouter = require('./citysRouter'); const app = express(); const port = ; app.use(express.json()); // json app.use('/city', citysRouter); app.get(`/`, function (req, res) { res.send(`<h2>Welcome to REST API SERVER. </h2>`); }); app.listen(port, () => { console.log(`Rest API SERVER 실행됨 port : ${port}`); });
citysDBC.js
// get the client const mysql = require('mysql2'); // Create the connection pool. The pool-specific settings are the defaults const pool = mysql.createPool({ host: 'localhost', user: '', password: '', database: '', port: , waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); const getCitys = async ()=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query('SELECT * FROM city;'); return rows; }; module.exports = { getCitys };
완료
![](https://lycos7560.com/wp-content/uploads/image-151.png)
![](https://lycos7560.com/wp-content/uploads/image-152.png)
![](https://lycos7560.com/wp-content/uploads/image-153.png)
![](https://lycos7560.com/wp-content/uploads/image-154.png)
USER 등록 및 검색
usersDBC.js
// get the client const mysql = require('mysql2'); const pool = mysql.createPool({ host: '', user: '', password: '', database: 'test_schema', port: , waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); const signup = async (values)=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query('insert into users (user_uid, nickname) values (?, ?)', values); //console.log(rows); return rows; }; const getUsers = async ()=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query('select * from users;'); console.log(rows); return rows; }; module.exports = { getUsers, signup };
usersRouter.js
const express = require(`express`); const userDBC = require(`./usersDBC`); const router = express.Router(); router.post('/signup', async(req, res)=>{ const res_signup = { status_code : 500 }; try{ const {user_uid, nickname} = req.body; const rows = await userDBC.signup([user_uid, nickname]); if(rows.affectedRows > 0){ // 적용됨 res_signup.status_code = 200; }else{ // 적용 안됨 res_signup.status_code = 201; } }catch(err) { //에러 console.log(err.message); }finally{ res.json(res_signup); } }); router.get('/getUsers', async (req, res)=>{ let res_get_users = { status_code : 500, users : [] }; try{ const rows = await userDBC.getUsers(); res_get_users.status_code = 200; if(rows.length > 0){ rows.forEach((user)=>{ res_get_users.users.push({ nickname : user.nickname }); }); }else{ console.log('사용자 없음'); } }catch(error) { console.log(error.message); }finally { //응답 res.json(res_get_users); } }); module.exports = router;
app.js
const express = require(`express`); const citysRouter = require('./citysRouter'); const usersRouter = require('./usersRouter'); const app = express(); const port = ; app.use(express.json()); // json app.use('/city', citysRouter); app.use('/user', usersRouter); app.get(`/`, function (req, res) { res.send(`<h2>Welcome to REST API SERVER. </h2>`); }); app.listen(port, () => { console.log(`Rest API SERVER 실행됨 port : ${port}`); });
![](https://lycos7560.com/wp-content/uploads/image-155.png)
![](https://lycos7560.com/wp-content/uploads/image-156.png)
![](https://lycos7560.com/wp-content/uploads/image-157.png)
![](https://lycos7560.com/wp-content/uploads/image-158.png)
cd .. 상위 디렉토리
cd – 뒤로가기
cd 폴더명 해당 디렉토리로
dir 위치의 파일 확인
mkdir 폴더명
pushd <-UNC 경로 지원 안할때
node js
netstat -a 사용중인 포트 보기
netstat findstr: 포트 번호
(혹은 netstat -an | findstr:”포트넘버”) 를 통해 특정한 포트넘버를 직접 찾을 수도 있다.
*-an 은 -a와 -n 을 합친 명령어로서 n은 숫자를 의미한다.
*findstr 은 특정 문자를 포함한 문자열을 찾는다는 뜻이다.)
ps -aef | grep node 사용중인 노드 보기
Taskkill /IM node.exe /F 를 입력해
kill node
killall node
Node.js 를 통해 실행중인 모든 서버를 종료할 수 있다.
taskkill /f /pid (종료할 pid) 를 입력하여 특정 pid를 가진 연결을 종료시킨다.
(pid는 맨 오른쪽에 있는 숫자가 pid이다.)
- pid 란 process ID 를 뜻한다.
연습용 프로토콜 문서
![](https://lycos7560.com/wp-content/uploads/image-159.png)
usersRouter.js
const express = require(`express`); const userDBC = require(`./usersDBC`); const router = express.Router(); router.post('/signUp', async(req, res)=>{ const res_signup = { status_code : 500 }; try{ const {user_uid, nickname} = req.body; const rows = await userDBC.signUp([user_uid, nickname]); if(rows.affectedRows > 0){ //적용됨 res_signup.status_code = 200; }else{ //적용안됨 res_signup.status_code = 201; } }catch(err) { //에러 console.log(err.message); }finally{ res.json(res_signup); } }); router.get('/getUsers', async (req, res)=>{ let res_get_users = { status_code : 500, users : [] }; try{ const rows = await userDBC.getUsers(); res_get_users.status_code = 200; if(rows.length > 0){ rows.forEach((user)=>{ res_get_users.users.push({ nickname : user.nickname }); }); }else{ console.log('사용자 없음'); } }catch(error) { console.log(error.message); }finally { //응답 res.json(res_get_users); } }); router.post('/nasSignUp', async(req, res)=>{ const res_signup = { status_Code : 500 }; try{ //console.log(req.body); const {user_uid, nickname} = req.body; const row = await userDBC.nasSignUp([user_uid, nickname]); if(row.length > 0) { res_signup.status_Code = row[0]; } }catch(err) { //에러 console.log(err.message); }finally{ res.json(res_signup.status_Code); } }); router.post('/nasGetUser', async(req, res)=>{ const res_getuser = { statusCode : 500, nickname : "" }; try{ const {user_uid} = req.body; const row = await userDBC.nasGetUser([user_uid]); const row2 = await userDBC.nasGetUserNick([user_uid]); if(row.length > 0) { res_getuser.statusCode = row[0].statusCode; res_getuser.nickname = row2[0].nickname; } console.log(row); } catch(err) { //에러 console.log(err.message); } finally{ res.json(res_getuser); } }); router.post('/nasSignOut', async(req, res)=>{ const res_signup = { status_Code : 500 }; try{ const {user_uid} = req.body; const row = await userDBC.nasSignOut([user_uid]); if(row.length > 0) { res_signup.status_Code = row[0]; } }catch(err) { //에러 console.log(err.message); }finally{ res.json(res_signup.status_Code); } }); module.exports = router;
usersDBC.js
// get the client const mysql = require('mysql2'); const pool = mysql.createPool({ host: ' user: ' password: ' database: ' port: waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); const signUp = async (values)=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query('insert into users (user_uid, nickname) values (?, ?)', values); //console.log(rows); return rows; }; const getUsers = async ()=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query('select * from users;'); console.log(rows); return rows; }; const signOut = async () => { const promisePool = pool.promise(); const [rows] = await promisePool.query(``) }; const nasSignUp = async ([user_uid, nickname])=>{ const promisePool = pool.promise(); //console.log(user_uid); //console.log(nickname); const [rows] = await promisePool.query(`SELECT FNC_sign_Up('${user_uid}','${nickname}') AS statusCode;`); //console.log(rows); return rows; }; const nasGetUser = async ([user_uid])=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query(`SELECT FNC_getUser_statusCode('${user_uid}') AS statusCode;`); return rows; }; const nasGetUserNick = async ([user_uid])=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query(`SELECT FNC_getUser_nickName('${user_uid}') AS nickname;`); return rows; }; const nasSignOut = async ([user_uid])=>{ const promisePool = pool.promise(); const [rows] = await promisePool.query(`SELECT FNC_signOut('${user_uid}') AS statusCode;`); return rows; }; module.exports = { getUsers, signUp, signOut, nasSignUp, nasGetUser, nasGetUserNick, nasSignOut };
app.js
const express = require(`express`); const citysRouter = require('./citysRouter'); const usersRouter = require('./usersRouter'); const app = express(); const port = ; app.use(express.json()); // json app.use('/city', citysRouter); app.use('/user', usersRouter); app.get(`/`, function (req, res) { res.send(`<h2>Welcome to REST API SERVER. </h2>`); }); app.listen(port, () => { console.log(`Rest API SERVER 실행됨 port : ${port}`); });
Query
USE test_schema; SELECT * FROM users; DELETE FROM users WHERE user_uid = '445a6a0a-577f-4ae4-b6f3-6f1301380edf'; ## 유저를 등록 delimiter // CREATE FUNCTION FNC_sign_Up($user_uid varchar(45), $nickName varchar(45)) RETURNS INT BEGIN SET @user_uid_duplicate_check = 0; -- 유저 uid로 검색하여 중복 체크 SET @nickname_duplicate_check = 0; -- 닉네임 중복 체크 SET @statusCode = 200; -- 기본으로 200 -- 200 유저 등록 완료 -- 201 이미 등록된 유저 -- 202 중복 닉네임 -- 500 서버 에러 select count(*) into @user_uid_duplicate_check from users where user_uid = $user_uid; select count(*) into @nickname_duplicate_check from users where nickName = $nickName; CASE WHEN @user_uid_duplicate_check > 0 THEN set @statusCode = 201; -- 이미 등록된 유저 WHEN @nickname_duplicate_check > 0 THEN set @statusCode = 202; -- 이미 등록된 닉네임 ELSE INSERT INTO users (user_uid, nickname) values ($user_uid, $nickName); END case; return @statusCode; -- 처리 결과를 반환함 END // delimiter ; SHOW function status; DROP FUNCTION FNC_sign_Up; SELECT FNC_sign_Up('13978557c-2810-4cbf-bd4b-1d4decac45d3', '최토리') AS status_Code; SELECT FNC_sign_Up('445a6a0a-577f-4ae4-b6f3-6f1301380edf', '토리') AS status_Code; ## 유저를 검색 delimiter // CREATE FUNCTION FNC_getUser_statusCode($user_uid varchar(45)) RETURNS INT BEGIN SET @user_uid_duplicate_check = 0; -- 유저 uid로 검색하여 체크 SET @statusCode = 500; -- 기본으로 500 -- 200 유저 검색 완료 -- 201 등록 되지 않은 유저 -- 500 서버 에러 select count(*) into @user_uid_duplicate_check from users where user_uid = $user_uid; CASE WHEN @user_uid_duplicate_check = 0 THEN set @statusCode = 201; -- 등록 되지 않은 유저 WHEN @user_uid_duplicate_check = 1 THEN set @statusCode = 200; -- 등록된 유저 END case; return @statusCode; -- 처리 결과를 반환함 END // delimiter ; SELECT FNC_getUser_statusCode('13978557c-2810-4cbf-bd4b-1d4decac45d3') AS statusCode; SHOW function status; DROP FUNCTION FNC_getUser_statusCode; ## UID로 유저를 검색 delimiter // CREATE FUNCTION FNC_getUser_nickName($user_uid varchar(45)) RETURNS varchar(45) BEGIN declare tnickname varchar(45); select nickname into tnickname from users where user_uid = $user_uid; return tnickname; END // delimiter ; SELECT FNC_getUser_nickName('445a6a0a-577f-4ae4-b6f3-6f1301380edf') AS nickname; DROP FUNCTION FNC_getUser_nickName; ## 유저를 삭제 delimiter // CREATE FUNCTION FNC_signOut($user_uid varchar(45)) RETURNS INT BEGIN SET @user_uid_duplicate_check = 0; -- 유저 uid로 검색하여 체크 SET @statusCode = 500; -- 기본으로 500 -- 200 유저 탈퇴 완료 -- 201 등록 되지 않은 유저 -- 500 서버 에러 select count(*) into @user_uid_duplicate_check from users where user_uid = $user_uid; CASE WHEN @user_uid_duplicate_check = 0 THEN set @statusCode = 201; -- 등록 되지 않은 유저 WHEN @user_uid_duplicate_check = 1 THEN set @statusCode = 200; DELETE FROM users WHERE user_uid = $user_uid; -- 등록된 유저 END case; return @statusCode; -- 처리 결과를 반환함 END // delimiter ; DROP FUNCTION FNC_signOut; SELECT FNC_signOut('13978557c-2810-4cbf-bd4b-1d4decac45d3') AS statusCode;
이제 간단하게 클라이언트(유니티)와 상호작용을 해보자
일단 계정을 등록하고 그 결과를 받아오는 부분을 해보겠습니다.
![](https://lycos7560.com/wp-content/uploads/image-160.png)
![](https://lycos7560.com/wp-content/uploads/image-161.png)
일단 유저의 Uid는 개인적으로 생성한 것 입니다.
https://www.uuidgenerator.net/ <- UUID 생성 사이트
닉네임을 입력하고 등록하면 유저의 Uid/nickname이 중복인지 확인을 하고 해당 결과를 보내줍니다.
테이블의 상태
![](https://lycos7560.com/wp-content/uploads/image-162.png)
서버 OFF 상태
![](https://lycos7560.com/wp-content/uploads/image-163.png)
![](https://lycos7560.com/wp-content/uploads/image-164.png)
서버 ON 상태 – 유저 등록 성공
![](https://lycos7560.com/wp-content/uploads/image-165.png)
데이터가 잘 들어온 것을 확인 할 수 있다.
![](https://lycos7560.com/wp-content/uploads/image-166.png)
SignUP 작업만 완료된 코드
HTTPManager.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using Newtonsoft.Json; using System.Text; public class HTTPManager : MonoBehaviour { public static HTTPManager instance; public string host = ""; public int port = ; public System.Action<int> getSignUpResult; // 싱글톤으로 만들어주자 private void Awake() { HTTPManager.instance = this; } private void OnDestroy() { HTTPManager.instance = null; } // uri => /user/signup public void RequestSignup(string uri, Packets.req_nasSignUp packet) { StartCoroutine(this.RequestSignupImpl(uri, packet)); } private IEnumerator RequestSignupImpl(string uri, Packets.req_nasSignUp packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); Debug.Log(url); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_signup = JsonConvert.DeserializeObject<Packets.res_nasSignUp>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}", res_signup.statusCode); this.getSignUpResult(res_signup.statusCode); } else { this.getSignUpResult(500); Debug.LogFormat("에러"); } www.Dispose(); } }
Packets.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Packets { /* 유저 등록(/users/nasSignUp) statusCode 200 유저 등록 완료 201 이미 등록된 유저 202 중복 닉네임 500 서버 에러 */ public class req_nasSignUp { public string user_uid; public string nickname; } public class res_nasSignUp { public int statusCode; } /* 유저 검색 (/users/nasGetUser) statusCode 200 유저 검색 완료 201 등록 되지 않는 유저 500 서버 에러 */ public class req_nasGetUser { public string user_uid; } public class res_nasGetUser { public int status_code; public string users; } }
RestTestMain.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; public class RestTestMain : MonoBehaviour { public TMP_Text tmp_User_Uid; private string user_Uid; public TMP_InputField userNickName_IF; private string user_NickName; public Button sighUpBtn; public TMP_Text result_Text; void Start() { this.user_Uid = tmp_User_Uid.text; HTTPManager.instance.getSignUpResult = (packet) => { Debug.LogFormat("HTTPManager.instance.getSignUpResult : {0}", packet) ; switch (packet) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 등록 완료", packet); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 이미 등록된 유저입니다.", packet); break; case 202: this.result_Text.text = string.Format("status_code : {0}, 중복된 닉네임 입니다.", packet); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet); break; } }; this.sighUpBtn.onClick.AddListener(() => { this.user_NickName = this.userNickName_IF.text; Debug.LogFormat("TMP_InputField : {0}", this.user_NickName); if (string.IsNullOrEmpty(this.user_NickName) && string.IsNullOrEmpty(this.user_Uid)) { Debug.Log("닉네임을 입력해주세요."); } else { Debug.LogFormat("{0}, {1}", this.user_Uid, this.user_NickName); var packet = new Packets.req_nasSignUp() { user_uid = this.user_Uid, nickname = this.user_NickName }; HTTPManager.instance.RequestSignup("/user/nasSignUp",packet); } }); } }
유니티에서 메모리 누수 오류가 뜨면 하단부를 추가하자
![](https://lycos7560.com/wp-content/uploads/image-114-2.png)
다음은 Uid로 유저를 검색해보자
항상 느끼는 거지만 코드를 작성하는 것보다 환경 구성하는 게 제일 화가 난다.
![](https://lycos7560.com/wp-content/uploads/image-167.png)
![](https://lycos7560.com/wp-content/uploads/image-168.png)
![](https://lycos7560.com/wp-content/uploads/image-169.png)
![](https://lycos7560.com/wp-content/uploads/image-170.png)
서버 OFF
![](https://lycos7560.com/wp-content/uploads/image-171.png)
HTTPManager.cs – GetUser 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using Newtonsoft.Json; using System.Text; public class HTTPManager : MonoBehaviour { public static HTTPManager instance; public string host = ""; public int port = ; public System.Action<int> getSignUpResult; public System.Action<Packets.res_nasGetUser> getGetUserResult; // 싱글톤으로 만들어주자 private void Awake() { HTTPManager.instance = this; } private void OnDestroy() { HTTPManager.instance = null; } // uri => /user/signup public void RequestSignup(string uri, Packets.req_nasSignUp packet) { StartCoroutine(this.RequestSignupImpl(uri, packet)); } private IEnumerator RequestSignupImpl(string uri, Packets.req_nasSignUp packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); Debug.Log(url); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_signup = JsonConvert.DeserializeObject<Packets.res_nasSignUp>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}", res_signup.statusCode); this.getSignUpResult(res_signup.statusCode); } else { this.getSignUpResult(500); Debug.LogFormat("에러"); } www.Dispose(); } public void RequestGetUser(string uri, Packets.req_nasGetUser packet) { StartCoroutine(this.RequestGetUserImpl(uri, packet)); } private IEnumerator RequestGetUserImpl(string uri, Packets.req_nasGetUser packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); Debug.Log(url); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_getuser = JsonConvert.DeserializeObject<Packets.res_nasGetUser>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}, nickName : {1}", res_getuser.statusCode, res_getuser.nickname); this.getGetUserResult(res_getuser); } else { Packets.res_nasGetUser res_getuser = new Packets.res_nasGetUser(); res_getuser.statusCode = 500; res_getuser.nickname = ""; this.getGetUserResult(res_getuser); Debug.LogFormat("에러"); } www.Dispose(); } }
Packets.cs – GetUser 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Packets { /* 유저 등록(/users/nasSignUp) statusCode 200 유저 등록 완료 201 이미 등록된 유저 202 중복 닉네임 500 서버 에러 */ public class req_nasSignUp { public string user_uid; public string nickname; } public class res_nasSignUp { public int statusCode; } /* 유저 검색 (/users/nasGetUser) statusCode 200 유저 검색 완료 201 등록 되지 않는 유저 500 서버 에러 */ public class req_nasGetUser { public string user_uid; } public class res_nasGetUser { public int statusCode; public string nickname; } }
RestTestMain.cs – GetUser 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; public class RestTestMain : MonoBehaviour { public Button SignUpTabBtn; public Button GetUserTabBtn; public GameObject SignUpGO; public GameObject GetUserGO; public TMP_Text tmp_User_Uid; private string user_Uid; public TMP_InputField userNickName_IF; private string user_NickName; public TMP_InputField UserUid_IF; public Button sighUpBtn; public Button getUserBtn; public TMP_Text result_Text; void Start() { this.user_Uid = tmp_User_Uid.text; this.SignUpTabBtn.onClick.AddListener(() => { this.SignUpGO.SetActive(true); this.GetUserGO.SetActive(false); }); this.GetUserTabBtn.onClick.AddListener(() => { this.SignUpGO.SetActive(false); this.GetUserGO.SetActive(true); }); HTTPManager.instance.getSignUpResult = (packet) => { Debug.LogFormat("HTTPManager.instance.getSignUpResult : {0}", packet) ; switch (packet) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 등록 완료", packet); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 이미 등록된 유저입니다.", packet); break; case 202: this.result_Text.text = string.Format("status_code : {0}, 중복된 닉네임 입니다.", packet); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet); break; } }; HTTPManager.instance.getGetUserResult = (packet) => { switch (packet.statusCode) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 검색 완료\n", packet.statusCode); this.result_Text.text += string.Format("NickName : {0}", packet.nickname); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 서버에 등록되지 않은 유저입니다.", packet.statusCode); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet.statusCode); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet.statusCode); break; } }; this.sighUpBtn.onClick.AddListener(() => { this.user_NickName = this.userNickName_IF.text; Debug.LogFormat("TMP_InputField : {0}", this.user_NickName); if (string.IsNullOrEmpty(this.user_NickName) && string.IsNullOrEmpty(this.user_Uid)) { this.result_Text.text = string.Format("닉네임을 입력해주세요."); } else { Debug.LogFormat("{0}, {1}", this.user_Uid, this.user_NickName); var packet = new Packets.req_nasSignUp() { user_uid = this.user_Uid, nickname = this.user_NickName }; HTTPManager.instance.RequestSignup("/user/nasSignUp",packet); } }); this.getUserBtn.onClick.AddListener(() => { if (string.IsNullOrEmpty(this.UserUid_IF.text)) { this.result_Text.text = string.Format("유저의 UID를 입력해주세요."); } else { var packet = new Packets.req_nasGetUser() { user_uid = this.UserUid_IF.text }; HTTPManager.instance.RequestGetUser("/user/nasGetUser", packet); } }); } }
다음은 Uid로 유저를 삭제해보자
![](https://lycos7560.com/wp-content/uploads/image-172.png)
![](https://lycos7560.com/wp-content/uploads/image-173.png)
![](https://lycos7560.com/wp-content/uploads/image-174.png)
![](https://lycos7560.com/wp-content/uploads/image-175.png)
![](https://lycos7560.com/wp-content/uploads/image-176.png)
![](https://lycos7560.com/wp-content/uploads/image-177.png)
![](https://lycos7560.com/wp-content/uploads/image-178.png)
![](https://lycos7560.com/wp-content/uploads/image-179.png)
HTTPManager.cs – SignOut 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using Newtonsoft.Json; using System.Text; public class HTTPManager : MonoBehaviour { public static HTTPManager instance; public string host = ""; public int port = ; public System.Action<int> getSignUpResult; public System.Action<Packets.res_nasGetUser> getGetUserResult; public System.Action<int> getSignOutResult; // 싱글톤으로 만들어주자 private void Awake() { HTTPManager.instance = this; } private void OnDestroy() { HTTPManager.instance = null; } // uri => /user/signup public void RequestSignup(string uri, Packets.req_nasSignUp packet) { StartCoroutine(this.RequestSignupImpl(uri, packet)); } private IEnumerator RequestSignupImpl(string uri, Packets.req_nasSignUp packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); Debug.Log(url); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_signup = JsonConvert.DeserializeObject<Packets.res_nasSignUp>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}", res_signup.statusCode); this.getSignUpResult(res_signup.statusCode); } else { this.getSignUpResult(500); Debug.LogFormat("에러"); } www.Dispose(); } public void RequestGetUser(string uri, Packets.req_nasGetUser packet) { StartCoroutine(this.RequestGetUserImpl(uri, packet)); } private IEnumerator RequestGetUserImpl(string uri, Packets.req_nasGetUser packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); Debug.Log(url); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_getuser = JsonConvert.DeserializeObject<Packets.res_nasGetUser>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}, nickName : {1}", res_getuser.statusCode, res_getuser.nickname); this.getGetUserResult(res_getuser); } else { Packets.res_nasGetUser res_getuser = new Packets.res_nasGetUser(); res_getuser.statusCode = 500; res_getuser.nickname = ""; this.getGetUserResult(res_getuser); Debug.LogFormat("에러"); } www.Dispose(); } public void RequestSignOut(string uri, Packets.req_nasSignOut packet) { StartCoroutine(this.RequestSignOutImpl(uri, packet)); } private IEnumerator RequestSignOutImpl(string uri, Packets.req_nasSignOut packet) { var url = string.Format("{0}:{1}{2}", this.host, this.port, uri); var www = new UnityWebRequest(url, "POST"); //객체를 -> 문자열 직렬화 var json = JsonConvert.SerializeObject(packet); //문자열 -> byte배열로 직렬화 var rawdata = Encoding.UTF8.GetBytes(json); www.uploadHandler = new UploadHandlerRaw(rawdata); //요청 www.downloadHandler = new DownloadHandlerBuffer(); //응답 www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { Debug.LogFormat("--->{0}", www.downloadHandler.text); var res_signup = JsonConvert.DeserializeObject<Packets.res_nasSignOut>(www.downloadHandler.text); //역직렬화 Debug.LogFormat("status : {0}", res_signup.statusCode); this.getSignOutResult(res_signup.statusCode); } else { this.getSignOutResult(500); Debug.LogFormat("에러"); } www.Dispose(); } }
Packets.cs – SignOut 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Packets { /* 유저 등록(/user/nasSignUp) statusCode 200 유저 등록 완료 201 이미 등록된 유저 202 중복 닉네임 500 서버 에러 */ public class req_nasSignUp { public string user_uid; public string nickname; } public class res_nasSignUp { public int statusCode; } /* 유저 검색 (/user/nasGetUser) statusCode 200 유저 검색 완료 201 등록 되지 않는 유저 500 서버 에러 */ public class req_nasGetUser { public string user_uid; } public class res_nasGetUser { public int statusCode; public string nickname; } /* 유저 탈퇴 (/user/nasSignOut) statusCode 200 유저 탈퇴 완료 201 등록 되지 않는 유저 500 서버 에러 */ public class req_nasSignOut { public string user_uid; } public class res_nasSignOut { public int statusCode; } }
RestTestMain.cs – SignOut 추가
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; public class RestTestMain : MonoBehaviour { public Button SignUpTabBtn; public Button GetUserTabBtn; public Button SignOutTabBtn; public GameObject SignUpGO; public GameObject GetUserGO; public GameObject SignOutGO; public TMP_Text tmp_User_Uid; private string user_Uid; public TMP_InputField userNickName_IF; private string user_NickName; public TMP_InputField UserUid_IF; public Button sighUpBtn; public Button getUserBtn; public Button SignOutBtn; public TMP_InputField UserUid_IF_SignOut; public TMP_Text result_Text; void Start() { this.user_Uid = tmp_User_Uid.text; this.SignUpTabBtn.onClick.AddListener(() => { this.SignUpGO.SetActive(true); this.GetUserGO.SetActive(false); this.SignOutGO.SetActive(false); }); this.GetUserTabBtn.onClick.AddListener(() => { this.SignUpGO.SetActive(false); this.GetUserGO.SetActive(true); this.SignOutGO.SetActive(false); }); this.SignOutTabBtn.onClick.AddListener(() => { this.SignUpGO.SetActive(false); this.GetUserGO.SetActive(false); this.SignOutGO.SetActive(true); }); HTTPManager.instance.getSignUpResult = (packet) => { Debug.LogFormat("HTTPManager.instance.getSignUpResult : {0}", packet) ; switch (packet) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 등록 완료", packet); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 이미 등록된 유저입니다.", packet); break; case 202: this.result_Text.text = string.Format("status_code : {0}, 중복된 닉네임 입니다.", packet); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet); break; } }; HTTPManager.instance.getGetUserResult = (packet) => { switch (packet.statusCode) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 검색 완료\n", packet.statusCode); this.result_Text.text += string.Format("NickName : {0}", packet.nickname); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 서버에 등록되지 않은 유저입니다.", packet.statusCode); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet.statusCode); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet.statusCode); break; } }; HTTPManager.instance.getSignOutResult = (packet) => { switch (packet) { case 200: this.result_Text.text = string.Format("status_code : {0}, 유저 탈퇴 완료", packet); break; case 201: this.result_Text.text = string.Format("status_code : {0}, 등록되지 않은 유저입니다.", packet); break; case 500: this.result_Text.text = string.Format("status_code : {0}, 서버가 응답이 없습니다.", packet); break; default: this.result_Text.text = string.Format("status_code : {0}, 이거 뜨면 망하는 겁니다.", packet); break; } }; this.sighUpBtn.onClick.AddListener(() => { this.user_NickName = this.userNickName_IF.text; Debug.LogFormat("TMP_InputField : {0}", this.user_NickName); if (string.IsNullOrEmpty(this.user_NickName) && string.IsNullOrEmpty(this.user_Uid)) { this.result_Text.text = string.Format("닉네임을 입력해주세요."); } else { Debug.LogFormat("{0}, {1}", this.user_Uid, this.user_NickName); var packet = new Packets.req_nasSignUp() { user_uid = this.user_Uid, nickname = this.user_NickName }; HTTPManager.instance.RequestSignup("/user/nasSignUp",packet); } }); this.getUserBtn.onClick.AddListener(() => { if (string.IsNullOrEmpty(this.UserUid_IF.text)) { this.result_Text.text = string.Format("유저의 UID를 입력해주세요."); } else { var packet = new Packets.req_nasGetUser() { user_uid = this.UserUid_IF.text }; HTTPManager.instance.RequestGetUser("/user/nasGetUser", packet); } }); this.SignOutBtn.onClick.AddListener(() => { if (string.IsNullOrEmpty(this.UserUid_IF_SignOut.text)) { this.result_Text.text = string.Format("유저의 UID를 입력해주세요."); } else { var packet = new Packets.req_nasSignOut() { user_uid = this.UserUid_IF_SignOut.text }; HTTPManager.instance.RequestSignOut("/user/nasSignOut", packet); } }); } }