자바스크립트에서도 다른 언어와 마찬가지로 && (and의 의미)와 || (or의 의미)라는 비교연산자가 있다. 그러나 다른 언어에서는 이들이 단순히 true 또는  false의 값만 리턴하는 것과 다르게, JS에선 이를 변수 할당에 이용할 수 있다. 단순히 bool 타입의 변수 할당이 아닌 다른 값(예를 들면 문자열)등을 할당할 때도 이들을  활용 가능하며, 상당히 직관적이다.

 

// sample
let ex0 = 1234;
let ex1 = false;

let ex2 = ex0 || 100;  // ex2 = 1234
let ex3 = ex1 || 100;  // ex3 = 100;

사실 공부중에 이렇게 할 수 있다는 걸 알게 됐는데, 처음엔 "어떤 의미인지는 대충 알겠는데 이게 돼?" 였다. 지금까지 나는 이런 상황에선 3항 연산자를 사용해서 또는 if문을 활용해서 할당해왔기 때문. 정리하자면 ||는 피연산자를 리턴할 수 있는데(bool타입이 아닌 피연산자도 리턴가능하다!!), 첫 번째 피연산자가 거짓이면 두 번째 피연산자의 값을 리턴하고 그렇지 않으면 첫 번째 피연산자를 리턴한다고 한다. 즉 첫 피연산자가 참으로 평가되면 첫 피연산자를, 첫 피연산자가 거짓으로 평가되면 두 번째 피연산자를 리턴한다는 것! 이 때 '거짓'으로 평가되는 것은 직접적으로 bool타입의 false 뿐만 아니라 빈 배열([]), 빈 문자열(''), 0, null, undefined, NaN 등이 있다.

 

이 녀석의 활용법은 무궁무진할 것이다. 예를 들어 b라는 변수에 a라는 배열의 마지막 값을 할당하고 싶지만 a가 빈 배열이면 1을 할당하고 싶을 땐 다음과 같이 심플하게 끝낼 수 있다.

let a = [1, 2, 3, 4];
let b = a[a.length - 1] || 1;

a가 빈 배열이라면 a[a.length - 1]이 undefined가 되고 이는 false로 평가되기 때문에 1이 할당될 것이다. 

 

 

지금까진 ||를 변수 할당 시에 이용해먹는 방법이 대해 알아봤고, 이젠 &&를 변수 할당 시에 이용할 수 있는 방법을 소개하겠다. 나는 ||는 직관적으로 잘 이해된 것에 비해 &&가 살짝 헷갈렸는데, 이 연산자들의 성질을 안다면 이해하기 좀 쉬울 것이다. 이 논리연산자들의 성질은 다음과 같다.

 

1. ||는 첫 번째 피연산자가 true면 뒤에 놈은 신경도 안 쓰고 바로 true를 내뱉는 성격이 급한 애다. 뒤에 놈은 첫 번째 피연산자가 false일 때만 쳐다본다.

2. &&는 첫 번째 피연산자가 false면 뒤에 놈은 신경도 안 쓰고 바로 false를 내뱉는 성격이 급한 애다. 뒤에 놈은 첫 피연산자가 true일 때만 쳐다본다.

 

이걸 학교 과제에서 이용할 때 ||이나 &&의 좌우로 수식을 써놓고 특정 상황에선 그 수식이 수행되고 어떤 상황에선 안 수행되고 이런 식으로 코드를 짰었는데..

 

암튼 각설하고, ||가 첫 피연산자가 참으로 평가되면 첫 피연산자를 리턴하고 그게 아니면 두 번째 피연산자를 리턴했듯이, 

&&는 첫 피연산자가 거짓으로 평가되면 첫 번째 피연산자를 리턴하고 그게 아니면 두 번째 피연산자를 리턴한다. 바로 위에서 소개한 성질이 있으니까! 

 

즉 다음 코드의 결과는 a = null이다.

a = 100 && 200 && null && 300; // a = null

 

참고로..엄밀히 말하자면 ||의 경우 첫 피연산자가 참으로 평가되면 첫 피연산자를, 그게 아니면 두 번째 피연산자를 리턴한다고 했는데 사실 왼쪽에서 오른쪽으로 피연산자를 하나하나 평가하면서 참으로 평가되는 녀석이 있으면 바로 그 녀석을 리턴하고, 모든 피연산자가 거짓으로 평가되는 경우엔 마지막 피연산자를 리턴하는 것이다. 근데 결론적으론 첫 피연산자가 거짓으로 평가되면 두 번째 피연산자를 리턴하는 꼴과 같다는 말에서 이렇게 쓴 것. &&도 이와 마찬가지다

 


