728x90
728x90

안드로이드 스튜디오에서 로그인 화면을 만드는 도중에, 버튼 색을 지정하기 위해 주어진 버튼 색의 핵사값을 알아내야 했다.

 

Pixlr Editor 로 임의의 색깔의 핵사값을 알아내보자.

 

Step 1)부터 하면 문제가 발생하니 Step 3) -> Step2) Step 4) 순서로 진행하면 된다.

 

Step 1) 알아내고자 하는 색이 포함된 이미지의 url 복사

 

  • 링크를 복사한다.

 

 

Step 2) pixlr editor 오픈

 

 

 

Step 3) step 1에서 복사한 url 붙여넣기

OPEN IMAGE FROM URL 을 클릭한다.

  • IOErrorEvent type="ioError" bubbles=false cancleable=false eventPhase=2 text="Error
  • 에러가 발생했다.

 

 

 

  • 새 탭을 열어서 이미지 주소를 복사한다.

위의 방법으로 하면 문제가 해결된다. 

 

 

 

 

Step 4) 색상코드 추출

  • 왼쪽의 스포이드 모양의 아이콘을 클릭하고 “Log in” 버튼 컬러를 클릭한다.

  • 왼쪽의 박스 색이 바뀌고 이를 클릭하면 위와 같이 창이 뜬다.
  • #00b2ed이 Log in 버튼의 색이다.
728x90
728x90

참고 : 유투브 — 센치한 개발자

 

 

 

[레이아웃]

  • MainActivity.java 파일의 line12를 보면 activity_main.xml 파일과 연결이 되어 있는 것을 확인할 수 있다.

 

 

[1. LinearLayout]

  • 화면을 구성하기 위해서 가장 바깥의 레이아웃을 정해야 한다.
  • RelativeLayout 혹은 LinearLayout 중에 선택할 수 있다.
  • LinearLayout 안의 요소들은 가로 혹은 세로로 배치가 된다.

 

 

  • LinearLayout 안에 3개의 TextView를 horizontal 방향으로 배치해 보았다.

 

  • vertical 방향으로 배치해 보았다.

 

 

[2. RelativeLayout]

  • RelativeLayout 안의 요소들은 서로 관계를 정의해야 한다.
  • 아직 관계를 정의해주지 않아서 TextView 세 개가 함께 겹쳐있는 것을 확인할 수 있다.

 

line 12,20,28 추가

  • 부모(RelativeLayout)와 자식(TextView)의 관계를 설정해 준 상태이다.
  • 화면의 가운데로 1,2,3 이 간 것을 확인할 수 있다.
  • 아직 자식들간의 관계를 설정해주지 않아 1,2,3 이 함께 겹쳐있는 상태이다.

 

  • 1,2,3을 화면 가운데에 가로로 배치해보자.
  • line 18 : 2를 기준으로 잡기 위해 id를 설정한다.
  • line 23: 2를 부모(RelativeLayout)를 기준으로 center 에 위치시킨다.
  • line12,13 : 1을 2의 왼쪽으로 배치시킨다.
  • line 31,32 : 마찬가지로 3을 2의 오른쪽으로 배치시킨다.

 

  • 이번엔 1,2,3 을 화면 가운데에 세로로 배치해보자.
  • 위와 같은 방식으로 하면 되는데, 2를 기준으로 잡고 ‘1과 2의 관계’ ‘2와 3의 관계’ 를 설정해주면 된다.
  • 앱 구현 시 퍼포먼스 측면에서 RelativeLayout이 더 좋다.

 

 

[3. Layout 안에 Layout 배치하기]

 

 

[4. 화면 등분 하기]

  • line 6 : 전체 합을 9로 설정한다.
  • line 14,24,35 : 화면을 각각 3/9, 즉 1/3 씩 차지하겠다는 뜻이다.

 

  • line 14,24,35 : weight를 1/9,7/9,1/9 로 나눈 결과이다.

 

728x90
728x90

 

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

 

로그아웃 기능을 구현해보자.

