-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java/Seogeurim #10
Merged
Java/Seogeurim #10
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9b3eba4
[Java] java overview 이론정리
Seogeurim a393daf
[Java] java basic 이론정리
Seogeurim cf16a1b
[Java] java basic 이론정리
Seogeurim 2b1a375
[java] java basic 이론정리
Seogeurim 1a842ef
[Java] java이론 목차정리
Seogeurim 638f546
[Java] java이론 목차정리
Seogeurim 8f55308
[java] 객체지향 이론정리
Seogeurim f1a0945
[java] 객체지향 이론정리
Seogeurim 2a689c9
[java] 자바논리연산자 이론정리 수정
Seogeurim File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,8 @@ | |
|
||
## Java | ||
|
||
- [자바 언어의 구조와 기본 문법](./java/1.md) | ||
- [객체지향 핵심 원리](./java/2.md) | ||
- 자바 API 활용 | ||
|
||
## C++ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
# 자바 언어의 구조와 기본 문법 | ||
|
||
> 작성자 : [서그림](https://github.com/Seogeurim) | ||
|
||
<details> | ||
<summary>Table of Contents</summary> | ||
|
||
- [Java 언어의 탄생 배경](#java-언어의-탄생-배경) | ||
- [Java의 10가지 특징](#java의-10가지-특징) | ||
- [Java 플랫폼](#java-플랫폼) | ||
- [Java 프로그램 구조](#java-프로그램-구조) | ||
- [Java 데이터 타입과 변수](#java-데이터-타입과-변수) | ||
- [Java 연산자](#java-연산자) | ||
- [Java의 배열](#java의-배열) | ||
- [Java 제어문](#java-제어문) | ||
|
||
</details> | ||
|
||
## Java 언어의 탄생 배경 | ||
|
||
### 썬마이크로시스템즈의 Green Project에서 시작 | ||
|
||
Green Project에서는 가정용 전자기기의 통합적 제어를 위해, 전자기기에서 사용되는 작은 컴퓨터 언어를 제안했다. 가정용 전자기기에 사용되는 power나 memory가 열악했기 때문에 여기에 사용되는 언어는 작고 견고하고, 신뢰할 수 있는 코드를 필요로 했다. 또한 다른 CPU가 선택될 수 있기 때문에 특정 디바이스에 종속되면 안 되었다. 따라서 **Virtual Machine에서 동작하는 중간 코드를 생성하여 이식성이 높은 언어를 디자인**하게 되었다. | ||
|
||
초기에는 절차 지향 + 객체 지향 언어인 C++ 기반으로 개발되었다. 하지만 C++ 언어가 가진 한계에 부딪혀 **완벽한 객체 지향 언어**인 Oak 언어를 개발하였고, 이미 존재하는 이름이라 추후 **Java**로 이름이 바뀌게 되었다. | ||
|
||
그 후 Java를 기반으로 한 HotJava라는 웹 브라우저를 제작하였는데, Java의 Applet 이라는 기능을 보여주기 위해 브라우저가 중간 코드(Bytecode)를 해석할 수 있도록 만들었다. 이 때 자바 붐이 일어나 Java 언어가 급격히 확산되었다. 이후 많은 업체들이 Java를 지원하기 시작하였고, 1996년 자바 2 플랫폼이라고 명명되었던 자바 버전 1.2가 출시되었다. 그리고 현재까지 많은 버전들이 출시되고 있다. | ||
|
||
## Java의 10가지 특징 | ||
|
||
1. **단순 (Simple)** | ||
C(절차 지향) + C++(객체 지향) 언어를 기초로 하지만, C언어의 복잡한 기능을 제외하여 코드를 단순하게 작성할 수 있다. 특히 가비지 컬렉터(Garbage Collector)에 의한 자동 메모리 관리로 할당된 메모리 해제를 신경쓰지 않아도 된다. | ||
2. **객체지향 (Object-Oriented)** | ||
자바는 객체 지향 언어로, 언어라는 객체를 사용해 프로그램을 작성하도록 한다. 이로써 **재사용성(Reusability)** 을 높일 수 있다. 코드의 재사용, 객체의 재사용 뿐만 아니라 수많은 클래스 라이브러리들을 API로 제공함으로서 재사용성을 높이고 있다. | ||
3. **분산 처리 (Distributed)** | ||
Java는 분산 환경에서 TCP/IP 등의 프로토콜을 통해 효율적으로 실행할 수 있도록 설계된 언어이다. Java는 다음을 지원한다. | ||
- TCP/IP 네트워크 기능 내장 | ||
- HTTP, FTP 등과 같은 프로토콜에 대한 라이브러리 제공 | ||
- 서로 다른 컴퓨터 상의 객체들도 원격으로 호출하여 실행할 수 있는 원격 메서드 호출과 관련된 RMI(Remote Method Invocation) 기능의 라이브러리 제공 | ||
4. **인터프리터 (Interpreter)** | ||
프로그래밍 언어는 인터프리터 언어, 컴파일 언어로 나뉜다. 자바는 **컴파일 언어인 동시에 인터프리터 언어**이며, 인터프리터에 의해 실행된다. 자바 프로그램은 다음과 같은 실행 과정을 거친다. | ||
- 소스코드(.java) ▶︎ **컴파일(Compile): javac** ▶︎ 중간코드(.class): 바이트 코드, 클래스 파일 ▶︎ **기계어로 해석(Interprete): java** ▶︎ 실행 | ||
5. **견고 (Robust)** | ||
다양한 플랫폼(컴퓨터) 상에서 실행되기 위해서는 **높은 신뢰성**이 중요하다. 자바는 다음과 같은 기능들을 지원함으로서 높은 신뢰성을 구현하였다. | ||
- 포인터를 사용하지 않음 | ||
- 가비지 컬렉션(Garbage Collector) 기능 | ||
- 엄격한 데이터 타입의 검사 : 에러 조기 발견 | ||
- Runtime 에러 처리 | ||
6. **안전 (Secure)** | ||
컴파일 시 엄격한 검사를 통해 프로그램 실행 시 발생할 수 있는 장애를 미리 방지한다. 소스코드가 컴파일된 .class 형태의 바이트코드는 **클래스 로더**, **바이트 코드 검증기**를 거친다. 이 때 문제가 없으면 인터프리터로 넘겨 실행하게 된다. | ||
- 클래스 로더 : 코드가 자신/다른 컴퓨터에서 온 것인지 판단하고 **코드를 분리**한다. | ||
- 바이트 코드 검증기 : **코드를 검증**하여 문제가 없을 시 인터프리터로 넘긴다. | ||
7. **플랫폼 독립적 (Architecture Neutral)** | ||
운영체제, CPU 등의 **하드웨어 사양에 관계 없이 실행**될 수 있다. 작성된 자바 프로프램은 자바 컴파일러를 거쳐 자바 가상 머신에서 기계어로 번역되게 된다. 번역된 기계어 코드는 하드웨어 사양에 관계 없이 동일하게 실행된다. | ||
8. **높은 성능 (High Performance)** | ||
**가비지 컬렉션(Garbage Collection) 기능**이 추가되어 있어 자동으로 메모리 관리가 가능하다. 이는 메모리가 할당된 객체의 상태를 추적하여 더 이상 참조되지 않으면 자동으로 할당된 메모리를 해제하여 불필요한 메모리 낭비를 방지하는 기능이다. | ||
9. **멀티스레드 (Multithread)** | ||
자바는 멀티스레드를 지원한다. 이는 한 번에 여러 개의 스레드가 동시에 수행되는 과정으로, 하나의 CPU가 여러 프로그램을 동시에 수행하도록 함으로서 수행 속도를 빠르게 한다. | ||
10. **동적 (Dynamic)** | ||
자바는 변화되는 환경에 잘 적응하도록 설계된 언어이다. 따라서 기존의 프로그램에 영향을 주지 않고 라이브러리에 새로운 메서드나 속성들을 추가할 수 있으며, 프로그램 간 라이브러리의 연결을 Runtime에 수행함으로써 라이브러리의 변화를 곧바로 적용할 수 있다. | ||
|
||
## Java 플랫폼 | ||
|
||
플랫폼(Platform)이란, 프로그램이 실행될 수 있는 HW 및 SW 환경을 의미한다. | ||
|
||
일반적인 플랫폼은 하드웨어 및 하드웨어를 제어하는 운영체제로 구성되어 있지만, 자바 플랫폼은 소프트웨어만으로 구성된다. 자바 플랫폼은 일반적으로 JDK(Java Development Kit)라는 툴로 설치된다. | ||
|
||
### 자바 플랫폼의 종류 | ||
|
||
- **Java SE (Java 2 Platform Standard Edition)** | ||
가장 기본이 되는 에디션, 자바 언어 대부분의 패키지가 포함된다. | ||
- **Java EE (Java 2 Platform Enterprise Edition)** | ||
현업에서 사용되는 API들이 집약된 에디션이다. (JSP, Servlet, JDBC 등) | ||
- **Java ME (Java 2 Platform Micro Edition)** | ||
모바일 기기 등에서 사용되는 API가 포함된 에디션이다. | ||
|
||
### 자바 플랫폼의 구조 | ||
|
||
자바 프로그램은 **자바 가상 머신** 위에서 동작한다. 자바 가상 머신에는 **자바 API** (자바 프로그램을 작성하는 데 기본적으로 활용할 수 있는 클래스 라이브러리, 즉 표준 API 라이브러리)가 제공된다. | ||
|
||
![image](https://user-images.githubusercontent.com/22045163/104326478-20603f80-552d-11eb-8845-4a6bf5218570.png) | ||
|
||
**자바 가상 머신(JVM, Java Virtual Machine)** 은 자바 프로그램과 운영체제 중간에 존재하여 서로를 분리함으로써, 애플리케이션이 운영체제에 영향 받지 않고 동작할 수 있는 환경을 제공한다. 단, JVM은 운영체제와 직접적으로 통신을 해야 하기 때문에 운영체제에 맞는 JVM을 설치해주어야 한다. | ||
|
||
**자바 API(Application Programming Interface)** 는 프로그래머가 필요로 하는 기본적인 클래스(Class)들을 거대한 라이브러리로 미리 만들어서 제공한다. 자바 언어 자체는 작고 단순한 구조를 갖지만, 많은 기능들을 API에서 제공하고 있다. 자바 API는 관련된 기능의 클래스들을 묶어 패키지의 형태로 제공한다. _(주요 패키지 : java.applet, java.awt, java.io, java.lang, java.net, javax.swing, java.util)_ | ||
|
||
## Java 프로그램 구조 | ||
|
||
- **자바 클래스(class)** 는 자바 프로그램의 최소 구성 단위로, 선언된 클래스 내부에 실행에 필요한 변수나 메서드 등이 정의된다. 일반적으로 자바 프로그램은 하나의 `.java` 파일에 하나의 클래스 정의를 원칙으로 한다. | ||
- **자바 애플리케이션** 은 바이트 코드로 번역된 후에 바로 실행할 수 있는 프로그램이다. 클래스 내에 `main()` 메서드를 가지고 있어야 한다. | ||
- 자바는 **블록(`{}`)** 으로 자바 문장들의 집합을 표현한다. 블록의 시작과 끝이 짝을 이루지 않으면 컴파일 오류가 발생하며, 클래스, 메서드, 자바 구문(`if`, `for`, `try-catch` 등)에 사용된다. | ||
- 자바 문장은 **세미콜론(`;`)** 을 사용해 문장들을 구분한다. | ||
|
||
```java | ||
public class 클래스명 { | ||
// 변수 정의 | ||
// 메서드 정의 | ||
public static void main(String args[]) { | ||
// 실행될 프로그램 코드 | ||
} | ||
} | ||
``` | ||
|
||
## Java 데이터 타입과 변수 | ||
|
||
- **데이터 타입**은 데이터의 성격을 규정한다. | ||
- 사용할 데이터를 **변수**에 저장하고 관리함으로써 데이터의 의미를 정확하게 해석하여 사용할 수 있다. | ||
|
||
### 데이터 타입 | ||
|
||
| 표현형태 | 데이터 타입 | 크기 | 표현 범위 | (자동 초기화 시) 초기값 | | ||
| :-------: | :---------: | :-----------: | :-------------------------------: | :---------------------: | | ||
| 논릿값 | boolean | 1bit | true/false | false | | ||
| 단일 문자 | char | 16bit (2byte) | `'\u0000'` ~ `'\uffff'` | `'\u0000'` (Null) | | ||
| 정수 | byte | 8bit (1byte) | -2^7 ~ 2^7-1 (-128 ~ 127) | 0 | | ||
| 정수 | short | 16bit (2byte) | -2^15 ~ 2^15-1 (-32768 ~ 32767) | 0 | | ||
| 정수 | int | 32bit (4byte) | -2^31 ~ 2^31-1 (약 -21억 ~ 21억) | 0 | | ||
| 정수 | long | 64bit (8byte) | -2^63 ~ 2^63-1 | 0L | | ||
| 실수 | float | 32bit (4byte) | 1.4E-45 ~ 3.4028235E38 | 0.0F | | ||
| 실수 | double | 64bit (8byte) | 4.9E-324 ~ 1.7976931348623157E308 | 0.0D | | ||
|
||
\* 정수 : 부호가 있는 정수, 형을 명시하지 않으면 `int`가 기본형 | ||
\* 실수 : 부호가 있는 부동소수점 실수, 형을 명시하지 않으면 `double`이 기본형 | ||
_(부동소수점이란, 컴퓨터가 소수점이 포함된 실수를 표현하는 방식 중 하나이다. 이는 고정소수점과 달리 소수점을 자유로이 움직일 수 있어서 표현할 수 있는 수의 범위가 매우 넓다는 장점이 있다.)_ | ||
\* 초기화 : 메서드(함수) 안에서 선언된 변수인 지역변수는 자동으로 초기화되지 않는다. | ||
\* 참조형(Reference Type) 변수의 초기값 : `null` | ||
|
||
#### 데이터 타입의 범위 초과 시 발생하는 오류 | ||
|
||
- 컴파일 오류 : **변수 초기화 시** 범위를 초과하는 경우 발생 | ||
- 런타임 오류 : **연산 결과**로 범위를 초과하는 경우 발생 | ||
|
||
#### 데이터 타입의 변환, 형변환 | ||
|
||
변수의 타입을 다른 타입으로 변경하고자 할 때, **형변환 연산자**를 사용해 변환할 수 있다. 작은 데이터 타입에서 큰 데이터 타입으로 변환하는 것을 **묵시적 형변환(Promotion)**, 그 반대를 **명시적 형변환(Demotion)** 이라고 한다. | ||
|
||
- **묵시적 형변환(Promotion)** : 데이터 손실의 우려가 없어 자동 캐스팅 가능하다. **(자동 형변환)** | ||
|
||
```java | ||
int age = 25; | ||
double avgAge = age; // double avgAge = (double)age; | ||
``` | ||
|
||
- 위와 같이 형변환 연산자인 `(double)`을 생략할 수 있다. | ||
- 단, 다음의 규칙에 따라 자동 형변환이 이루어진다. | ||
- byte -> short -> int -> long -> float -> double 순 | ||
- char -> int -> long -> float -> double 순 | ||
|
||
- **명시적 형변환(Demotion)** : 더 작은 범위를 나타내는 데이터 타입으로 변환하기 때문에 데이터 손실의 우려가 있어 명시적 캐스팅이 필요하다. **(축소 형변환)** | ||
|
||
```java | ||
double avgAge = 24.56; | ||
int age = (int)avgAge; | ||
``` | ||
|
||
- 위와 같이 형변환 연산자를 명시해주어야 한다. | ||
- 단, 데이터 타입이 축소되어 변환된 후에도 해당 값을 표현할 수 있어야 한다. 다음은 올바르지 못한 예이다. | ||
|
||
```java | ||
int sum = 128 | ||
byte data = (byte)sum // -128 | ||
``` | ||
|
||
### 변수 | ||
|
||
- 변수는 컴퓨터 내부의 데이터와 1:1 대응되어 변수를 통해 메모리상의 데이터에 접근 가능하다. | ||
- 기본형(Primitive Type)과 참조형(Reference Type) 두 가지 변수가 존재한다. | ||
- 전역(Global) 변수와 지역(Local) 변수로 선언할 수 있다. | ||
- 변수는 자신이 속한 블록({})을 벗어나면 사용이 불가하다. | ||
|
||
#### 전역(Global) 변수와 지역(Local) 변수 | ||
|
||
- **전역(Global) 변수** : 클래스 선언부 밑에 선언된 변수로, 여러 메서드에서 공통으로 사용할 수 있다. | ||
- **지역(Local) 변수** : 메서드 선언부 밑 또는 메서드 매개변수로 선언된 변수로, 해당 변수가 선언된 메서드 내에서만 사용 가능하다. | ||
|
||
#### 변수 선언 | ||
|
||
- 자바 가상 머신(JVM)에게 데이터를 저장하기 위한 메모리 할당을 요청하는 것이다. | ||
- 데이터가 필요로 하는 크기의 메모리 할당을 위해 데이터 타입을 명시해야 한다. | ||
|
||
## Java 연산자 | ||
|
||
### 산술 연산자 | ||
|
||
- 정수형, 실수형에 사용됨 | ||
- 증감 연산자 : `++`, `--` (단항) | ||
- 부호 연산자 : `+`, `-`, `*`, `/` (이항) | ||
- 나머지 연산자 : `%` (이항) | ||
|
||
### 비교 연산자 | ||
|
||
- 대소 비교나 객체의 타입 비교 등에 사용됨 | ||
- 비교 연산을 수행한 결과로 `boolean` 타입의 결과를 리턴함 | ||
- `>`, `>=`, `<`, `<=`, `==`, `!=`, `instanceof` | ||
- `값1 instanceof 값2` : `값1`이 `값2` 데이터 타입의 객체인 경우 `true` 반환 | ||
|
||
### 논리 연산자 | ||
|
||
- `boolean` 데이터 타입에 적용되며, `boolean` 타입의 결과를 리턴함 | ||
- `&`, `&&`, `|`, `||`, `!` | ||
- `값1 && 값2`의 경우, `값1`이 `false`인 경우 `값2`를 수행하지 않고 `false`를 리턴한다. | ||
- `값1 || 값2`의 경우, `값1`이 `true`인 경우 `값2`를 수행하지 않고 `true`를 리턴한다. | ||
- `&`, `|` 연산자는 모든 조건을 다 확인한 후 그 결과를 리턴한다. | ||
|
||
### 비트 연산자 | ||
|
||
- 값을 비트(bit)로 연산하는 연산자 | ||
- 메모리를 최대한 효율적으로 활용해야 하는 경우 비트 단위로 데이터를 관리해야 한다. | ||
- `&` 논리곱(and), `|` 논리합(or), `^` 배타 논리합(exclusive or, XOR), `~` 보수(not) | ||
- `>>`, `>>>`, `<<` 시프트 | ||
- `값1 >> 값2` : `값1`을 비트 단위로 `값2`의 비트 수만큼 오른쪽으로 시프트, 왼쪽에는 현재 부호 비트가 채워짐 | ||
- `값1 >>> 값2` : `값1`을 비트 단위로 `값2`의 비트 수만큼 오른쪽으로 시프트, 왼쪽에는 0이 채워짐 | ||
- `값1 << 값2` : `값1`을 비트 단위로 `값2`의 비트 수만큼 왼쪽으로 시프트, 오른쪽에는 0이 채워짐 | ||
|
||
### 기타 연산자 | ||
|
||
- 대입 연산자 (`=`) : 변수의 값을 저장, 오른쪽의 값을 왼쪽에 대입 | ||
- 조건 삼항 연산자 (`? :`) : `if~else`문을 축약하여 사용할 수 있다. | ||
- `변수 = 조건 ? 값1 : 값2` : 조건이 참이면 `값1`이 변수에 대입되고, 거짓이면 `값2`가 변수에 대입된다. | ||
|
||
## Java의 배열 | ||
|
||
배열은 같은 타입의 데이터들의 모임으로, 메모리가 절약되고, 쉽고 간결하게 프로그램을 작성할 수 있다. | ||
|
||
### 일차원 배열의 선언과 사용 | ||
|
||
- 배열 객체를 참조할 배열 변수 선언 ▶︎ 배열 객체 생성 | ||
- 배열 변수 선언 : `데이터타입 배열변수명[];` 또는 `데이터타입[] 배열변수명;` | ||
- 배열 객체 생성 : `배열변수명 = new 데이터타입[배열의 길이];` | ||
- 두 구문을 합쳐 한 문장으로 표현 가능 | ||
|
||
### 이차원 배열 | ||
|
||
- 다차원 배열 : 일차원 배열을 여러 개 사용하여 다시 배열을 구현한 것, 즉 배열의 배열 | ||
- 배열의 크기를 나타내는 배열 첨자(`[]`)를 차수에 따라 추가하면 된다. | ||
- 배열 객체를 참조할 배열 변수 선언 ▶︎ 배열 객체 생성 | ||
- 배열 변수 선언 : `데이터타입 배열변수명 [][];` 또는 `데이터타입[][] 배열변수명;` 또는 `데이터타입[] 배열변수명 [];` | ||
- 배열 객체 생성 : `배열변수명 = new 데이터타입[배열의 배열 길이][배열 길이];` 또는 | ||
`배열변수명 = new 데이터타입[배열의 배열 길이][]; 배열변수명[인덱스 번호] = new 데이터타입[배열 길이];` | ||
|
||
### 명령행 매개변수 | ||
|
||
`main()` 메서드란, 자바 애플리케이션에 필수적으로 포함되어야 하는 메서드로, 애플리케이션이 실행될 때 자동으로 실행된다. 일반적으로 자바 애플리케이션은 `main()` 메서드 내에서 다른 클래스 객체를 생성하고, 그 객체의 메서드 호출 또는 변수 조작 과정을 통해 원하는 결과를 얻는다. | ||
|
||
```java | ||
public class CommandLineArgTest { | ||
public static void main(String args[]) { | ||
// code | ||
} | ||
} | ||
``` | ||
|
||
위 코드의 `main()` 메서드를 살펴보면 `String args[]`라는 매개변수를 볼 수 있는데, 이를 **명령행 매개변수**라고 한다. 명령행 매개변수는 문자열 배열을 매개변수로 받아, 프로그램 실행 시 필요한 정보를 프로그램에 전달한다. | ||
|
||
- String 데이터 타입의 배열이다. | ||
- 사용자가 입력한 문자열의 순서에 따라 차례로 배열에 저장된다. | ||
- 공백을 구분자로 여러 개의 값을 전달할 수 있다. | ||
- 문자열 타입이므로 숫자를 입력했을 시 문자열을 숫자로 변환해야 한다. | ||
- 자바 API에서 메서드 제공 : Integer 클래스의 `parseInt()`, Double 클래스의 `parseDouble()` | ||
|
||
## Java 제어문 | ||
|
||
- 조건 제어문 : `if`, `if-else`, `if-else if`, `switch` 문 | ||
- 반복 제어문 : `for`, `while`, `do-while` 문 | ||
- 이동 제어문 : `break`, `continue`, `return` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정하였습니다 !! @Hee-Jae
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오... 이해가 쏙쏙 됐습니다. 전달력이 엄청나시네요!