이 글을 쓰고 나중에 다른 곳에서 강의를 들으며 이 내용이 나와서 정리.

JS에서 &&는 왼쪽 값이 true로 평가되면 오른쪽 값을 리턴. 반대로 왼쪽 값이 false로 평가되면 그 값을 리턴

JS에서 ||는 왼쪽 값이 true로 평가되면 왼쪽 값을 리턴, 반대로 왼쪽 값이 false로 평가되면 오른쪽 값을 리턴

이 두 줄로 정리된다.

 

※ 아래 영상을 보고 개인공부를 위해 정리할 겸 작성한 글입니다. 

https://www.youtube.com/watch?v=6fc9NAQkcv0&t=4s 

원작자의 허락을 받았으며, 문제가 될 시 본 글은 삭제조치하겠습니다 :)

 


1. DNS란 무엇인가?

Domain Name System의 줄임말이다. www.naver.com이란  란 url이 있을 때, naver.com이 도메인에 해당하고 www는 호스트 네임에 해당하는 부분이다.

 

2. 근데 잠깐! 도메인은 왜 있는거야?

우리가 어느 웹사이트에 들어가려 하면, 우리가 쓰는 웹 브라우저(ex : 크롬, 사파리 등)이 그 사이트를 제공하는 지구의 어딘가에 있는 서버에다가 요청 즉 request를 해야 한다. 이를 위해선 이 서버의 IP주소를 알아야 한다. 그런데 사실 모든 웹 사이트의 IP주소를 하나하나 외우고 다니는 건 힘드니까..친구들 전화번호 하나하나 외우기 싫어서 전화번호부 만드는 것처럼, 이 IP주소들을 key : value처럼(전화번호부 예로는 친구이름 : 전화번호) 특정이름 : IP주소 관계로 만들면 좋겠다고 사람들이 생각한거지.  여기서 특정이름에 해당하는 부분이 도메인.

 

3. 도메인을 IP주소와 대응시킨 거구나. 그럼 이 '전화번호부'가 저장되는 곳이 따로 있어?

그게 바로 DNS! 근데 System이란 말에서 알 수 있듯이 이 전화번호부가 어느 한 군데에 싹 몰려 있는게 아니다! 다층적으로 구성된 네트워크에 분산되어 있다.

 

4. DNS의 동작원리 간단하게 한 입

내 컴퓨터에서 www.naver.com에  에 접속하려는 상황이라고 하자. 그러면 naver사이트를 제공하는 서버에다가 request를 해야 하는데 그 서버의 IP주소를 현재 모르는 상태다! 이 때 브라우저는 PC에 설정된 로컬 DNS서버에 naver.com이라는 도메인과 www이라는 호스트 네임을 가지는 IP를 갖고 있는지 물어본다. (이 때 로컬 DNS서버는 통신사마다 다르며 사용자가 다른 곳으로 바꿀 수도 있음) 이 로컬 DNS서버엔 내가 원하는 IP주소가 이미 캐싱(caching)돼있을 수도 있고 아닐 수도 있는데, 캐싱돼있다면 바로 그 주소를 가져다가 쓰면 되고 없다면 다른 곳을 거쳐서 가져와야 한다.

 

여기서 '다른 곳을 거쳐오는 작업'은 우선 첫 번째로 Root DNS 서버에 이 주소(www.naver.com)에 해당하는 IP주소를 어디서 찾을 수 있냐고 물어본다. Root DNS 서버는 이에 대한 응답(response)로 .com으로 끝나는 도메인들을 담당하는 DNS 서버의 IP주소를 돌려준다! 이를 통해 로컬 DNS서버가 .com을 담당하는 DNS 서버에게 찾아가 내가 원하는 주소의 IP주소가 어딨느냐고 물으면, .com 담당 서버는 이에 대한 응답으로 naver.com의 도메인 정보를 가진 서버의 IP주소를 준다! 다시 이를 통해 로컬 DNS 서버가 naver.com의 도메인 정보를 가진 DNS 서버에게 찾아가고, 거기엔 여러 호스트 네임별(www, mail, blog 등)로 IP주소가 있는데 그 중 www와 매칭되는 IP주소 즉 www.naver.com의  IP주소를 준다. 이를 로컬 DNS서버가 브라우저에게 반환하면 비로소 www.naver.com의  의 서버로 접속하게 되는 것.

 