로그아웃 기능 구현 과정은 아래의 세가지 단계로 나눠 생각해볼 수 있다.

 

1. 로그아웃 route 만들기

2. 로그아웃하려는 유저를 DB에서 찾기

3. 그 유저의 토큰 삭제

 

 

index.js 파일에 아래의 코드를 추가해주자.

app.get('/api/users/logout', auth, (req,res) => {

    User.findOneAndUpdate({_id: req.user._id},
        {token: ""}             //토큰을 지워준다
        , (err,user) => {       //콜백 함수
            if(err) return res.json({success: false, err});
            return res.status(200).send({
                success: true
            })
        })
})

 

미들웨어 auth에서 설정해준 req로 유저 아이디를 찾아서 정보를 업데이트(findOneAndUpdate) 해준다.

 

 

 

이제 로그아웃 기능을 확인해보자.

 

MongoDB에서 확인해보면, token이 있는게 로그인된 것이다. 이 유저를 로그아웃 시켜보자.

먼저 'npm run start'로 서버를 켜고, postman에서 send를 보내 로그인한다.

 

 

 

 

그 후 get을 해보면

위 그림과 같이 로그아웃에 성공한 것을 확인할 수 있다.

728x90
728x90

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

 

Auth route 를 만들어보자.

로그인 된 유저만 게시판에 글을 쓸 수 있게 한다던가, 지정된 페이지에 접근할 수 있게 하는 기능을 위한것이다.

 

 

- 저번 시간 복습

 

- 토큰 생성 후 User 정보에 넣고 Server에는 UserDB에 넣고, Client에서는 쿠키에 저장했다.

- 그리고 Server의 Token과 Client의 Toekn을 계속 비교하면서 맞는지 체크한다. 

 

- 만약 유저가 A page -> B page 로 이동할때, B page에 접근 가능한지 체크하는 과정

     1) Client에서 쿠키에 담긴 정보를 Server에 전달한다.

     2) Server는 Encode 된 쿠키를 받아서 Decode를 하고 그러면 User ID 가 나온다. ID 가 Server 쪽의 User DB에 있으면 인증되는 것이다. ('user._id + 'secrete Token' 해서 토큰을 생성했음. 디코드할때는 secretToken을 넣으면 user._id가 나옴.

그래서 user)

 

 

[결론]

1. Cookie에서 저장된 Token을 Server에서 가져와서 복호화를 한다.

2. 복호화를 하면 User ID가 나오는데 그 User ID를 이용해서 데이터베이스 User Collection에서 유저를 찾은 후 쿠키에서 받아온 token이 유저도 갖고 있는지 확인한다.

3. 쿠키가 일치하면 Authentication이 true이다. 그리고 그에 해당하는 유저의 정보들을 

 

 

Step 1) findByToken 메소드 작성

- 가져온 토큰을 디코드하는 findByToken 메소드를 User.js에 정의해보자 

userSchema.statics.findByToken = function(token,cb){
    var user = this;

    //가져온 토큰(token)을 디코드한다.
    jwt.verify(token, 'secretToken', function(err,dcoded) {

        //유저 아이디(decoded)를 이용해서 유저를 찾은 다음,
        //클라이언트에서 가져온 token과 DB에 보관된 token이 일치하는지 확인


        //findOne()는 MongoDB에 이미 있는 함수임. id와 token으로 찾을것
        user.findOne({"_id" : decoded, "token": token}, function(err,user){
            if(err) return cb(err)  //에러 있으면 콜백으로 에러 전달
            cb(null, user)          //에러 없으면 유저 정보 전달
        })
    })
}

 

 

아래의 형식으로 디코드한다. (참고 : www.npmjs.com/package/jsonwebtoken)

jwt.verify(token, 'shhhhh', function(err, decoded) {
        console.log(decoded.foo) // bar
      });

 

 

 

 

 

Step2) 미들웨어 생성

