반응형

Dart의 반복문은 특정 조건이 참일 때까지 또는 특정 횟수만큼 코드를 반복 실행하는 데 사용됩니다. Dart에서 사용할 수 있는 주요 반복문에는 for 문, for-in 문, while 문, do-while 문이 있습니다. 각 반복문과 그 사용법에 대해 설명하겠습니다.

 

1. for 문

 

for 문은 반복 횟수가 명확할 때 주로 사용됩니다. 초기화, 조건 검사, 증감식을 한 줄에 작성할 수 있습니다.

void main() {
  // 0부터 4까지 출력
  for (int i = 0; i < 5; i++) {
    print(i);
  }
}

2. for-in 문

 

for-in 문은 컬렉션(리스트, 셋 등)의 요소를 하나씩 순회할 때 사용됩니다.

void main() {
  var numbers = [1, 2, 3, 4, 5];

  // 각 요소를 출력
  for (var number in numbers) {
    print(number);
  }
}

3. while 문

 

while 문은 조건이 참인 동안 코드를 반복 실행합니다. 조건이 거짓이 되면 반복을 종료합니다.

void main() {
  int i = 0;

  // i가 5보다 작을 때까지 반복
  while (i < 5) {
    print(i);
    i++;
  }
}

4. do-while 문

 

do-while 문은 조건을 검사하기 전에 코드를 먼저 한 번 실행한 후, 조건이 참인 동안 반복 실행합니다.

void main() {
  int i = 0;

  // 최소 한 번은 실행 후, i가 5보다 작을 때까지 반복
  do {
    print(i);
    i++;
  } while (i < 5);
}

5. 중첩 반복문

 

반복문을 중첩하여 사용할 수 있습니다. 이 경우 외부 반복문이 한 번 반복될 때마다 내부 반복문이 완전히 실행됩니다.

void main() {
  // 구구단 출력
  for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
      print('$i * $j = ${i * j}');
    }
  }
}

6. 반복문 제어문

 

반복문 내에서 반복의 흐름을 제어하기 위해 breakcontinue를 사용할 수 있습니다.

 

break

 

break 문은 반복문을 즉시 종료합니다.

void main() {
  for (int i = 0; i < 5; i++) {
    if (i == 3) {
      break; // 반복문 종료
    }
    print(i);
  }
}

continue

 

continue 문은 현재 반복 주기의 나머지 부분을 건너뛰고 다음 반복 주기로 넘어갑니다.

void main() {
  for (int i = 0; i < 5; i++) {
    if (i == 3) {
      continue; // 다음 반복 주기로 건너뜀
    }
    print(i);
  }
}

요약

 

for: 초기화, 조건 검사, 증감식을 한 줄에 작성하여 반복.

for-in: 컬렉션의 요소를 순회.

while: 조건이 참인 동안 반복.

do-while: 최소 한 번 실행 후 조건이 참인 동안 반복.

중첩 반복문: 반복문 내에 다른 반복문을 포함하여 사용.

break: 반복문을 즉시 종료.

continue: 현재 반복 주기를 건너뛰고 다음 주기로 넘어감.

반응형

'프론트엔드 > Flutter' 카테고리의 다른 글

flutter bloc 패턴 적용  (0) 2024.07.22
flutter 리프레쉬 인디케이터  (0) 2024.07.22
dart 조건문 정리  (0) 2024.07.21
dart collection 설명 및 예시  (0) 2024.07.21
dart 연산자  (0) 2024.07.21
반응형

Dart의 조건문은 프로그램의 흐름을 제어하고 특정 조건에 따라 다른 코드를 실행하는 데 사용됩니다.

주요 조건문에는 if, else if, else, switch 문이 있습니다. 각 조건문과 그 사용법에 대해 설명하겠습니다.

 

1. if 문

 

if 문은 주어진 조건이 true일 때 코드를 실행합니다.

void main() {
  int number = 10;

  if (number > 5) {
    print('Number is greater than 5');
  }
}

 

2. if-else 문

 

if-else 문은 if 조건이 false일 때 else 블록의 코드를 실행합니다.

void main() {
  int number = 3;

  if (number > 5) {
    print('Number is greater than 5');
  } else {
    print('Number is not greater than 5');
  }
}

3. else if 문

 

else if 문은 여러 조건을 검사할 때 사용됩니다. 첫 번째 if 조건이 false일 때, 그 다음 else if 조건을 검사합니다.

void main() {
  int number = 7;

  if (number > 10) {
    print('Number is greater than 10');
  } else if (number > 5) {
    print('Number is greater than 5 but less than or equal to 10');
  } else {
    print('Number is 5 or less');
  }
}

4. 중첩 if 문

 

if 문은 다른 if 문 안에 중첩될 수 있습니다. 이는 복잡한 조건을 검사할 때 유용합니다.

