[Front-end] 개발자 공부

[개발 공부 40일차] ...(spread 연산자), Compile Error

MOLLY_ 2024. 2. 19. 19:23
728x90

< 목차 >

1. [JSONPlaceholder] setState & spread 연산자 쓰임 이유

2. Uncaught TypeError: Cannot read properties of null (reading 'map')

3. Failed to load resource: net::ERR_CONNECTION_REFUSED

4. Uncaught (in promise) ReferenceError: process is not defined

5. 컴파일 에러(Compile Error) & 런타임 에러(Runtime Error)

6. 금일 소감

 

 

 

1. [JSONPlaceholder] setState & spread 연산자 쓰임 이유

 

하이라이트 처리한 부분 이해 덜 됨

 

 

JSONPlaceholder를 복습하다가 위 사진에 하이라이트 처리한 부분이 이해가 정확히 안 돼서 알아봤다. 해설은 다음과 같다.

 

코드는 서버에서 가져온 데이터(json)를 새로운 배열로 만들어 data 상태에 저장한다. 이 방식은 불변성을 유지하면서 상태를 안전하게 업데이트하는 데에 도움된다.

 

 

① 스프레드 연산자 [...json]

스프레드 연산자 ...는 배열이나 객체의 요소를 개별 요소로 확장하는데 사용된다. 이 경우, ...json은 json 배열의 모든 항목을 개별 요소로 확장하고, 새로운 배열에 그 요소들을 담는다. 이는 json 배열의 깊은 복사본을 생성하는 것과 유사하다. json이 배열일 때, [...json]은 json 배열의 모든 요소를 새로운 배열에 복사한다.

 

 

② setData([...json]);

fetch 함수를 사용하여 비동기적으로 데이터를 가져오고, .then()을 통해 응답을 JSON 형태로 변환한 뒤, 그 결과를 setData 함수를 사용하여 data 상태에 저장한다. 여기서 setData([...json]);는 가져온 json 데이터(여기서는 배열로 가정)의 모든 항목을 새로운 배열로 복사하고, 그 새로운 배열을 data 상태로 설정한다.

 

 

 

위 내용을 알아보고 Spread 연산자에 대해 좀 더 정확하고 자세히 알고 싶어졌다.

 

...(spread 연산자)

배열이나 객체의 요소를 개별 요소로 "펼쳐" 넣을 때 사용하는 JavaScript의 문법

이 연산자는 함수 호출에서의 인자, 배열 리터럴, 객체 리터럴에서 사용 가능하며, 코드를 간결하게 만들고 다양한 작업을 보다 쉽게 처리할 수 있도록 도와준다.

 

 

배열에서의 사용

①  배열 합치기

const first = [1, 2, 3];
const second = [4, 5, 6];
const combined = [...first, ...second];
// combined: [1, 2, 3, 4, 5, 6]

 

 

②  배열 복사하기

const original = [1, 2, 3];
const copied = [...original];
// copied: [1, 2, 3], 별도의 배열 참조를 가짐

 

 

③  함수 인자로 배열 사용하기

function addThreeNumbers(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3];
const result = addThreeNumbers(...numbers);
// result: 6

 

 

 

객체에서의 사용

①  객체 복사하기

const originalObj = { a: 1, b: 2 };
const copiedObj = { ...originalObj };
// copiedObj: { a: 1, b: 2 }, 별도의 객체 참조를 가짐

 

 

②  객체 확장하기

const person = { name: 'John', age: 30 };
const updatedPerson = { ...person, job: 'Developer' };
// updatedPerson: { name: 'John', age: 30, job: 'Developer' }

 

 

③  객체 프로퍼티 업데이트하기

const person = { name: 'John', age: 30 };
const updatedPerson = { ...person, age: 31 };
// updatedPerson: { name: 'John', age: 31 }

 

 

 

< 핵심 포인트 >

  • 스프레드 연산자를 사용하면 기존의 배열이나 객체를 쉽게 복사하거나 확장 가능
  • 배열이나 객체의 깊은 복사를 위해서는 스프레드 연산자만으로는 충분하지 않으며, 내부의 중첩된 객체나 배열에 대해서는 깊은 복사 방법을 따로 적용해야 한다.
  • 스프레드 연산자는 함수의 인자로 배열을 전달할 때 유용하게 사용된다.
  • 객체 사용 시, 스프레드 연산자를 통해 손쉽게 프로퍼티를 추가하거나 기존 프로퍼티를 업데이트 가능

 

 

2. Uncaught TypeError: Cannot read properties of null (reading 'map')

Uncaught TypeError: Cannot read properties of null (reading 'map')

 

 