middleware폴더를 생성하고 그 아래에 auth.js 파일을 생성한다. 이곳에서 유저 인증을 처리해보자.

 

      - 미들웨어 : endpoint에서 request를 받은 다음 call back function 실행 전에 중간에서 실행되는 것. 

 

작성한 코드는 아래와 같다.

const { User } = require('../models/User');



let auth = (req, res, next) => {


    //인증 처리를 하는 곳 
    //1. 클라이언트 쿠키에서 토큰을 가져온다. cooike-parser 이용
    let token = req.cookies.x_auth;

    //2. 토큰을 복호화한 후 유저를 찾는다. 유저 모델에서 메소드 만들어서 
    User.findByToken(token, (err,user) => {
        if(err) throw err;
        if(!user) return res.json({ isAuth: false, error: true})    //유저가 없을 때. 클라이언트에 전해줌.


        //유저가 있으면 유저 정보 넣어줌 ~> User.js에서 req를 통해 유저 정보에 접근 가능해짐 
        req.token = token;
        req.user = user;
        next(); //미들웨어 끝나고 다음으로 넘어갈 수 있도록 해줌 
         
    })
    //3. 유저가 있으면 인증 Ok
    //4. 유저가 없으면 인증 NO

}

module.exports = {auth};     //auth를 다른 파일에서도 쓸 수 있게 해줌

 

 

 

 

 

Step 3) index.js- 인증 부분 추가

//Authentication 인증 부분
app.get('/api/users/auth', auth , (req,res) => {    //auth : 미들웨어 -> 


    //미들웨어 auth에 문제 생겨서 false가 되면 미들웨어내에서 return돼서 다른 곳으로 빠져나감. 
    //즉, 여기까지 미들웨어를 통과해 왔다는 얘기는 Authentication이 True 라는 말
    //True니까 유저 정보를 클라이언트에 전달해주면 됨

    res.status(200).json({
        _id: req.user._id,
        isAdmin: req.user.role === 0 ? false : true,        //관리자 유저인지 아닌지. role이
        isAuth: true,
        email: req.user.email,
        name: req.user.name,
        lastname: req.user.lastname,
        role: req.user.role,
        image: req.user.image

    })

})

 

 

만약, A page 의 어드민의 role이 1이고, B page의 어디민의 role이 2이라면 그때에 따라 isAdmin 줄의 코드는 다르게 작성할 수 있다.

지금은 role==0이면 일반 유저, role != 0 이면 관리자라고 가정해서 위와 같이 코드를 작성했다.

 

 

 

 

 

 

 

 

 

 

728x90
728x90

 

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

 

로그인 기능을 구현해보자.

Step 1) Login Route 만들기

 

[로그인 라우터에서 할 일]

1) 요청된 이메일이 디비에 있는지 찾는다.

2) 요청된 이메일이 디비에 있다면 유저가 입력한 비밀번호가 맞는 비밀번호인지 확인

3) 비밀번호까지 맞다면 토큰 생성 (npm install jsonwebtoken — save 라이브러리 설치 해아함.) 

 

 

index.js 에 아래의 함수를 추가한다.

쿠키에 토큰을 저장하기 위해

$npm install cookie-parser --save

위의 명령어로 라이브러리를 다운한다.

 

const cookieParser = require('cookie-parser');
app.use(cookieParser());




//로그인 기능 
app.post('./login',(req,res) => {


    //로그인 라우터에서 할 일 
    //1. 요청된 이메일이 디비에 있는지 찾는다.
    User.findOne({email: req.body.email }, (err,user) => {
        if(!user) {
            return res.json({
                loginSuccess: false,
                message: "제공된 이메일에 해당하는 유저가 없습니다."
            })
        }
    
        //2. 요청된 이메일이 디비에 있다면 유저가 입력한 비밀번호가 맞는 비밀번호인지 확인 
        user.comparePassword(req.body.password, (err,isMatch) => {
            if(!isMatch)    //비밀번호 틀렸으면 틀렸다고 알려주는 response를 clinet에게 줌
                return res.json({loginSuccess: false, message: "비밀번호가 틀렸습니다." })
            

            //3. 비밀번호까지 맞다면 해당 유저를 위한 토큰 생성
            user.generateToken((err, user) => {
                if(err) return res.status(400).send(err);   //client에게 에러 있다고 알려주고(400), 에러 메세지도 함께 send
                
                //token을 저장한다. 어디에? 여러군데에 할 수 있음. 쿠키, 로컬스토리지,세션,,, 
                //어디가 안전한지에 대해 논란 많은데 여기선 쿠키에 할 것! (각각 장단점이 있음)

                res.cookie("x_auth", user.token)			//x_auth는 임의로 설정한 값
                .status(200)    //성공했다고 알려줌
                .json({loginSuccess: true, userId: user._id})

            })    
            
        })
    })
})

 

 

 