void main() {
  int number = 8;

  if (number > 5) {
    if (number < 10) {
      print('Number is between 5 and 10');
    } else {
      print('Number is 10 or greater');
    }
  } else {
    print('Number is 5 or less');
  }
}

 

5. 삼항 연산자

 

삼항 연산자는 간단한 if-else 문을 한 줄로 표현할 수 있습니다.

void main() {
  int number = 4;
  String result = number > 5 ? 'Number is greater than 5' : 'Number is not greater than 5';
  print(result);
}

6. switch 문

 

switch 문은 하나의 변수에 대한 여러 조건을 검사할 때 사용됩니다. 각 조건은 case 키워드로 표시됩니다.

void main() {
  String grade = 'B';

  switch (grade) {
    case 'A':
      print('Excellent!');
      break;
    case 'B':
      print('Good!');
      break;
    case 'C':
      print('Fair');
      break;
    case 'D':
      print('Poor');
      break;
    default:
      print('Invalid grade');
  }
}

7. switch 문에서 fall-through 방지

 

Dart에서는 case 블록이 끝나면 break 문을 사용하여 switch 문을 종료해야 합니다. 그렇지 않으면 다음 case 블록으로 넘어가는 fall-through가 발생하지 않습니다.

void main() {
  int number = 2;

  switch (number) {
    case 1:
      print('One');
      break;
    case 2:
      print('Two');
      break;
    case 3:
      print('Three');
      break;
    default:
      print('Other number');
  }
}

요약

 

if: 조건이 참일 때 코드 실행.

if-else: 조건이 참이면 if 블록, 거짓이면 else 블록 실행.

else if: 여러 조건 검사.

중첩 if: 복잡한 조건 검사.

삼항 연산자: 간단한 if-else 문을 한 줄로 표현.

switch: 하나의 변수에 대한 여러 조건 검사.

반응형

'프론트엔드 > Flutter' 카테고리의 다른 글

flutter 리프레쉬 인디케이터  (0) 2024.07.22
dart 반복문 정리  (0) 2024.07.21
dart collection 설명 및 예시  (0) 2024.07.21
dart 연산자  (0) 2024.07.21
Dart에서 변수 초기화 null Safety 와 late 키워드  (0) 2024.07.18
반응형

Dart의 컬렉션(Collection)은 여러 요소를 관리하고 조작할 수 있는 데이터 구조를 제공합니다.

주요 컬렉션 타입으로는 리스트(List), 셋(Set), 맵(Map)이 있습니다.

각각의 컬렉션은 다양한 용도로 사용될 수 있으며, Dart는 이러한 컬렉션을 쉽게 사용할 수 있도록 다양한 메서드와 연산자를 제공합니다.

 

1. List

 

리스트(List)는 순서가 있는 요소의 집합으로, 배열과 유사합니다. 요소의 순서를 유지하며, 동일한 값을 중복해서 가질 수 있습니다.

 

생성 및 초기화

void main() {
  // 빈 리스트 생성
  List<int> numbers = [];

  // 초기값을 가지는 리스트 생성
  List<String> fruits = ['Apple', 'Banana', 'Orange'];

  // 리스트에 요소 추가
  numbers.add(1);
  numbers.add(2);
  numbers.add(3);

  // 인덱스를 사용하여 요소 접근
  print(fruits[0]); // Apple

  // 리스트 길이
  print(fruits.length); // 3
}

 

 

주요 메서드

void main() {
  List<String> fruits = ['Apple', 'Banana', 'Orange'];

  // 요소 추가
  fruits.add('Grape');

  // 여러 요소 추가
  fruits.addAll(['Mango', 'Pineapple']);

  // 요소 제거
  fruits.remove('Banana');

  // 인덱스로 요소 제거
  fruits.removeAt(1);

  // 조건에 맞는 모든 요소 제거
  fruits.removeWhere((fruit) => fruit.startsWith('A'));

  // 요소 포함 여부 확인
  print(fruits.contains('Orange')); // true

  // 요소의 인덱스 찾기
  print(fruits.indexOf('Mango')); // 2
}

 

2. Set

 

셋(Set)은 순서가 없는 고유한 요소의 집합입니다. 동일한 값을 중복해서 가질 수 없습니다.

 

생성 및 초기화

void main() {
  // 빈 셋 생성
  Set<int> numbers = {};

  // 초기값을 가지는 셋 생성
  Set<String> fruits = {'Apple', 'Banana', 'Orange'};

  // 셋에 요소 추가
  numbers.add(1);
  numbers.add(2);
  numbers.add(3);

  // 요소 추가 (중복된 요소는 추가되지 않음)
  fruits.add('Apple');

  // 셋 길이
  print(fruits.length); // 3
}

 

주요 메서드