Uncaught TypeError: Cannot read properties of null (reading 'map') 오류는 todos 상태가 null인 상태에서 .map 메서드를 호출하려고 시도할 때 발생한다. 초기 상태인 null에는 .map 메서드가 없기 때문에 이러한 오류가 발생하는 것이다.

 

 

 

todos의 초기 상태를 빈 배열로 설정하면 해결된다.

 

 

 

3. Failed to load resource: net::ERR_CONNECTION_REFUSED

Failed to load resource: net::ERR_CONNECTION_REFUSED

 

 

Failed to load resource: net::ERR_CONNECTION_REFUSED 에러는 '네트워크 연결이 거부되었을 때 발생'한다. 이 오류는 주로 클라이언트가 서버에 접속하려고 시도했으나, 서버가 요청을 받을 수 없는 상태일 때 나타난다.

 

이 에러에 대해 곰곰이 생각해 보다가 뭔가 'JSON 서버를 실행하지 않아서 이런 에러가 뜨는 게 아닐까?' 라는 의문을 가졌다.

 

따라서 '터미널에서 json 서버를 여는 json-server --watch db.json --port 4000 명령어랑  localhost 메인 페이지 여는 명령어인 npm run dev를 동시에 실행해야 해결되지 않을까?' 라는 생각이 들었다. 그래서 동시에 실행하려면 어떻게 해야 하는지 알아봤다.

 

[해결!] 정상적으로 출력된 화면

 


방법은 간단했다. 위 사진처럼 터미널창을 2개 열면 된다. 위처럼 '분할 터미널'을 실행해서 각각의 터미널에서 명령어를 실행해서 열었더니 정상적으로 출력되는 걸 확인할 수 있었다.

 

 

 

4. Uncaught (in promise) ReferenceError: process is not defined

Uncaught (in promise) ReferenceError: process is not defined

 

 

위처럼 에러 코드 뜨면서 환경 설정 참조가 안 되길래 '이거 왜 안 되지?...' 하며 고민하다가 '설마 Vite으로 돌려서 그런가?' 싶어서 Vite으로 환경 설정하는 형식을 알아보았고 적용했다.

 

 

.env.로 파일명을 바꿨더니 해결됨

 

 

 

에러는 더 이상 안 뜨는데 화면상에 todos가 뜨질 않아서 누가 봐도 환경 설정 때문이겠다 싶어서 날이 밝자마자 튜터님께 찾아갔다. 알고 보니 .env.development로 설정해놔서 그런 것이었다. 아마 Vite에서 적용되지 않는 형식인가 보다. 그래서 .env로 파일명을 변경했더니 말끔히 해결되었다.

 

 

Vite 공식 문서

 

 

이렇게.. Vite 공식 문서에 엄청 잘 나와있다..

막히면 공식 문서부터 보자 제발

 

 

[Vite 공식 문서]

https://ko.vitejs.dev/guide/env-and-mode.html

 

 

 

5. 컴파일 에러(Compile Error) & 런타임 에러(Runtime Error)

유명한 밈들

 

 

 

공부하다가 문득 컴파일 에러와 런타임 에러에 대해 정확하게 알고 싶다는 생각이 들었다. 그래서 관련 내용을 알아봤다.

 

 

ㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

컴파일 에러와 런타임 에러는 프로그래밍에서 발생하는 두 가지 주요 에러 유형이다. 이 둘은 발생하는 시점과 원인에 따라 구별된다.

 

요약하면, 컴파일 에러는 코드 작성 중에 발생하여 프로그램의 실행을 막는 반면, 런타임 에러는 프로그램이 실행되는 동안에 발생하여 프로그램의 실행을 중단시킬 수 있다. 일단 개념에 대해 자세히 들어가기 전에 컴파일이란 무엇인지부터 알아보자.

 

 

컴파일 (Compile)

프로그래밍 언어로 작성된 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 변환하는 과정

이 과정은 일반적으로 컴파일러라는 특수한 프로그램에 의해 수행된다.

컴파일러는 소스 코드를 분석하여 문법적 오류를 확인하고, 그것을 기계어로 번역하여 새로운 실행 파일을 생성한다. 이 실행 파일은 컴퓨터에서 직접 실행될 수 있다.

 


컴파일은 대부분의 프로그래밍 언어에서 필요한 단계로, 일반적으로 다음과 같은 절차로 진행된다.

 

  1. 소스 코드 작성프로그래머가 특정 프로그래밍 언어로 소스 코드를 작성한다.
  2. 컴파일러 실행: 작성된 소스 코드를 컴파일러에 전달하여 컴파일을 시작한다.
  3. 구문 및 의미 분석컴파일러는 소스 코드를 읽고 구문적 오류(예: 잘못된 문법 사용)와 의미적 오류(예: 변수가 선언되지 않음)를 확인한다.
  4. 기계어로 번역오류가 없으면 컴파일러는 소스 코드를 해당 언어의 기계어로 번역한다.
  5. 실행 파일 생성번역된 기계어 코드를 실행 파일로 변환하여 저장한다. 이 실행 파일은 컴퓨터에서 직접 실행될 수 있다.
  6. 컴파일의 결과물은 일반적으로 실행 파일 또는 라이브러리 형태일 수 있다. 이 파일은 특정 운영 체제와 하드웨어 아키텍처에서 실행되도록 설계되었다.