비밀번호가 일치할 때 토큰을 생성하기 위해 아래의 명령어로 jsonwebtoken 라이브러리를 다운해야한다.

$npm install jsonwebtoken --save

- 참고  : www.npmjs.com/package/jsonwebtoken

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric)

www.npmjs.com

 

 

 

그 후 User.js에도 아래의 함수를 정의해준다.

const jwt = require('jsonwebtoken');



//함수 정의     
userSchema.methods.comparePassword = function(plainPassword, cb){   //cb : callback function
    
    //암호화된 비밀번호 복호화 불가 -> plain password를 암호화해서 그 결과값 비교해봐야함
    bcrypt.compare(plainPassword, this.password, function(err,isMatch){
        if(err) return cb(err);
        cb(null, isMatch)
        

    })
}


userSchema.methods.generateToken = function(cb) {
    var user = this;
    
    //jsonwebtoken을 이용해서 token 생성하기 
    var token = jwt.sign(user._id.toHexString(),  'secretToken')

    user.token = token
    user.save(function(err,user){
        if(err) return cb(err)  //에러 발생시 콜백으로 에러 전달

        cb(null, user)      //에러 발생 안하면 err는 null이고 user 정보 전달
    })

}

 

 

 

Step 2) 로그인 기능 확인

 

이제 실제로 로그인해보자.

여기서 세번째걸로 로그인 테스트를 해볼 것이다.

 

 

서버를 켠 후, Postman을 이용해서 email과 password를 send 해보자.

$npm run start

로 서버를 켠다.

 

그리고 postman에서 send 를 한다.

 

 

이때 password가 maxLength 즉 설정해놓은 50보다 넘어가서 오류가 발생했다. User.js파일에서 password의 maxLength를 100으로 고친 후 다시 send 하니 정상적으로 처리된 것을 확인할 수 있었다.

728x90
728x90

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

소스 안의 비밀 정보를 보호해보자.

MONGO DB의 connection string 를 gitignore에 추가하여 github에 올라가지 않게 한다.

 

  • 두가지 개발환경을 따로 생각해야한다.

 

 

 

Step 1) config폴더 아래에 파일 생성

  • dev.js

  • prod.js

  • key.js

 

 

 

 

Step2) index.js 파일 수정

const config = require('./config/key');

추가하고

 

 

const mongoose = require('mongoose')
mongoose.connect(config.mongoURI,{
    useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false
}).then(() => console.log('MongoDB Connected...'))
.catch(err => console.log(err))

에서 connect 함수의 첫번째 파라미터 값을 변경한다.

 

 

 

Step 3) Heroku 사이트 설정

Config Vars에 key는 MONGO_URI로 value는 connection string 으로 설정한다.

이후 ‘npm run start’로 실행하여 정상적으로 연결됨을 확인한다.

 

 

 

Step 4) dev.js 제외하고 git에 push 하기

.gitignore 에 dev.js를 추가하고

$ git commit -m "비밀 정보 보호"
$ git push origin main

으로 커밋과 푸시를 한다.

 

 

 

Step 5) Bcrpyt로 비밀번호 암호화하기

client가 입력한 비밀번호를 암호화한 뒤 DB에 저장해보자.