void main() {
  Set<String> fruits = {'Apple', 'Banana', 'Orange'};

  // 요소 추가
  fruits.add('Grape');

  // 여러 요소 추가
  fruits.addAll({'Mango', 'Pineapple'});

  // 요소 제거
  fruits.remove('Banana');

  // 조건에 맞는 모든 요소 제거
  fruits.removeWhere((fruit) => fruit.startsWith('A'));

  // 요소 포함 여부 확인
  print(fruits.contains('Orange')); // true
}

 

3. Map

 

맵(Map)은 키-값 쌍으로 이루어진 컬렉션입니다. 각 키는 고유하며, 키를 통해 값에 접근할 수 있습니다.

 

생성 및 초기화

void main() {
  // 빈 맵 생성
  Map<String, int> ages = {};

  // 초기값을 가지는 맵 생성
  Map<String, int> scores = {
    'Alice': 90,
    'Bob': 85,
    'Charlie': 95,
  };

  // 맵에 요소 추가
  ages['John'] = 25;
  ages['Doe'] = 30;

  // 키를 사용하여 값 접근
  print(scores['Alice']); // 90

  // 맵 길이
  print(scores.length); // 3
}

주요 메서드

void main() {
  Map<String, int> scores = {
    'Alice': 90,
    'Bob': 85,
    'Charlie': 95,
  };

  // 요소 추가
  scores['David'] = 88;

  // 요소 제거
  scores.remove('Bob');

  // 모든 키 가져오기
  print(scores.keys); // (Alice, Charlie, David)

  // 모든 값 가져오기
  print(scores.values); // (90, 95, 88)

  // 특정 키의 값 업데이트
  scores.update('Alice', (value) => 92);

  // 키 포함 여부 확인
  print(scores.containsKey('Charlie')); // true

  // 값 포함 여부 확인
  print(scores.containsValue(88)); // true
}

결론

 

Dart의 컬렉션은 데이터를 저장하고 조작하는 데 매우 유용한 도구입니다. 리스트(List)는 순서가 있는 요소의 집합을 다루며, 셋(Set)은 고유한 요소의 집합을 다루고, 맵(Map)은 키-값 쌍을 다룹니다. 이러한 컬렉션을 사용하여 데이터를 효율적으로 관리하고 처리할 수 있습니다.

 

참고 문서

 

Dart List 클래스 문서

Dart Set 클래스 문서

Dart Map 클래스 문서

Dart Language Tour - Collections

반응형

'프론트엔드 > Flutter' 카테고리의 다른 글

dart 반복문 정리  (0) 2024.07.21
dart 조건문 정리  (0) 2024.07.21
dart 연산자  (0) 2024.07.21
Dart에서 변수 초기화 null Safety 와 late 키워드  (0) 2024.07.18
dart 3 언어 주요 변경 사항 및 새로운 기능  (0) 2024.07.18
반응형

Dart에서는 다양한 연산자를 제공하여 변수와 값에 대해 다양한 작업을 수행할 수 있습니다.

연산자는 크게 다음과 같은 범주로 나눌 수 있습니다

 

1. 산술 연산자

2. 증감 연산자

3. 관계 연산자

4. 논리 연산자

5. 비트 연산자

6. 할당 연산자

7. 조건 연산자

8. 형 변환 연산자

9. 기타 연산자

 

1. 산술 연산자

 

산술 연산자는 기본적인 산술 계산을 수행합니다.

 

+ (덧셈)

- (뺄셈)

* (곱셈)

/ (나눗셈)

~/ (몫 연산)

% (나머지 연산)

 

void main() {
  int a = 10;
  int b = 3;

  print(a + b); // 13
  print(a - b); // 7
  print(a * b); // 30
  print(a / b); // 3.3333333333333335
  print(a ~/ b); // 3
  print(a % b); // 1
}

 

2. 증감 연산자

 

증감 연산자는 변수의 값을 증가시키거나 감소시킵니다.

 

++a (전위 증가)

a++ (후위 증가)

--a (전위 감소)

a-- (후위 감소)

void main() {
  int a = 10;

  print(++a); // 11
  print(a++); // 11
  print(a); // 12
  print(--a); // 11
  print(a--); // 11
  print(a); // 10
}

 

3. 관계 연산자

 

관계 연산자는 두 피연산자 간의 관계를 비교합니다. 결과는 boolean 값입니다.

 

== (같다)

!= (같지 않다)

> (크다)

< (작다)

>= (크거나 같다)

<= (작거나 같다)

void main() {
  int a = 10;
  int b = 3;

  print(a == b); // false
  print(a != b); // true
  print(a > b); // true
  print(a < b); // false
  print(a >= b); // true
  print(a <= b); // false
}

 

4. 논리 연산자

 

논리 연산자는 boolean 값에 대해 논리 연산을 수행합니다.

 