(개인적으론 컴퓨터 구조 시간에 배운 메모리, 캐시 등의 관계가 DNS서버간에도 있다는 게 신기했다)

 

5.  아니 그러면 DNS 서버들에 문제가 생기면 인터넷도 못하는거야?

Yes. 정확히 말하자면 DNS서버들에 문제가 생기면 전화전호부를 못 쓰게 되는 것이니 도메인을 통한 접속만 안되는 거고, IP주소를 안다면 그것을 활용한 접속이 가능. 그러나 IP주소로 직접 접근하는 걸 막아놓은 사이트는 아예 못 쓰는 것이 된다.

 

6. 가만 생각해보니, 해커가  DNS를 해커가 악의적으로 조작할 수 있을 것 같아

맞다. 해커가 악의적으로 내가 원하는 사이트의 IP주소가 아니라 다른 엉뚱한 사이트의 IP주소를 알려주도록 할 수 있다. 이를 DNS 스푸핑(DNS spoofing)이라 함!

 

7. 근데 로컬 DNS서버를 바꾼다는 건 뭐야?

로컬 DNS서버는 일반적으로 통신사 것으로 설정돼있는데, 이걸 수정한다는 것은 정부에서 막아놓은 사이트에 접속하거나 국가검열받은 전화번호부 대신 외국의 전화번호부를 쓴다는 것과 같은 의미! 또는 특정 서비스를 보다 빠르게 이용하기 위해 로컬 DNS서버를 바꾸기도 함. 예를 들어 기본 로컬 DNS서버를 구글의 서버 주소로 세팅하면 유튜브처럼 구글에서 제공하는 서비스를 보다 빠르게 이용가능! (그러나 다른 서비스들은 느려질 수 있으니 그냥 쓰던 대로 쓰자..)

'WEB > 그 외 필요한 지식' 카테고리의 다른 글

[짧] 단방향 암호화 vs 양방향 암호화  (0) 2023.01.24
세션 인증 방식 vs 토큰 인증 방식  (2) 2023.01.24
HTTP 상태 코드  (0) 2022.07.12
HTTP의 특징(stateless 등..)  (0) 2022.07.06
JWT(JSON WEB TOKEN)  (0) 2022.06.22

state?

: 리액트에서 데이터를 다룰 때 사용하는 것으로, props가 부모 컴포넌트에서 자식 컴포넌트로 값을 전달할 때 사용하는 것이었다면 state는 컴포넌트 자기 자신이 갖는 값을 의미한다. props의 주인은 부모이지만 state의 주인은 나! 인 느낌.

 

이 state의 값이 바뀔 때마다 얘를 갖고 있는 컴포넌트들이 새로 렌더링되며, state는 다음과 같이 만들 수 있다.

import { useState } from 'React';

function Component(){
	const [num, setNum] = useState(1);
    
	return(
    	<>
        </>
	)
}

export default Component

Component란 컴포넌트에서 num이란 이름의 state를 만든 모습이다. 보통 이렇게 Destrucrturing 문법으로 작성한다. 초기엔 useState를 통해 초깃값을 할당하는데 파라미터로 준 값이 초깃값이 된다. setNum은 setter함수라고 부르며 보통 state이름 앞에 set을 붙이고 camel case로 명명한다. state를 변경하는 것은 기존에 하던 것처럼 num = 5 이런 식으로 하면 안되고, 이 setter함수를 이용해야 한다. 예를 들어 setNum(5)를 해야 num이란 state가 5로 바뀐다. 

 

 

참조형 state?

js를 공부하다보면 참조형 변수라는 걸 만나게 된다. 기본형 변수는 변수에 값을 그대로 할당하는 반면 참조형 변수는 값의 주소를 할당한다는 점(즉 참조한다)에 차이가 있다. 참조형의 예로는 객체, 배열 등이 있다.

 

예를 들어 let a = 1; 을 하면 a라는 변수를 위한 공간이 메모리의 100번지에 마련되고, 100번지에 해당하는 공간에 1이란 값이 들어간다. 즉 값이 그대로 할당되는 것. 그러나 let b = [1, 2, 3]을 하면 b라는 변수를 위한 공간이 메모리의 101번지에 마련되지만 이 101번지에 해당하는 공간에 [1, 2, 3]이 아니라 메모리 어딘가에 만들어둔 [1, 2, 3]의 주소가 할당되는 것이다.

 