컴파일은 프로그램을 실행하기 전에 필요한 전처리 단계이며, 소스 코드를 실행 가능한 형태로 변환하여 컴퓨터가 처리할 수 있도록 한다.

 

 

컴파일 에러 (Compile-time Error)

문법을 잘못 작성해 프로그램을 컴파일할 수 없는 에러

에러 메시지를 통해 에러가 발생한 부분을 확인해 비교적 쉽게 해결할 수 있다.


ex.
 ; (세미콜론)이 누락된 문법 에러,
 괄호가 맞지 않는 구문 에러,
 interface 사용 시 함수의 구체적인 내용을 적지 않은 에러

 

 

  • 컴파일러가 소스 코드를 해석하여 기계어로 변환하는 과정에서 발생한다.
  • 일반적으로 코드의 구문, 형식, 타입 오류 등과 관련된다.
  • 컴파일 시간에 발생하며, 프로그램이 실행되기 전에 발견된다.
  • 컴파일러는 컴파일 에러를 발견하고 그에 따른 오류 메시지를 출력한다.
  • 컴파일 에러가 있는 경우, 프로그램은 컴파일되지 않고 실행되지 않는다.

 

 

런타임 에러 (Runtime Error)

프로그래머의 설계 미숙으로 프로그램 실행 중 발생하는 에러

에러 발생 시, 프로그래머가 역추적해 원인을 확인해야 한다. 대체로 try-catch문을 이용해 에러를 해결할 수 있다.

ex.
NullPointerException(생성되지 않은 객체를 참조할 때 발생),
Infinite Loop(무한 루프),
ArithmeticException(0으로 나눴을 때 발생)


런타임 에러에는 논리 에러, 시스템 에러가 있다.

 

  • 논리 에러(Logical Error) : 프로그래머의 논리적 실수에 의해 발생하는 에러
  • 시스템 에러(System Error) : 프로그램 동작 중에 운영체제 또는 하드웨어에 문제가 발생해 프로그램이 정상적으로 동작하지 않는 경우에 발생하는 에러

 

  • 프로그램 실행 중에 발생하는 오류로, 실행 시간에 발생한다.
  • 프로그램이 실행되는 동안 메모리 상태, 데이터 입력, 파일 상태 등의 요소에 의해 발생할 수 있다.
  • 일반적으로 잘못된 연산, 잘못된 사용자 입력, 메모리 오버플로우, 분할 by zero 등이 이에 해당된다.
  • 프로그램이 실행되는 동안 발생하기 때문에, 프로그램의 실행 흐름에 따라 발생한다.
  • 컴파일러에 의해 감지되지 않으며, 프로그램 실행 중에만 발견된다.
  • 런타임 에러가 발생하면 프로그램은 종료되거나 예외 처리를 통해 처리될 수 있다.

 

 

[Reference]

https://junboom.tistory.com/39

 

 

 

6. 금일 소감

휴.. 밤새워가며 코드만 계속 작성했다. 위 내용처럼 강의 들으면서 실습 같이 했는데 뭔가 코드 똑같이 작성해도 에러 뜨는 부분이 있길래 최대한 혼자 이런저런 시도하다가 답이 안 나와서 오늘 튜터님께 가서 질문하여 거의 해결하고 이해도 되었다. 일부 코드는 혼자서 왜 안 되는지 알아내라고 하셔서 알아보고, 또 이해했다.

 

오늘은 챌린지 세션이 진행되었다. '클린 코드를 작성하는 법'에 대한 내용이었고, 중요한 것은 '일관성, 규칙성, 작명 잘하기, 쓸데없는 거 작성하지 말고 당장 쓸 것만 작성해라, 함수한테 일을 하나만 줘라'였다. 코딩 공부하며 계속해서 언급되는 부분이 클린 코드 내용이기도 해서 내용은 그리 어렵지 않았다.

 

오늘 세션 들으면서 특히 더 이론보단 최대한 코드 짜는 데에 집중해야겠다 싶었다. 클린 코드도 예문 코드가 많았어서 확실히 코드를 많이 보고, 직접 짜는 시간을 늘리니 더욱 이해가 잘 됐다. 지금처럼 매일매일 코드 짜고, GitHub에 Push 하자!

 

 

728x90