&& (그리고)

|| (또는)

! (부정)

void main() {
  bool a = true;
  bool b = false;

  print(a && b); // false
  print(a || b); // true
  print(!a); // false
  print(!b); // true
}

 

5. 비트 연산자

 

비트 연산자는 비트 수준에서 연산을 수행합니다.

 

& (AND)

| (OR)

^ (XOR)

~ (NOT)

<< (왼쪽 시프트)

>> (오른쪽 시프트)

void main() {
  int a = 10; // 1010
  int b = 3; // 0011

  print(a & b); // 2 (0010)
  print(a | b); // 11 (1011)
  print(a ^ b); // 9 (1001)
  print(~a); // -11 (2의 보수)
  print(a << 1); // 20 (10100)
  print(a >> 1); // 5 (0101)
}

 

6. 할당 연산자

 

할당 연산자는 변수에 값을 할당하거나 특정 연산을 수행한 후 할당합니다.

 

= (할당)

+= (더한 후 할당)

-= (뺀 후 할당)

*= (곱한 후 할당)

/= (나눈 후 할당)

~/= (몫을 구한 후 할당)

%= (나머지를 구한 후 할당)

void main() {
  int a = 10;
  int b = 3;

  a += b; // a = a + b
  print(a); // 13

  a -= b; // a = a - b
  print(a); // 10

  a *= b; // a = a * b
  print(a); // 30

  a /= b; // a = a / b
  print(a); // 10.0

  a ~/= b; // a = a ~/ b
  print(a); // 3

  a %= b; // a = a % b
  print(a); // 0
}

 

7. 조건 연산자

 

조건 연산자는 특정 조건에 따라 값을 선택합니다.

 

condition ? expr1 : expr2 (삼항 연산자)

?? (널 병합 연산자)

void main() {
  int a = 10;
  int b = 3;

  var result = a > b ? 'a가 크다' : 'b가 크다';
  print(result); // a가 크다

  String? name;
  String userName = name ?? 'Guest';
  print(userName); // Guest
}

 

8. 형 변환 연산자

 

형 변환 연산자는 객체의 타입을 변환하거나 확인합니다.

 

as (형 변환)

is (타입 검사)

is! (타입 검사 - 부정)

 

void main() {
  dynamic a = 10;

  // 타입 검사
  if (a is int) {
    print('a는 int 타입입니다.');
  }

  // 타입 검사 - 부정
  if (a is! String) {
    print('a는 String 타입이 아닙니다.');
  }

  // 형 변환
  var b = a as int;
  print(b); // 10
}

 

9. 기타 연산자

 

[] (리스트 및 맵 접근 연산자)

. (멤버 접근 연산자)

?. (널 안전 멤버 접근 연산자)

.. (계단식 표기법)

void main() {
  List<int> numbers = [1, 2, 3];
  Map<String, int> ages = {'John': 25, 'Doe': 30};

  // 리스트 및 맵 접근
  print(numbers[0]); // 1
  print(ages['John']); // 25

  // 멤버 접근
  String text = 'Hello';
  print(text.length); // 5

  // 널 안전 멤버 접근
  String? nullableText;
  print(nullableText?.length); // null

  // 계단식 표기법
  var buffer = StringBuffer()
    ..write('Hello')
    ..write(' ')
    ..write('World');
  print(buffer.toString()); // Hello World
}

 

결론

 

Dart 연산자는 다양한 작업을 수행할 수 있도록 돕는 중요한 도구입니다. 연산자의 올바른 사용법을 익히면 코드의 효율성과 가독성을 높일 수 있습니다. 이 문서에서 설명한 다양한 연산자를 잘 활용하여 더욱 효과적인 Dart 프로그래밍을 수행할 수 있습니다.

 

참고 문서

 

Dart Language Tour - Operators

반응형
반응형

Vue.js 프로젝트에서는 환경 변수를 사용하여 개발, 테스트, 프로덕션 환경에 따라 설정을 다르게 할 수 있습니다.

Vue CLI를 사용하면 이러한 환경 변수를 쉽게 설정하고 관리할 수 있습니다.

아래에 환경 변수를 설정하고 사용하는 방법을 단계별로 정리하겠습니다.

 

1. 환경 변수 파일 설정

 

Vue CLI를 사용하면 .env 파일을 통해 환경 변수를 설정할 수 있습니다.

Vue CLI는 프로젝트 루트 디렉토리에 위치한 .env 파일을 자동으로 로드합니다.

 

환경 변수 파일 종류

 

.env: 모든 환경에 적용되는 기본 환경 변수.

.env.local: 모든 환경에 적용되지만, 버전 관리를 하지 않는 로컬 환경 변수.

.env.development: 개발 환경에 적용되는 환경 변수.