$ npm instll bcrypt --save

 

 

www.npmjs.com/package/bcrypt

 

bcrypt

A bcrypt library for NodeJS.

www.npmjs.com

 

에서 Technique1의 코드를 가져온다.

User.js에 아래와 같이 코드를 추가한다.

 

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const saltRoudns = 10  //암호화하는데에 필요한 salt의 글자 수(길이)


const jwt = require('jsonwebtoken');

const userSchema = mongoose.Schema({
    name:{
        type: String,
        maxLength: 50
    },
    email: {
        type: String,
        trim: true,      //공백 없애줌 
        unique: 1
    },
    password: {
        type: String,
        maxLength: 50
    },
    lastname: {
        type: String,
        maxLength:50
    },
    role: {
        type: Number,
        default: 0
    },
    image: String,
    token: {    //유효성 관리 
        type: String
    },
    tokenExp: { //토큰 사용 가능한 유효기간 
        type: Number
    }
})



//저장하기 전에 비밀번호를 암호화시킨다. index.js의 save 함수 실행 전에! 
userSchema.pre('save', function(next){
    var user = this;

    if(user.isModified('password')){//비밀번호를 바꿀때만 암호화해야함. 이메일 바꿨는데 비밀번호가 암호화 되면 x 

        bcrypt.genSalt(saltRoudns, function(err,salt){
            if(err) return next(err)


            //user.password : client가 입력한 비밀번호
            //hash : 암호화된 비밀번호 
            bcrypt.hash(user.password, salt, function(err, hash){
                if(err) return next(err)
                user.password = hash        //해시된 비밀번호로 교체
                next()
            })
        })
    } else{ //다른거 바꿀때는 다음으로 넘어감 
        next()
    }
}) 


//함수 정의     
userSchema.methods.comparePassword = function(plainPassword, cb){   //cb : callback function
    
    //암호화된 비밀번호 복호화 불가 -> plain password를 암호화해서 그 결과값 비교해봐야함
    bcrypt.compare(plainPassword, this.password, function(err,isMatch){
        if(err) return cb(err),
        cb(null, isMatch)
        

    })
}

userSchema.methods.generateToken = function(cb) {


    var user = this;
    
    //jsonwebtoken을 이용해서 token 생성하기 
    var token = jwt.sign(user._id,  'secretToken')

    user.token - token
    user.save(function(err,user){
        if(err) return cb(err)  //에러 발생시 콜백으로 에러 전달

        cb(null, user)      //에러 발생 안하면 err는 null이고 user 정보 전달
    })

}

const User = mongoose.model('User', userSchema)

module.exports = {User}         //이 스키마를 다른 파일에서도 쓸 수 있게 함 

 

 

 

 

  • POSTMAN에서 다시 send 를 한 뒤 MongoDB에서 확인해보니 password가 암호화되어 저장된 것을 볼 수 있었다.

728x90
728x90

 

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

 

Step 1) Body-Parser 설치

Body-Parser라는 Dependency를 이용하여 Client에서 보내는 자료들(이름, 이메일 등)을 서버에서 분석해서 받을 수 있도록 한다.

 

$ npm install body-parser --save

 

 

Step 2) POST MAN 설치

Client에서 Request를 줘야하는데 현재 Client 가 없으니 POSTMAN을 이용해서 request 를 보낸다.

구글에서 postman을 검색하여 다운받자.

 

 

Step 3) Register Router 만들기

회원 가입을 위한 Router를 만들어보자.

  • index.js 파일에 코드를 추가하여 아래와 같이 작성한다.
const express = require('express')
const app = express()
const port = 5000

//body-parser 와 User 가져오기
const bodyParser = require('body-parser');
const {User} = require("./models/User");

//bodyParser에 옵션주기
app.use(bodyParser.urlencoded({extended: true}));   //Clinet가 보낸 application/x-www-form-urlencoded로 된 데이터를 분석해서 가져올 수 있도록 함
app.use(bodyParser.json());                         //이건 application/json 형태의 데이터 가져올 수 있게 함

