React로 웹페이지를 작성하던 도중,

조건을 할당하여 useEffect의 동작이상을 개선하였습니다.


- 상황 -

'toDo' dependency가 수정되면 해당 정보를 localStorage에 저장합니다.

 

- 문제점 - 

해당 정보가 수정되지 않고 불러오기만 했는데도 빈 배열이 localStorage에 저장되었습니다.

 

- 해결 -

조건을 할당하여 페이지를 처음 불러 올 때에,

빈 배열이 localStorage에 저장되지 않도록 개선하였습니다.

뭔가 더 나은 방법이 없는지 의문이 듭니다.

 

- 기타 자료 -

React로 웹페이지를 작성하던 도중,

Nullish coalescing operator (??)을 활용하여 서버 동작이상을 개선 하였습니다.


- 상황 -

페이지를 처음 불러오면 localStorage에 저장되어있는 배열의 정보를 렌더링하여 출력합니다.

 

- 문제점 - 

localStorage에 적절한 정보가 들어있다면 문제 없으나,

localStorage가 비어있다면 서버가 동작하지 않습니다.

 

- 해결 -

해당 소스코드(6번 줄)에, 

Nullish coalescing operator (??) 및 빈 배열을 할당하여 서버 동작이상을 개선했습니다.

 

- 기타 자료 -

 

게시글 하나에 너무 많은 주제를 담는 것 같기도 합니다.

 

하지만 제목의 키워드들은 각각에 대해 자세히 이야기 하는 것 보다,

서로의 연관성에 대해 이해 하는 것이 먼저 필요할 것 같습니다.

 

이에 본 게시글은,

각각이 어떻게 연관되어있는지 왜 함께 언급되는지에 대해,

제 나름의 이해를 설명하려 합니다.

 

내용 중 잘못 된 것이 있다면,

댓글로 알려주시면 도움이 되겠습니다.

 

- 동기와 비동기 - 

동기적인 실행은 요청한대로 응답하는 방식을 말합니다.

해당 요청에 대한 응답이 마무리되지 않는다면 다른 작업을 진행하지 않습니다.

 

비동기적 실행도 요청한대로 응답합니다.

하지만 해당 요청에 대한 응답이 마무리 되지 않더라도 다른 작업을 진행합니다.

자바스크립트의 정의(출처 MDN 공식홈페이지)

MDN의 정의에도 나와있듯이 자바스크립트는 single-threaded language입니다.

때문에 기본적으로 동기적인 방식으로 script가 실행합니다.

 

동기적인 script 실행에는 중요한 특징이 있습니다.

무거운 연산을 실행 할 경우,

해당 연산이 끝나기 전까지 다른 작업을 진행 할 수 없다는 것입니다.

 

이때문에 사용자의 필요에 따라,

비동기적으로 script를 실행 하는 방식도 필요합니다.

Web API을 통한 데이터 fetching, setTimeout 등이 대표적인 예 입니다.

비동기적으로 실행되는 data의 fetching(출처 MDN 공식홈페이지)

문제는 동기적 실행과 비동기적 실행이 섞여있는 경우,

그 실행순서를 예측하기 어렵고 예상치 못한 버그가 발생하는 경우가 있다는 것입니다.

 

예를들어 하기와 같은 소스코드를 실행한다고 가정합니다.

1
2
3
4
5
6
7
8
9
10
11
function test() {
    setTimeout(() => {
        variable = '3번 줄';
        console.log(variable);
    }, 500);
 
    let variable = '7번 줄';
    console.log(variable);
}
 
test();
cs

겉으로 보기에는 2~5번 줄의 코드블럭이 먼저 실행되고,

7~8번줄의 코드블럭이 나중에 실행되어야 할 것 같습니다만,

실행결과는 하기와 같이 정 반대입니다.

setTimeout코드 블럭이 나중에 실행 됨

이러한 점때문에, 

코드의 실행순서를 명확히 제어 할 필요가 있습니다.

 

동기적 실행,

비동기적 실행 각각의 특징이 있고 쓰임새가 다릅니다.

 

다만 중요한 것은,

코드의 실행 순서는 개발자의 의도대로 이루어져야 한다는 점이겠지요.

 

하기에서 다룰,