즉 js에선

let b = [1, 2, 3];
let c = b;
c[2] = 5;

console.log(b);
console.log(c);

 

출력되는 두 결과가 [1, 2, 5]로 같다. 

 

암튼, 리액트도 js를 기반으로 만들어진 놈이니 state를 다룰 때 state를 배열같은 걸로 해준다면, 참조형을 다루는 것이므로 예기지 못한 상황에 직면할 수 있다.  

 

다음과 같은 state를 만들었는데, 배열을 사용하는 놈이라고 하자.

const [list, setList] = useState([]);

이 때 다음 코드를 실행한 결과는 무엇이 될까?

list.push(5)
setList(list)

당연히 이 코드를 작성한 사람이 원한 것은 list에 5를 추가하는 것인데, setter함수로만 list를 조작할 수 있으니 push를 해주고 setList를 통해 list를 다시 설정해주는 것. 그러나 이렇게 하면 list state에는 아무런 변화가 없다..!

list는 배열이니까 주소를 갖고 있는데, push하던 뭘하던 주소엔 변화가 없으니까 리액트는 상태가 바뀌었다고 판단하지 않는 것.

 

그래서 참조형 변수를 state로 활용할 때 state를 변경하고 싶다면 새로운 참조형 변수를 만들어야 한다. 위와 같은 상황에서 가장 쉬운 방법은 Spread문법을 활용하는 것.

setList([...list, 5]);

 

 

※ spread문법

펼치다 라는 뜻을 갖는 문법.

let a = [1, 2, 3, 4];가 있다고 하자. a는 배열이다. 그럼 a를 펼치면 뭐가 되는가? 1, 2, 3, 4가 된다.

...은 그런 '펼치는' 역할을 해준다.

list라는 배열이 있고 [1, 2, 3, 4]일 때, 여기에 5를 push한 새 배열을 만들고 싶다. 그러면 [...list, 5]를 해주면 된다. list를 펼친 1, 2, 3, 4가 그대로 ...list에 들어간다고 생각하면 됨.

 

객체에서도 spread문법을 활용가능하다. 다음처럼. 얘도 똑같~~이 펼치다 라는 뜻에 주목해서 보면 됨.

const obj1 = {
    name : "JSH",
    age : 24
}

const obj2 = {
   ...obj1
   gender : "man"
}

// obj2는 name, age, gender프로퍼티를 가지며 value는 각각 "JSH", 24, "man"

props에 대해 정리해보자.

JSX문법에서 컴포넌트 작성 시 컴포넌트에 지정한 속성들을 props라 부른다. properties의 약자이며, 컴포넌트에 속성을 지정해주면 얘네들이 하나의 객체로 모여서 컴포넌트를 지정한 함수의 첫 번째 파라미터로 전달된다! 이 때 파라미터 이름은 통상 props로 해주는 게 깔끔. 이 때 props로 전달하는 것은 함수도 가능하다.

 

ex)

import React from 'react';
import Jofe from './jofe';

function App(){
    const func = function(){
        alert("Hi!");
    }
    return (
        <>
            <Jofe name="lje" age={23} func={func}/>
        </>
    );
}

export default App;

 

이렇게 App.js에서 Jofe라는 컴포넌트를 사용하는데 이런 식으로 props들을 Jofe컴포넌트로 전달가능하며, 이 녀석들은 다음과 같은 형태 즉 객체의 형태로 묶여서 전달됨.

{
    name : "lge",
    age : 23,
    func : func
}

 

그럼 여기서 children이란 걸 알아본다. props에서 특별취급하는 prop으로, JSX 문법에서 컴포넌트 작성 시 컴포넌트를 단일 태그가 아닌 여는태그 + 닫는태그의 형태로 작성하면, 이 태그 사이에 작성된 코드가 자동으로 아무것도 해주지 않아도 children이란 값에 담겨 컴포넌트로 전달된다.

import React from 'react';
import Jofe from './jofe';

function App(){
    return (
        <>
            <Jofe name="lje" age={23}>안녕안녕children</Jofe>
        </>
    );
}

export default App;

즉 여기선  안녕안녕children이란 문자열이 chidren에 담겨 Jofe컴포넌트에 전달된다. children이란 값에 담겨 전달되니 Jofe컴포넌트를 지정한 함수에선 children이란 이름으로 접근해 사용가능.