.env.development.local: 개발 환경에 적용되지만, 버전 관리를 하지 않는 로컬 환경 변수.

.env.production: 프로덕션 환경에 적용되는 환경 변수.

.env.production.local: 프로덕션 환경에 적용되지만, 버전 관리를 하지 않는 로컬 환경 변수.

 

예시: 환경 변수 파일 생성

 

프로젝트 루트에 .env.development.env.production 파일을 생성합니다.

 

.env.development

VUE_APP_API_URL=http://localhost:3000
VUE_APP_DEBUG=true

.env.production

VUE_APP_API_URL=https://api.example.com
VUE_APP_DEBUG=false

2. 환경 변수 사용

 

Vue 애플리케이션에서 환경 변수를 사용하려면 process.env 객체를 통해 접근할 수 있습니다. Vue CLI는 VUE_APP_ 접두사가 붙은 환경 변수만을 인식하므로, 모든 환경 변수 이름은 VUE_APP_으로 시작해야 합니다.

 

예시: 환경 변수 사용

 

src/main.js 파일에서 환경 변수를 사용하는 방법을 설명합니다.

 

src/main.js

import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false;

console.log('API URL:', process.env.VUE_APP_API_URL);
console.log('Debug mode:', process.env.VUE_APP_DEBUG);

new Vue({
  render: h => h(App),
}).$mount('#app');

예시: 컴포넌트에서 환경 변수 사용

 

컴포넌트 내에서 환경 변수를 사용하는 방법도 동일합니다.

 

src/components/ExampleComponent.vue

<template>
  <div>
    <p>API URL: {{ apiUrl }}</p>
    <p>Debug Mode: {{ debugMode }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      apiUrl: process.env.VUE_APP_API_URL,
      debugMode: process.env.VUE_APP_DEBUG
    };
  }
};
</script>

3. 환경 변수의 동작 확인

 

환경 변수 파일을 설정하고, 개발 또는 프로덕션 모드로 애플리케이션을 실행하여 환경 변수가 제대로 동작하는지 확인합니다.

 

개발 모드 실행

npm run serve

npm run serve 명령어는 .env.development 파일의 환경 변수를 로드합니다.

 

프로덕션 모드 실행

npm run build

npm run build 명령어는 .env.production 파일의 환경 변수를 로드합니다.

 

4. 환경 변수 파일 버전 관리

 

.env 파일과 .env.production 파일은 일반적으로 버전 관리 시스템에 포함됩니다.

그러나 로컬 환경 변수 파일(.env.local, .env.development.local, .env.production.local)은 버전 관리에서 제외하는 것이 좋습니다.

 

예시: .gitignore 파일 설정

.gitignore

# local env files
.env.local
.env.*.local

요약

 

1. 환경 변수 파일 설정: 프로젝트 루트에 .env 파일을 생성하여 환경 변수를 정의합니다. 환경에 따라 .env.development, .env.production 파일을 사용합니다.

2. 환경 변수 사용: process.env 객체를 통해 환경 변수에 접근합니다. 모든 환경 변수는 VUE_APP_ 접두사로 시작해야 합니다.

3. 환경 변수의 동작 확인: 개발 또는 프로덕션 모드로 애플리케이션을 실행하여 환경 변수가 올바르게 로드되는지 확인합니다.

4. 환경 변수 파일 버전 관리: .env.local, .env.development.local, .env.production.local 파일은 버전 관리에서 제외합니다.

반응형
반응형

Vue.js 프로젝트를 설정하는 과정은 Vue CLI를 사용하면 매우 간단하고 효율적입니다.

아래에 Vue CLI를 사용하여 프로젝트를 설정하는 단계별 가이드를 제공하겠습니다.

 

1. 개발 환경 설정

 

Vue.js 프로젝트를 시작하기 전에 Node.js와 Vue CLI가 설치되어 있어야 합니다.

 

Node.js 설치:

Node.js 공식 웹사이트에서 최신 LTS 버전을 다운로드하고 설치합니다.

설치가 완료되면, 터미널에서 Node.js와 npm(Node Package Manager)의 버전을 확인합니다.

 

node -v
npm -v

 

Vue CLI 설치:

Vue CLI는 Vue.js 애플리케이션을 생성하고 관리하는 데 도움을 주는 명령줄 도구입니다.

npm을 사용하여 Vue CLI를 전역 설치합니다.

 

npm install -g @vue/cli

 

Vue CLI 설치가 완료되면, 터미널에서 버전을 확인합니다.

vue --version

2. 새로운 Vue 프로젝트 생성

 

Vue CLI를 사용하여 새로운 Vue 프로젝트를 생성합니다.

 

프로젝트 생성 명령어:

vue create my-project

 

프로젝트 생성 과정:

프로젝트 이름을 지정하고, Vue CLI에서 제공하는 기본 템플릿을 선택하거나, 커스텀 설정을 선택할 수 있습니다.