콜백함수, Promise, Async와 Await등은 모두,

코드 실행순서 및 결과 제어가 중요 포인트 인 것 같습니다.

 

가장 간단히 코드실행 순서를 제어하는 방법이 바로 콜백함수입니다.

 

 

- 콜백함수 - 

콜백함수는 함수의 결과값을 인자로 받는 함수를 의미합니다.

콜백함수의 정의자체는 비동기적 의미를 가지지 않습니다.

 

MDN에 기재되어있는 콜백함수의 정의는 하기와 같습니다.

콜백함수의 정의(출처 MDN 공식홈페이지)

콜백함수는 다른 함수의 실행결과값을 함수의 인자로 받기 때문에,

그 자체가 코드의 실행순서를 제어한다고 말 할 수 있습니다.

 

다만 가독성이 떨어지고,

디버깅이 어렵고,

모듈화가 어렵고,

모든 실행결과를 if문으로 작성해야하는 단점이 있습니다.

콜백함수의 좋지못한 가독성(출처 https://dev.to/jerrycode06/callback-hell-and-how-to-rescue-it-ggj)

 

- Promise - 

MDN에 기재되어있는 Promise의 정의는 하기와 같습니다.

Promise의 정의(출처 MDN 공식홈페이지)

위 그림에 나와있는대로,

Promise는 비동기적 작업과 그 결과값을 표현하는 객체입니다.

Promise의 사용 흐름을 그림으로 표현하면 하기와 같습니다.

Promise의 사용 흐름(MDN을 보고 이해한대로 내가 그린 그림)

 

Promise의 상태는 pending, fulfilled, reject로 나타냅니다.

상태에 따라 then, catch, finally method를 통해 결과를 제어합니다.

 

resolve함수를 Promise내에 지정하여,

Promise가 fulfill될 경우 then method를 통해 해당 함수를 호출합니다. 

 

reject함수를 Promise내에 지정하여,

Promise가 reject될 경우 catch method를 통해 에러를 제어합니다.

 

finally method는 Promise결과와는 관계없이 가장 마지막에 무조건 실행됩니다.

 

하기와 같은 간단한 소스코드를 작성하고 실행해보았습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
function promiseTest(param) {
    return new Promise((resolve, reject) => {
        if (!param) {
            reject(new Error('parameter needed'));
        }
        resolve();
    });
}
 
promiseTest()
    .then(() => console.log('promise fulfilled')) // promiseTest가 정상적으로 호출 될 경우 실행
    .catch(console.error) // promiseTest호출 시 에러가 발생 될 경우 실행
    .finally(() => console.log('you finally get here')); // 호출 결과에 관계없이 무조건 실행
cs

 

promiseTest에 인자를 입력 할 경우(promise fulfilled)의 결과는 하기와 같습니다.

promise fulfilled시의 console

promiseTest에 인자를 입력 하지 않을 경우(promise rejected)의 결과는 하기와 같습니다.

promise rejected시의 console

 

- Async와 Await - 

MDN에 기재되어있는 Async의 정의는 하기와 같습니다.

Async의 정의(출처 MDN 공식홈페이지)

Async의 경우,

정의못지않게 하기의 내용도 중요합니다.

Async의 return값(출처 MDN 공식홈페이지)

Async의 경우,

실행결과로 promise 객체가 반환되기 때문에 promise객체를 대신하여 사용할 수 있는 것입니다.

 

내용을 확인하기 위해,

위의 promise에서 예시로 들었던 소스코드를 Async를 활용하여 변경해보았습니다.

1
2
3
4
5
6
7
8
9
10
11
12
const promiseTest = async (param) => {
    try {
        if (!param) {
            throw new Error('parameter needed');
        }
        console.log('promise fulfilled'); // promiseTest가 정상적으로 호출 될 경우 실행
    } catch (error) {
        console.error(error); // promiseTest호출 시 에러가 발생 될 경우 실행
    } finally {
        console.log('you finally get here'); // 호출 결과에 관계없이 무조건 실행
    }
};
cs

 

에러가 발생하지 않을 시의 console은 하기와 같습니다.

에러가 발생하지 않을 시의 console

에러가 발생할 시의 console은 하기와 같습니다.

에러가 발생할 시의 console

 

promise를 사용할 때, Async를 사용할 때 동일한 결과를 얻을 수 있었습니다.

 

위와 같이 흐름 자체를 먼저 이해하니,

개념정리에 많은 도움이 되는 기분입니다.

 

아직 이해가 불완전한 부분도 있지만,

차차 수정 및 보완해가며 완전히 이해하도록 해야겠습니다.

Javascript의 Nullish coalescing operator (??)의 정의, 사용 예시에 대해 알아봅니다.

 

- 정의-

MDN에 기재된 Nullish coalescing operator (??)의 정의는 하기와 같습니다.

 

Nullish coalescing operator (??)

The nullish coalescing (??) operator is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.

 

같은 falsy라고 모두 (??)를 적용할 수 있는 것은 아닙니다.

(??)를 기준으로 왼쪽데이터가 null이나 undefined일 경우에만 의미가 있습니다.

 

- 사용 예시-

하기 소스코드를 작성하여 실행합니다.

1
2
3
4
5
6
7
8
9
const data1 = null ?? 'This will be displayed if data1 is null';
const data2 = undefined ?? 'This will be displayed if data2 is undefined';
const data3 = 0 ?? 'This will be not displayed even if data3 is falsy';
const data4 = NaN ?? 'This will be not displayed even if data4 is falsy';
 
console.log('data1', data1);
console.log('data2', data2);
console.log('data3', data3);
console.log('data4', data4);
cs

 

터미널에 하기와 같은 결과가 출력됩니다.

Javascript의 Optional chaining (?.)의 정의, 사용 예시에 대해 알아봅니다.

 

- 정의-

MDN에 기재된 Optional chaining (?.)의 정의는 하기와 같습니다.

 

Optional chaining (?.)

The optional chaining (?.) operator accesses an object's property or calls a function. If the object is undefined or null, it returns undefined instead of throwing an error.

 

(?.)연산자의 경우,

객체의 depth가 1단계 일 때에는 사용되지 않고 2단일 때 유용하게 사용 될 것으로 보입니다.

 

- 사용 예시-

아래와 같이 소스코드를 작성하여 실행합니다.

1
2
3
4
5
6
7
8
9
10
11
12
const music = {
    genre: 'R&B',
    singer: 'Brian McKnight',
    song: { title: 'Home' },
};
 
console.log(music);
console.log(music.song);
console.log(music.song.title);
 
console.log(music.lyric?.title); // ?.로 인해 undefined로 출력, app충돌발생하지않음
console.log(music.lyric.title); // app충돌발생
cs

 

터미널에 하기와 같은 결과가 출력됩니다.

Javascript의 배열관련 method 중 forEach, map, filter가 있습니다.

각각의 정의와 차이, 예시에 대해 정리합니다.

 

- 각각의 정의 및 차이-

MDN에 기재된 각 method의 정의는 하기와 같습니다.

 

Array.prototype.forEach()

The forEach() method executes a provided function once for each array element.

 

Array.prototype.map()

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

 

Array.prototype.filter()

The filter() method creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function.

 

상기내용을 간략히 정의하면 하기와 같습니다.

 

1. forEach은 각각의 인자를 주어진 함수에 대입 및 실행합니다. 

2. map은 각각의 인자를 callback 함수에 대입하고, 결과값들로 이루어진 새로운 배열을 생성합니다.

3. filter는 각각의 인자를 주어진 조건식에 대입 및 확인 하고, true인 경우의 결과값들로 이루어진 새로운 배열을 생성합니다.

 

차이점은 하기와 같습니다.

 

1. forEach는 어떠한 배열도 반환하지 않습니다.

2. map은 callback함수를 인자로 받습니다.

3. filter는 조건식이 따라붙습니다.

 

- 사용 예시 - 

우선 for와 forEach의 활용 예시입니다.

동일한 결과 값을 출력하기 위해 각각을 활용하여 소스코드를 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const singers = [
    'Ray Charles',
    'Stevie Wonder',
    'Sisqo',
    'Boyz II Men',
    'Luther Vandross',
    'Brian McKnight',
    'Mariah Carey',
];
 
for (let i = 0; i < singers.length; i++) {
    console.log('for문', singers[i]);
}
 
singers.forEach((singer) => console.log('forEach', singer));
cs

 

하기와 같이 동일한 결과를 얻을 수 있습니다.

 

다음은 map과 filter의 활용 예시입니다.

map의 경우 배열 내 특정 key값으로만 이루어진 새로운 배열을 생성합니다.

filter의 경우 특정 문자열로 시작하는 value값으로 이루어진 새로운 배열을 생성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const singersNsongs = [
    { singer: 'Ray Charles', song: 'Hit The Road Jack' },
    { singer: 'Stevie Wonder', song: 'Lately' },
    { singer: 'Sisqo', song: 'Incomplete' },
    { singer: 'Boyz II Men', song: 'On bended knee' },
    { singer: 'Luther Vandross', song: 'A house is not a home' },
    { singer: 'Brian McKnight', song: 'One last cry' },
    { singer: 'Mariah Carey', song: 'Hero' },
];
 
const songsFromArray = singersNsongs.map((song) => song.song);
const songsStartsWithO = singersNsongs.filter((song) =>
    song.song.startsWith('O')
);
 
console.log(songsFromArray);
console.log(songsStartsWithO);
 
cs

 

하기와 같은 결과를 얻을 수 있습니다.

 

MySQL Int형 데이터의 크기에 대해 정리합니다.

 

MySQL의 Int형 데이터에 대한 전반적인 내용은 MySQL공식홈페이지에서,

https://dev.mysql.com/doc/refman/8.0/en/integer-types.html

 

MySQL :: MySQL 8.0 Reference Manual :: 11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT,

11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT MySQL supports the SQL standard integer types INTEGER (or INT) and SMALLINT. As an extension to the standard, MySQL also supports the integer types TINYINT, MEDIUMINT,

dev.mysql.com

 

Unsigned Int형에 관한 내용은 하기 홈페이지를 참고하였습니다. 

https://www.cs.utah.edu/~germain/PPS/Topics/unsigned_integer.html

 

Programming - Unsigned Integers

Unsigned Integers Unsigned integers are used when we know that the value that we are storing will always be non-negative (zero or positive). Note: it is almost always the case that you could use a regular integer variable in place of an unsigned integer. T

www.cs.utah.edu

 

Type Storage ( Bytes) Minimum Value
Signed
Minimum Value
Unsigned
Maximum Value
Signed
Maximum Value
Unsigned
TINYINT 1 -128 0 127 255
SMALLINT 2 -32768 0 32767 65535
MEDIUMINT 3 -8388608 0 8388607 16777215
INT 4 -2147483648 0 2147483647 4294967295
BIGINT 8 -2^63 0 2(^63)-1 2(^64)-1

 

위 표와 링크를 통해 하기 2가지 내용에 대해 알 수 있습니다.

 

1. TINY는 최대(unsigned의 경우에 한정) 255까지 표현 할 수 있다.

-> 각 타입별로 데이터할당 크기를 정확히 파악 할 필요가 있겠습니다.

 

2. 부호의 유무(signed, unsigned)에 따라 최대 데이터 표현 크기가 다르다.

-> 음의정수를 표현필요 유무를 고려하여 데이터타입을 지정 할 필요가 있겠습니다.

관련 포스팅 : MySQL - 집계함수, JOIN, JSON_ARRAYAGG를 활용한 데이터 출력

 

첨부URL의 쿼리문을 작성하는 도중 발생한,

2건의 문제점을 개선하였습니다.

 

문제점 1.

 

카테고리 별로 가장 저렴한 음식 1개씩만을 출력하는 것이 목표였습니다.

기존 조건 하에서도 카테고리별로 가장 저렴한 음식이 1개씩 출력되긴했습니다.

하지만 윗 줄의 음식과 동일한 가격의 음식(불필요한 데이터)이 함께 출력되는 문제점이 있었습니다.

순두부찌개가 불필요하게 출력 됨

 

하기와 같이 조건을 추가하여 원하는 결과를 출력할 수 있었습니다.

원하는대로 출력 됨

 

문제점 2.

 

카테고리별로 가장 저렴한 금액을 가진 음식이 중복된다면 어떻게될까요?

하기 사진과 같이 데이터는 잘 출력 되지만 한 줄로 합쳐야 할 필요가 있어보입니다.

순두부찌개와 소불고기덮밥을 묶어 출력해야 함

 

하기와 같이 조건을 추가하여 원하는 결과를 출력할 수 있었습니다.

원하는대로 출력 됨

 

집계함수, JOIN, JSON_ARRAYGG를 활용하여,

하기와 같이 데이터를 가공 및 추출해보았습니다.

 

* '음식'테이블을 활용합니다.

* 카테고리는 '고기', '분식', '중식', '한식', '일식'의 5종 입니다.

 

- 구현 목표 -

 

1. 카테고리 별 메뉴의 갯수를 출력합니다.

2. 카테고리 별 가장 저렴한 메뉴의 단가를 출력합니다.

3. 카테고리 별 가장 저렴한 메뉴의 이름을 출력합니다.

 

데이터를 추출 할 'food' 테이블

 

실행 쿼리문은 하기와 같습니다.

----------------------------------------------------------------------------------------

WITH temp AS ( 👈 카테고리 별 메뉴 갯수, 가장 저렴한 단가를 출력하기 위해 temp 테이블 생성

SELECT category AS 카테고리

    , count(category) AS 카테고리_별_음식_수 👈 카테고리 별 메뉴 갯수 출력(구현목표 1번)

    , min(unitprice) AS 카테고리_별_가장_저렴한_단가 👈 카테고리 별 가장 저렴한 메뉴의 단가를 출력(구현목표 2번)

FROM food

GROUP BY category 

)

SELECT food.category AS 카테고리 👈 주 쿼리문 시작

    , 카테고리_별_음식_수,

    카테고리_별_가장_저렴한_단가 

    , JSON_ARRAYAGG( 👈 카테고리별 가장 저렴한 메뉴의 이름을 출력(구현목표 3번)

        JSON_OBJECT(

        "name", food.name))AS 카테고리_별_가장_싼_음식의_이름

FROM food

JOIN temp 👈 필요자료 가공을 위해 테이블 결합

    ON temp.카테고리_별_가장_저렴한_단가 = food.unitprice 👈 테이블 결합 조건 지정

    AND temp.카테고리 = food.category 

GROUP BY category;

----------------------------------------------------------------------------------------

 

하기와 같이 정상적으로 출력됩니다.

쿼리문 실행 결과

 

많이 사용되는 HTTP response status codes에 관해 간략히 정리합니다.

 

내용은 첨부URL을 기준으로 합니다.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

 

HTTP response status codes - HTTP | MDN

HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes:

developer.mozilla.org

 

- Successful reponses - 

200 OK

요청이 성공한 대부분의 경우에 사용합니다.

하기 201과 204과 같이 특정한 경우를 제외합니다.

 

201 Created

요청이 성공하였고,

처리결과로 리소스가 생성된 경우에 사용합니다.

ex)회원가입, 게시글 작성, 댓글 작성 등

 

204 No Content

요청이 성공하였고,

처리 결과로 반환 할 리소스가 없을 경우에 사용합니다.

ex)회원탈퇴, 게시글 삭제, 댓글 삭제 등

 

 

- Client error responses -

400 Bad Request

클라이언트쪽의 에러라고 판단되어,

서버가 반응할 수 없거나 하지 않는 경우에 사용합니다.

 

401 Unauthorized

접근에 인증이 필요한 서비스에,

인증되지 않은 사용자가 접근 할 시 사용합니다.

*서버는 사용자가 누구인지 모릅니다.

ex)토큰 없이 마이페이지 접근 등

 

403 Forbidden

권한이 없는 클라이언트가,

자료를 요청 할 경우 사용합니다.

*서버는 사용자가 누구인지 알고있습니다.

ex)특정 국가에서 접근, 사용정지 당한 계정 차단 등

 

404 Not Found

클라이언트가 존재하지 않는 페이지를 요청 할 경우 사용합니다.

ex)주소 오기입 등

 

 

- Server error responses - 

500 Internal Server Error

원인불명의 에러가 발생할 시 사용합니다.

 

503 Service Unavaliable

서버가 요청에 대응할 준비가 되어 있지 않은 경우 사용합니다.

 

 

 

+ Recent posts