import React from 'react';

function Jofe({name, age, children}){
    return (
        <>
            <p>my name is {name} and age = {age}, children = {children}</p>
        </>
    );
}

export default Jofe;

 

그럼 children을 쓰면 뭐가 좋은가?

 

1. 화면에 보여질 모습을 좀 더 직관적인 코드로 쓰고자 할 때 활용 가능

2. 컴포넌트 안에 컴포넌트 작성 또는 컴포넌트 안에 복잡한 태그들 작성 가능. children을 쓸려면 단일 태그로 컴포넌트를 작성하는 게 아니라 여는 태그 + 닫는 태그로 컴포넌트를 작성하게 되므로!

 

props : 컴포넌트가 어떤 값을 전달받아 사용해야 할 때 이용된다. 컴포넌트에 속성들을 지정하는 형태로 전달하며,  객체 형태로 전달된다! 무슨 말인지는 예시 코드를 보자.

 

import React from 'react';
import Jofe from './jofe';

function App(){
    return (
        <>
            <Jofe />
        </>
    );
}

export default App;

 

이런 코드가 있다고 하자. App에서 Jofe라는 컴포넌트를 사용하는 모습이다. 이 때 Jofe컴포넌트에 "jsh"를 name이란 이름으로 전달하고 싶다면?

import React from 'react';
import Jofe from './jofe';

function App(){
    return (
        <>
            <Jofe name="jsh"/>
        </>
    );
}

export default App;

이렇게 태그의 속성을 지정하는 형태로 컴포넌트에 전달할 수 있다는 얘기다. 객체 형태로 전달된다는 것은, {name : "jsh"}이런 형태로 전달된다는 말이고.

 

Jofe 컴포넌트에선 이를 props라는 파라미터 이름으로 전달받아 사용가능하다. prrops말고 다른 이름도 쓸 수 있지만 다들 의미를 알기 쉽게 할려고 props라는 이름으로 쓴다고 한다.

import React from 'react';

function Jofe(props){
    return (
        <>
            <p>my name is {props.name}</p>
        </>
    );
}

export default Jofe;

 

- Props를 여러 개 전달하기

다음과 같이 여러 개의 props를 전달하는 것도 물론 가능하다.

import React from 'react';
import Jofe from './jofe';

function App(){
    return (
        <>
            <Jofe name="jsh" age={24}/>
        </>
    );
}

export default App;

props를 전달할 때 자바스크립트 숫자를 전달하기 위해선 {}로 감싸서 해야 한다고 한다. 문자열같은 건 ""로 하면 되고. 또한 Jofe 컴포넌트에선 props라는 이름으로 파라미터를 받는 게 아니라 다음과 같은 형태로 받을 수도 있다.

import React from 'react';

function Jofe({name, age}){
    return (
        <>
            <p>my name is {name} and age = {age}</p>
        </>
    );
}

export default Jofe;

이렇게 하면 매번 props.name이나 props.age 등 번거롭게 props라는 이름을 달아줄 필요가 없다. 또한 props를 전달받지 않는 상황에 대비해 디폴트 props를 지정가능하다.

import React from 'react';

function Jofe({name = "jsh", age = 24}){
    return (
        <>
            <p>my name is {name} and age = {age}</p>
        </>
    );
}

export default Jofe;

다음과 같은 방법으로도 디폴트 props를 지정 가능.

import React from 'react';

function Jofe({name, age}){
    return (
        <>
            <p>my name is {name} and age = {age}</p>
        </>
    );
}

Jofe.defaultProps = {
    name: 'jsh',
    age: 24
}

export default Jofe;

 

- 함수도 전달할 수 있다

함수도 props로 전달가능하다. 

import React from 'react';
import Jofe from './jofe';

function App(){
    const func = function(){
        alert("Hi!");
    }
    return (
        <>
            <Jofe name="lje" age={23} func={func}/>
        </>
    );
}

export default App;

alert를 이용해 hi라는 알림창을 띄우는 함수 func를 Jofe컴포넌트에 전달하는 모습. Jofe컴포넌트에선 다음과 같이 활용가능하다.

import React from 'react';

function Jofe({name, age, func}){
    return (
        <>
            <p onClick={func}>my name is {name} and age = {age}</p>
        </>
    );
}

export default Jofe;

p태그의 onclick이벤트로 등록해줬다. 실제로 저 글을 클릭하면 다음과 같이 알림창이 뜬다.

+ Recent posts