기본 템플릿을 선택할 경우, “Default (Vue 2)” 또는 “Default (Vue 3)” 중 하나를 선택합니다.

커스텀 설정을 선택할 경우, 필요한 기능들을 선택할 수 있습니다. (예: Babel, TypeScript, Vue Router, Vuex, CSS Pre-processors, Linter/Formatter, Unit Testing, E2E Testing)

 

3. 프로젝트 디렉토리 구조

 

프로젝트 생성이 완료되면, 해당 디렉토리로 이동하여 프로젝트 구조를 확인합니다.

 

my-project/
├── node_modules/       // 프로젝트의 의존성 모듈들이 설치되는 디렉토리
├── public/             // 정적 파일들이 위치하는 디렉토리
│   └── index.html      // 애플리케이션의 기본 HTML 파일
├── src/                // 소스 코드가 위치하는 디렉토리
│   ├── assets/         // 이미지, 스타일 등의 정적 파일
│   ├── components/     // Vue 컴포넌트들이 위치하는 디렉토리
│   ├── App.vue         // 루트 컴포넌트
│   ├── main.js         // 애플리케이션의 진입 파일
├── .gitignore          // Git에서 무시할 파일들을 지정하는 파일
├── babel.config.js     // Babel 설정 파일
├── package.json        // 프로젝트 메타데이터 및 의존성 정보
├── README.md           // 프로젝트 설명서

4. 프로젝트 실행

 

프로젝트가 생성되면, 로컬 개발 서버를 실행하여 애플리케이션을 확인할 수 있습니다.

 

개발 서버 실행:

cd my-project
npm run serve

 

npm run serve 명령어를 실행하면, 로컬 개발 서버가 시작되고, 애플리케이션을 브라우저에서 확인할 수 있습니다. 일반적으로 http://localhost:8080에서 실행됩니다.

 

5. 주요 파일 및 설정

 

프로젝트의 주요 파일과 설정에 대해 이해하는 것이 중요합니다.

 

package.json:

프로젝트의 메타데이터 및 의존성 정보를 포함합니다.

스크립트 섹션에서 다양한 명령어를 정의할 수 있습니다.

예:

{
  "name": "my-project",
  "version": "0.1.0",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-service": "~4.5.0"
  }
}

main.js:

Vue 애플리케이션의 진입 파일로, Vue 인스턴스를 생성하고, 루트 컴포넌트를 마운트합니다.

예:

import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
}).$mount('#app');

 

App.vue:

루트 컴포넌트로, 애플리케이션의 주요 구조를 정의합니다.

예:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  components: {
    HelloWorld
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

요약

 

1. 개발 환경 설정: Node.js와 Vue CLI 설치.

2. 새로운 Vue 프로젝트 생성: Vue CLI를 사용하여 프로젝트 생성.

3. 프로젝트 디렉토리 구조: 프로젝트의 기본 구조 이해.

4. 프로젝트 실행: 로컬 개발 서버를 통해 애플리케이션 확인.

5. 주요 파일 및 설정: package.json, main.js, App.vue 등의 주요 파일 이해.

반응형
반응형

1. Vue.js 소개

 

Vue.js는 경량의 점진적 프레임워크로, 사용자 인터페이스를 구축하는 데 사용됩니다. Vue는 주요 라이브러리 부분만으로도 충분히 활용할 수 있지만, 복잡한 애플리케이션을 개발할 때는 다양한 도구와 라이브러리들을 포함하는 생태계를 제공합니다.

 

주요 특징

 

컴포넌트 기반 구조: 재사용 가능한 컴포넌트를 통해 복잡한 UI를 효율적으로 관리할 수 있습니다.

반응형 데이터 바인딩: 데이터와 DOM이 자동으로 동기화되어 개발자 경험을 향상시킵니다.

유연성: 프로젝트의 크기와 복잡도에 맞게 필요한 기능만 선택적으로 사용할 수 있습니다.

친화적인 학습 곡선: 기본적인 HTML, CSS, JavaScript 지식만으로 쉽게 학습할 수 있습니다.

 

2. Vue.js 기본 개념

 

2.1 Vue 인스턴스

 

Vue 애플리케이션의 모든 것은 Vue 인스턴스에서 시작합니다. Vue 인스턴스를 생성하여 특정 DOM 요소에 연결하고, 데이터와 메소드를 정의합니다.

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
});

2.2 템플릿 문법

 

Vue는 HTML 기반 템플릿 문법을 사용하여 DOM에 데이터를 바인딩합니다. Vue의 템플릿 문법은 선언적 렌더링을 가능하게 합니다.

 

Mustache 구문: 데이터를 HTML로 바인딩하는 구문입니다.

<span>{{ message }}</span>

 