const mongoose = require('mongoose')
mongoose.connect('mongodb+srv://nanyoung:<비밀번호>@cluster0.5wf88.mongodb.net/<dbname>?retryWrites=true&w=majority',{
useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false
	}).then(() => console.log('MongoDB Connected...'))
	.catch(err => console.log(err))
    
    
app.get('/', (req, res) => {
	res.send('Hello World!')
})

app.post('/register', (req,res) => {
//회원 가입할 때 필요한 정보들을 Client에서 가져오면
//그것들을 DB에 넣는다.

const user = new User(req.body)

//req.body에는 아래와 같이 body-parser를 이용해서 json 형태로 받은 데이터 들어있음
// {
//     id: "hello"
//     password: "123"
// }

user.save((err, userInfo) =>{
	if(err) return res.json({success: false, err})  //실패하면 에러메세지를 json 형태로 출력
		return res.status(200).json({   //status(200)은 성공했다는 뜻
		success: true
	})
	}) //MongoDB에서 오는 메소드
})

app.listen(port, () => {
	console.log(`Example app listening at http://localhost:${port}`)
})

app.listen(port, () => {
	console.log(`Example app listening at http://localhost:${port}`)
})

 

그 후

$ npm run start

로 application을 실행한다.

 

 

 

Step 4) Post man 으로 실제로 회원가입하기

성공

 

 

 

 

Step 5) NODE MON 다운로드

  • NODE MON : 소스를 변경할 때 그걸 감지해서 자동으로 서버를 재 시작해주는 툴
$ npm install nodemon --save -dev
  • dev : development(로컬)과 production(배포 이후) 두가지 버전 중 전자에 해당.

 

 

Step 6) NODEMON으로 시작하기

package.json 파일에 아래와 같이 Line8 을 추가한다.

 

 

그 후 

$npm run backend

로 서버를 실행해보자.

728x90
728x90

출처 : 인프런_따라하며 배우는 노드, 리액트 시리즈 — 기본 강의

 

 

Step 1) Model Schema 작성

Model : Schema를 감싸주는 역할이며 Shema는 정보를 지정해주는 역할을 한다.

 

 

 

Step 2) Git 설치와 commit

Git : 분산 버젼 관리 시스템

git을 다운로드하고 아래의 명령어로 잘 설치됐는지 확인한다.

$git --version

 

아래의 명령어로 git 저장소를 만들어준다.

$git init

라이브러리들을 제외하고 저장소에 올리기 위해 .gitignore 파일을 생성한다.

.gitignore파일에 node_module(라이브러리 폴더)를 입력해서 이 폴더를 제외하고 git commit 을 실행한다. (Local 저장소에 올라감)

참고

 

 

 

Step 3) SSH 설정하기

내 노트북과 GITHUB 사이에서 안전하게 통신하기 위해 Secure Shel(SSH)를 설정해보자.

  • 참고사이트

docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

 

Generating a new SSH key and adding it to the ssh-agent - GitHub Docs

Generating a new SSH key and adding it to the ssh-agent After you've checked for existing SSH keys, you can generate a new SSH key to use for authentication, then add it to the ssh-agent. Mac Windows Linux If you don't already have an SSH key, you must gen

docs.github.com

 

 

$ ls -a ~/.ssh

위 명령어를 실행했을때 아무것도 안나오면 SSH 설정이 안 된것이다.

.

$ ssh-keygen -t ed25519 -C "nanyoung@gmail.com"
$ eval "$(ssh-agent -s)"
$ ssh-add -K ~/.ssh/id_ed25519
$ pbcopy < ~/.ssh/id_ed25519.pub

터미널에서 차례로 위 명령어를 실행한다.

 

그 후 VSCode로 아와서 아래의 명령어를 실행하여 이전에 만들어놓은 Remote Repository에 push한다.

$ git remote add origin https://github.com/NanyoungKim/boiler-plate-ko.git
$ git branch -M main
$ git push -u origin main
728x90

+ Recent posts