디렉티브: v- 접두사를 사용하는 특수 속성으로, HTML 요소에 Vue의 반응형 기능을 제공합니다.

v-bind: 속성 바인딩

v-model: 양방향 데이터 바인딩

v-if, v-else, v-show: 조건부 렌더링

v-for: 리스트 렌더링

 

2.3 데이터 바인딩과 이벤트 처리

 

Vue는 데이터 바인딩과 이벤트 처리를 통해 UI와 데이터의 동기화를 쉽게 할 수 있습니다.

 

데이터 바인딩: Vue 인스턴스의 데이터 속성을 HTML에 바인딩합니다.

<span>{{ message }}</span>

이벤트 처리: v-on 디렉티브를 사용하여 이벤트를 처리할 수 있습니다.

<button v-on:click="reverseMessage">Reverse Message</button>

 

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('');
    }
  }
});

 

2.4 컴포넌트

 

컴포넌트는 Vue의 핵심 기능으로, 재사용 가능한 UI 블록을 생성합니다. 컴포넌트를 통해 복잡한 애플리케이션을 모듈화하여 관리할 수 있습니다.

 

전역 등록:

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
});

 

로컬 등록:

var Child = {
  template: '<div>A custom component!</div>'
};

new Vue({
  el: '#app',
  components: {
    'my-component': Child
  }
});

 

2.5 Vue 인스턴스의 생명주기

 

Vue 인스턴스는 생성부터 소멸까지 여러 생명주기 단계를 거칩니다. 각 단계에서 특정 이벤트가 발생하며, 이 이벤트를 통해 특정 시점에 로직을 실행할 수 있습니다.

 

생명주기 훅: created, mounted, updated, destroyed 등 다양한 훅을 통해 애플리케이션의 생명주기 동안 특정 작업을 수행할 수 있습니다.

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  created: function () {
    console.log('Vue instance is created');
  }
});

요약

 

Vue 인스턴스: Vue 애플리케이션의 기본 단위로, 데이터와 DOM 요소를 연결합니다.

템플릿 문법: 선언적 렌더링을 위한 HTML 기반 문법입니다.

데이터 바인딩: Vue의 반응형 데이터 바인딩으로 데이터와 UI를 동기화합니다.

컴포넌트: 재사용 가능한 UI 블록을 통해 애플리케이션을 모듈화합니다.

생명주기: Vue 인스턴스의 생성부터 소멸까지의 단계로, 각 단계에서 특정 로직을 실행할 수 있습니다.

반응형
반응형

 

1. Google Cloud Console 접속:

2. 프로젝트 선택 또는 생성:

  • 기존 프로젝트가 있다면 선택합니다.
  • 새 프로젝트를 만들려면 상단의 프로젝트 선택 드롭다운 메뉴에서 "새 프로젝트"를 선택합니다.

 

 

3. API 및 서비스 대시보드로 이동:

  • 왼쪽 메뉴에서 "API 및 서비스"를 선택합니다.

4. OAuth 동의 화면 설정:

  • 왼쪽 메뉴에서 "OAuth 동의 화면"을 선택합니다.
  • 외부 또는 내부 사용자 유형을 선택하고 "만들기"를 클릭합니다.
  • 필요한 정보를 입력하고 저장합니다.

 

extrenal 을 사용해줍니다.

 

앱 이름 및 연락처만 등록 후 [저장 후 계속]

[저장 후 계속]

테스트 할 계정을 추가해주세요.
테스트 user 의 경우 오픈전에 설정해주어야 계정 테스트가 가능합니다. 

유저 추가후 [저장 후 계속]

 

위 과정까지 입력해주고 넘어갑니다.

여기까지 OAuth 동의 화면 완료

5. 사용자 인증 정보 생성:

  • 왼쪽 메뉴에서 "사용자 인증 정보"를 선택합니다.
  • "사용자 인증 정보 만들기" > "OAuth 클라이언트 ID"를 클릭합니다.

[상단에 사용자 인증 정보 만들기] [OAuth 클라이언트 ID] 버튼 클릭

애플리케이션 유형 선택:

  • "애플리케이션 유형"에서 "웹 애플리케이션"을 선택합니다.

애플리케이션 정보 입력:

  • 이름을 입력합니다 (예: "PopupGo Web Client").
  • "승인된 JavaScript 원본"에 개발 서버 URL을 추가합니다 (예: http://localhost:5173). -> 프론트
  • "승인된 리디렉션 URI"에도 개발 서버 URL을 추가합니다 (예: http://localhost:5173/oauth2/callback). -> 인증 후 redirect 할 주소. 해당 리다이렉트 파라미터에 access_token 을 받아올 수 있음. - 필자는 프론트 리다이렉트로 처리함.
  • 실제 배포 시에는 프로덕션 URL도 추가해야 합니다.

리다이렉션 URI 까지 입력 후 [만들기] 버튼 클릭

잘려진 화면 우측에 id 및 비밀번호가 보입니다. 

 

  • 클라이언트 ID 확인:
    • 생성된 클라이언트 ID가 표시됩니다. 이것이 YOUR_GOOGLE_CLIENT_ID 대신 사용할 값입니다.
  • 클라이언트 ID 보관:
    • 이 클라이언트 ID를 안전하게 보관하세요.
    • 언제든 "사용자 인증 정보" 페이지에서 다시 확인할 수 있습니다.

보안 주의사항:

  • 클라이언트 ID는 공개될 수 있는 정보이지만, 클라이언트 시크릿은 절대 공개되어서는 안 됩니다.
  • 프로덕션 환경에서는 클라이언트 ID를 환경 변수로 관리하는 것이 좋습니다.

이렇게 얻은 클라이언트 ID를 로그인 버튼 있는 파일의 YOUR_GOOGLE_CLIENT_ID 부분에 붙여넣으면 됩니다. 예를 들어:

 

로그인 버튼 클릭시 메소드

loginWithGoogle() {
      const clientId = '~~~~.apps.googleusercontent.com'; // Replace with your actual client ID
      const redirectUri = 'http://localhost:5173/oauth2/callback'; // The URL where you want to handle the response
      const scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';
      const responseType = 'token';

      const authUrl = `https://accounts.google.com/o/oauth2/auth?` +
                      `client_id=${clientId}&` +
                      `redirect_uri=${redirectUri}&` +
                      `response_type=${responseType}&` +
                      `scope=${scope}`;

      window.location.href = authUrl;
    }

해당 메소드를 실행하면 구글 로그인 할 수 있는 계정이 나옵니다.

 

 

계속을 누르면 링크가 이동 됩니다. 
여기서 리다이렉트를 서버 api 로 받아도 되고, 다시 프론트로 받고 백엔드로 다시 요청해서 처리해도 됩니다.
저는 리다이렉트 url 을 프론트로 했기 때문에 해당 프론트 페이지에서 토큰을 추출 후 서버로 요청했습니다. 

 

프론트 리다이렉트 url 
http://localhost:5173/oauth2/callback 
해당 경로로 프론트 페이지를 만들어 줍니다. 

 

해당 리다이렉트 페이지로 오면 토큰 추출 후 백엔드 api 를 호출해줍니다.

handleOAuth2Callback() {
    const hashParams = new URLSearchParams(window.location.hash.substring(1));
    const accessToken = hashParams.get('access_token');
    console.log(accessToken)
    if (accessToken) {
      fetch('http://localhost:8080/api/oauth2/google', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ token: accessToken })
      })
      .then(response => response.json())
      .then(data => {
        if (data.success) {
          localStorage.setItem('jwt', data.jwt); // JWT 토큰을 로컬 스토리지에 저장
          this.$router.push('/home');
        } else {
          alert('Authentication failed');
        }
      });
    } else {
      alert('Failed to get access token from URL');
    }
  }


응답 후 처리 방식은 각자 코드에 맞게 수정해주시면 됩니다. 

그리고 프론트 리다이렉트 페이지에서 요청하는 백엔드 api 호출하면 됩니다. 
해당 백엔드 api 에서는 가져온 토큰으로 서버에서 구글 토큰에 해당하는 유저정보를 가지고 옵니다. 

 

@Slf4j
@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/api/oauth2")
public class OAuth2Controller {

    @PostMapping("/google")
    public ResponseEntity<?> googleLogin(@RequestBody Map<String, String> body) {
        log.info("start google login");
        String token = body.get("token");
        log.info("Received token: {}", token);
        String url = "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=" + token;
        RestTemplate restTemplate = new RestTemplate();
        try {
            log.info("Requesting token info from Google API");
            Map<String, Object> tokenInfo = restTemplate.getForObject(url, Map.class);
            log.info("Token info received: {}", tokenInfo);
            String email = (String) tokenInfo.get("email");
            log.info(email);
            // 사용자 정보를 통해 인증 및 세션 관리 로직 추가
            return ResponseEntity.ok(Map.of("success", true, "email", email));
        } catch (Exception e) {
            log.error("Error during Google login", e);
            return ResponseEntity.status(401).body(Map.of("success", false, "error", e.getMessage()));
        }
    }
}

 

security 가 적용되어 있다면 해당 api 허용되게 수정해주시면 됩니다. 

.requestMatchers("/api/oauth2/**").permitAll()

 

 

혹여나 안된다면 controller 에 cors 허용 되어있는지 확인해주시면 됩니다.

 

위의 코드로 작성해준다면 백엔드 api 에서 oauth 라이브러리를 import 하지 않아도 됩니다. 

반응형

+ Recent posts