4장. 정보를 어디에 넣고 싶은데

공부하는 감자·2023년 11월 26일
0

자바의 신 3판

목록 보기
4/30

들어가기 전

『자바의 신 3판』 을 읽고 내용 정리 및 공부한 내용을 정리한 글입니다.
서적: 자바의 신 3판 구입처

내용 정리

자바의 변수 종류

자바에는 총 4개의 변수가 존재한다.

  • 지역 변수 (local variables)

    • 중괄호 내에서 선언된 변수.
    • 중괄호 내에서만 유효하다.
  • 매개 변수 (parameters)

    • 메소드에 넘겨주는 변수.
    • 메소드가 호출될 때 생명이 시작되고, 메소드가 끝나면 소멸된다.
  • 인스턴스 변수 (instance variables)

    • 메소드 밖에, 클래스 안에 선언된 변수.
    • 객체가 생성될 때 생명이 시작되고, 그 객체를 참조하고 있는 다른 객체가 없으면 소멸된다.
  • 클래스 변수 (class variables)

    • 메소드 밖에, 클래스 안에 선언된 static 변수
    • 클래스가 처음 호출될 때 생명이 시작되고, 자바 프로그램이 끝날 때 소멸된다.

※ 인스턴스 변수와 클래스 변수는 static 이냐 아니냐에 따라 달라진다.

💡 할당 해제
C나 C++이라는 언어는 할당(allocation)을 한 변수에 어떤 값을 지정했으면, 개발자가 추후 할당을 해제할 수 있다. 그러면 바로 메모리에서 사라진다.
하지만 자바에서는 가비지 콜렉터(Garbage collector)가 알아서 메모리를 청소해 주기 때문에, 개발자가 임의로 할당 해제할 수가 없고 해서도 안 된다.

변수의 이름

한글로 변수 이름을 지정해도 컴파일하는 데 문제는 없지만, 기본적인 규칙은 다음과 같다.

  • 길이의 제한은 없다
  • 첫 문자는 유니코드 문자, 알파벳, $(달러표시, dollar sign), (언더스코어, underscore)만 올 수 있다. 그런데 보통 변수 이름은 일반적으로 $와 로 시작하지 않는다.
  • 두 번째 문자부터는 유니코드 문자, 알파벳, 숫자, $, _ 중 아무것이나 사용할 수 있다.
  • 첫 문자는 소문자로 시작하는 단어이고, 두 번째 단어의 첫 문자만 대문자로 시작한다.
  • 상수(constant value)의 경우에는 모두 대문자로 지정하며, 단어와 단어 사이에는 _로 구분을 한다.

명명 표기법 종류

책의 내용이 아닌, 추가로 찾아서 기입한 것이다.
출처

변수, 함수, 클래스 등 이름을 짓는 다양한 표기법들이 있다. 카멜 표기법, 스네이크 표기법, 파스칼 표기법이 그 대표적인 예다.

  • 카멜 표기법(Camel case)
    • 예: camelCase
    • ‘카멜’은 낙타로, 낙타의 등에 혹이 불룩하게 나와있는 것과 비슷해 붙은 이름.
    • 각 단어의 첫 글자를 대문자로 표기하되 첫 단어의 첫 글자는 소문자로 표기하는 방식이다.
  • 파스칼 표기법(Pascal case)
    • 예: PascalCase
    • 파스칼 언어에서 이러한 표기법을 사용해서 붙은 이름.
    • 각 단어의 첫 글자와 첫 단어의 첫 글자 모두 대문자로 표기한다.
    • 클래스의 이름은 파스칼 표기법을 사용하는게 보통이다.
  • 스네이크 표기법(Snake case)
    • 예: snake_case
    • 땅바닥을 기어다니는 뱀의 모양과 비슷하다고 해서 붙은 이름.
    • 모두 소문자(혹은 모두 대문자)로 쓰되, 띄어쓰기를 밑줄(_) 기호로 대체한다.
    • 대소문자를 구별하지 않는 언어라면 스네이크 표기법을 사용한다.
    • Java는 상수(static final 변수)와 enum 값 이름에 대문자 스네이크 표기법을 쓴다.
  • 케밥 표기법(Kebab case)
    • 예: kebab-case
    • 케밥 꼬치에 재료가 듬성듬성 꽂혀있는 것과 비슷해 붙은 이름.
    • 모두 소문자(혹은 대문자)로 쓰되, 띄어쓰기를 하이픈(-) 기호로 대체한다.
    • 하이픈은 뺄셈 기호로도 쓰이기 때문에 일반 프로그래밍 언어에서는 잘 안쓰이는 편이다.
  • 헝가리안 표기법(Hungarian notation)
    • 예: strHungarianNotation
    • 대소문자를 뜻하는 case 대신에 표기법을 뜻하는 notation을 사용하는데, 이는 대소문자 문제가 아니기 때문이다.
    • 첫 단어를 포함해서 모든 단어의 첫 글자를 대문자로 하되, 그 앞에 변수의 유형을 뜻하는 약어를 소문자로 붙여 준다.
      정수(int)형이라면 i, 문자열(string)이라면 str을 붙이는 식이다. → 나는 s를 붙이는 경우도 봤다.
    • 이 방법을 처음 고안한 마이크로소프트의 개발자가 헝가리인이었기 때문에 이런 이름이 붙었다.
    • 지금은 잘 안 쓰는 방식이다.

자바의 자료형

자바의 타입(자료형)은 크게 기본 자료형(Primitive data type)과 참조형(Reference data type)으로 나뉜다. 참조 자료형은 우리가 마음대로 만들 수 있지만, 기본 자료형은 정해져 있다.

자료형을 초기화할 때 new라는 예약어를 사용해 초기화하는 것을 참조 자료형, 그렇지 않고 바로 초기화할 수 있는 것을 기본 자료형이라고 한다.

변수 초기화

어떤 변수든 값을 저장하기 위해서 만든다. 저장할 값이 정해져 있다면, 그 값을 지정해주면 되겠지만 항상 저장할 값이 정해져 있지는 않다.

그래서 변수를 선언할 때에는 초기화를 해줘야 변수가 사용할 수 있는 상황이 된다고 기억하면 된다.

초기화할 때 예외로는 참조형 중 String이 있다. String은 두 가지 방식으로 초기화할 수 있다.

  • String str = “god of java”
  • String str = new String(”god of java”);

String만이 참조 자료형이지만 new를 사용해서 객체를 생성하지 않아도 되는 유일한 타입이다. 상세한 내용은 15장에서 설명한다.

기본자료형

기본 자료형은 총 8개다. 기본 자료형은 숫자와 boolean 타입 두 가지로 나뉜다. 그리고 숫자는 정수형과 소수형으로 나뉜다.

  • 정수형: byte, short, int, long, char
  • 소수형: float, double
  • 논리형: boolen

byte, short, int, long, float, double 은 순서대로 해당 타입의 범위가 정해진다.

정수형

정수형에는 byte, short, int, long, char 가 있다. 방금 타입의 범위가 정해진다고 했는데, 자바에서는 숫자의 크기에 제한이 있다.

만약 제한이 없다면, π 같은 무한 소수도 엄청나게 길게 저장할 수 있을 것이다.

정수형 중에서 unsigned(부호가 없는)인 것은 char 뿐이고, 나머지는 부호가 있는 signed 타입들이다.

각 정수형의 타입별 숫자의 범위는 다음과 같다.

타입최소최대
byte27-2^7 (-128)2712^7-1 (127)
short215-2^{15} (-32,768)21512^{15}-1 (32,767)
int231-2^{31} (-2,147,483,648)23112^{31}-1 (2,147,483,647)
long263-2^{63} (-9,223,372,036,854,775,808)26312^{63}-1 (9,223,372,036,854,775,807)
char00 (’\u0000’)21612^{16}-1 (’\uffff’)

컴퓨터는 0과 1을 사용하는 2진법으로 숫자를 표현한다. 따라서 모든 자바의 숫자 타입들은 2의 배수로 그 범위가 정해진다.

byte부터 long까지의 범위를 보면, 8 → 16 → 32 → 64 순으로 두 배씩 범위가 증가하고 있는 것을 볼 수 있다.

2n2^n가 아닌, 2n12^{n-1} 로 표기되고 있는 이유는 바로 부호가 있기(signed) 때문이다. 앞서 말했듯이 컴퓨터는 0과 1로 숫자를 표현하는데, 음수와 양수를 표현해주기 위해 맨 앞의 있는 값을 사용한다.

맨 앞자리의 값이 0이면 양수, 1이면 음수

여기에서 최대값에는 1-1 을 해주고 있는 이유는 바로 0 때문이다. 8비트(1byte)에서 표현하자면 다음과 같다.

0000 0000 0000 00001000 0000 0000 00000000\ 0000 \ 0000 \ 0000 \\ 1000\ 0000 \ 0000 \ 0000

0에는 양수와 음수라는 개념이 없다. 뒤에서 비트 연산자를 배울 때 자세히 알아보겠지만, 일단은 맨 앞자리가 1인 0은 0이 아니라 128(282^8)으로 취급한다.

그러므로 절대값만으로 따지자면 최소값의 절대값이 최대값의 절대값보다 딱 1이 더 크다는 것을 알 수 있다.

연습: 비트의 덧셈과 뺄셈

책에서는 비트를 더하고 빼서 설명을 하는데, 비트의 연산에 대한 설명이 없어 추가한다.

컴퓨터는 0과 1로 된 2진수를 사용한다. 그리고 이러한 2진수의 덧셈은 일반 숫자를 더하는 것과 유사하게 생각하면 된다.

2진수 덧셈 예제

0+0=00+1=11+1=(1)00+0=0\\ 0+1=1\\ 1+1=(1)0

이렇게 1과 1을 더했을 때 앞에 1이 나가며, 이를 캐리(carry)라고 부른다. 만약 앞의 비트가 없으면 이 캐리는 버린다.

컴퓨터에서는 덧셈만 존재하므로, 뺄셈을 할 경우에는 비트를 2의 보수를 취해 더해줘야 한다.

관련 내용은 CS 지식을 정리할 때 자세히 나오겠지만, 일단은 단순히 아래처럼 생각하면 된다.

1의 보수: 모든 비트를 0은 1로, 1은 0으로 바꿔준다.
2의 보수: 1의 보수를 한 상태에서 +1을 해준다.

아래는 십진수 1+1=21+1 = 211=01-1 = 0을 2진수로 변환하여 계산하는 과정이다.

1+1=0001+0001=0010=211=1+(1)=0001+1111=0000=01 + 1 = 0001 + 0001 = 0010 = 2\\ 1 - 1 = 1 + (-1) = 0001 + 1111 = 0000 = 0

정수형의 최소값과 최대값

책에 나온 예제를 이용해 정수형들의 최소값과 최대값에서 각각 1을 더하고 빼보는 코드이다.

기본적으로 자바에서는 숫자를 명시하면 int로 생각하기 때문에, long타입의 숫자를 명시적으로 지정해 줄 때에는 반드시 숫자 가장 뒤에 L을 붙여주어야만 한다.

public void checkByte() {
  byte byteMin = -128;
  byte byteMax = 127;
  System.out.println("byteMin="+byteMin);
  System.out.println("byteMax="+byteMax);
 
  byteMin = (byte) (byteMin - 1);
  byteMax = (byte) (byteMax + 1);
  System.out.println("byteMin="+byteMin);
  System.out.println("byteMax="+byteMax);
 
  short shortMax=32767;
  int intMax = 2147483647;
  long longMax = 9223372036854775807L;
  System.out.println(shortMax + ", " + intMax + ", " + longMax);
 
  shortMax = (short) (shortMax + 1);
  intMax = intMax + 1;
	// longMax + 1 으로 써도 문제없이 실행된다.
  longMax = (long) (longMax + 1);
  System.out.println(shortMax + ", " + intMax + ", " + longMax);
}

(byte) (bytemin-1) 이런 식으로 감싸 형 변환을 시켜준 이유는, 이전 버전의 자바에서는 정상적으로 수행이 되었지만 자바8에서는 컴파일 오류가 발생하게 되어서라고 한다.

short 형 변환 중 발생한 오류가 있어서 해결한 것을 아래에 첨부한다.

  • incompatible types: possible lossy conversion from int to short

작성 중, (short) (shortMax+1) 이렇게 괄호를 빼먹는 실수를 했다.

그러자 위와 같이, int를 short로 바꿀 수 없다는 오류가 발생했다. 그런데, long 형 연산에서는 동일하게 괄호를 빼먹어도 오류가 발생하지 않았다.

이건 자바에서 int보다 작은 정수형의 연산은 모두 int로 취급해서 그렇다고 한다. 따라서 long 형 연산에서는 형 변환을 시키지 않아도 오류없이 실행되는 것이다.

출처: adding two short numbers error

byte 타입을 만든 이유는?

동영상을 저장하고, 이미지를 저장할 때 int를 사용하면 단순히 숫자 하나를 표현하기 위해서 32개의 비트를 표시하기 위한 공간이 필요하다. 즉, byte대비 4배의 저장공간이 더 필요하게 되는 것이다. 그래서 많은 부분에서 데이터를 저장할 때 byte 값들을 조합해서 사용한다. 그래야 적은 공간에 보다 많은 내용을 저장할 수 있다.

JDK 7부터는 숫자 표현을 보다 명확하고 편하게 할 수 있도록 되어 있다. 자세한 내용은 30장의 JDK 7 관련 부분을 참조.

소수형

float 와 double 모두 소수점 값을 처리하기 위해서 사용된다. float는 32비트이며, double은 64비트로 표현된다. 그런데, 이 두 가지의 소수점은 간단한 계산에서는 사용해도 무방하지만 돈 계산과 같이 중요한 부분에서는 사용해서는 안 된다.

왜냐하면 이 타입들은 32비트와 64비트로 제공할 수 있는 범위를 넘어서면 그 값의 정확성을 보장하지 못하기 때문이다. 그래서 자바에서는 돈 계산과 같이 정확한 계산이 요구될 때에는 java.math.BigDecimal 이라는 클래스를 사용해야만 한다. 부록 13의 java.util 패키지 참조.

Oracle의 자바 설명서에는 다음과 같이 정의되어 있다.

  • float: single-precision 32-bit IEEE 754 floating point
  • double: double-precision 64-bit IEEE 754 floating point

float는 “단일-정확도를 가지는 32비트 IEEE 754 부동 소수점”이라고 해석할 수 있다.

소수점 처리를 할 때 일반적으로는 double을 많이 사용한다. 그리고, 대량으로 소수점 자리수가 적은 데이터를 저장하려고할 경우에는 float를 사용하면된다.

이 타입들의 범위를 알려면 복잡한 수학 공식을 알아야 한다. 자세한 설명은 부록을 참고하고, 일단 아래처럼 구성된다는 것만 알아두자.

  • float: 부호(1자리) + 지수(8자리) + 가수(23자리) = 32 비트
  • double: 부호(1자리) + 지수(11자리) + 가수(52자리) = 64 비트

💡 IEEE란?

	IEEE는 국제적인 표준을 의미하고, 754는 그 표준의 번호다.
    각 번호마다 명칭이 있는데, IEEE 754의 정식 명칭은 Standard for Binary Floating-Point Arithmetic이다.

char 값

char 는 “캐릭터-character-”라고 읽는다. 보통 문자열과 관련된 부분에서 사용하며, 정의할 때 홑따옴표를 사용한다.

char는 정수형이므로, 아래와 같이 사용해도 문제는 없다. 왜냐하면 char의 범위(0~65,535)는 int보다 좁기 때문에 이와 같은 형 변환은 가능해야 한다.

int intValue = 'a' // char to int

결과는 아스키코드인 97 로 나온다.

💡 ASCII 코드란?

	미국에서 만들어진 1 byte 단위의 문자들. 
    알파벳, 숫자, 기호를 포함하며 각 문자마다 고정되어 있는 번호가 할당되어 있다. 이 번호는 어떤 컴퓨터, 언어, OS를 가더라도 동일하다.
    
    자바에서는 Unicode라는 2 byte를 사용하기 때문에 ASCII가 할당된 값들이 먼저 나오고, 그 다음에 미리 정해져 있는 유니코드들이 존재한다.

char의 값을 지정하는 방법은 크게 세 가지다.

  • 홑따옴표 안에 직접 값을 넣기
  • 홑따옴표 안에 \u와 16진수의 값을 넣기 (이는 유니코드이다)
  • 해당 값의 유니코드 번호를 지정하기 (단, 그 번호는 char 범위 내의 숫자여야 한다)

char의 올바른 예

char test0 = 'a';
char test1 = '가';
char test2 = '\u1188';
char test3 = 44032;

💡 한글은 대부분 2 바이트로 표현하며 유니코드에 포함되어 있다. 그러므로 사용할 수 있다.

char의 잘못된 예

char test4 = '';	 // Invalid character constant
char test5 = '\u11'; // Invalid unicode
char test6 = 'ab';	 // Invalid character constant
char test7 = "";	 // Type mismatch: cannot convert from String to char
char test8 = -1;	 // Type mismatch: cannot convert from int to char

boolean 값

boolean은 “true”와 “false”, 두 개의 값밖에 없다. 다시 말해서, “참”과 “거짓”밖에 없는 타입이다.

참일 경우 true를, 거짓일 경우 false를 넣는다.

boolean flag1 = true;
boolean flag2 = false;

기본 자료형의 기본 값

자바의 모든 자료형은 값을 지정하지 않으면 기본값을 사용한다. 그런데, 지역 변수로 기본 자료형을 사용할 때에는 기본 값이 자동으로 적용되지 않고, 반드시 값을 지정해야만 한다.

즉, 메소드 안에서 정의한 변수에 값을 지정하지 않고 사용하려고 하면, 컴파일 시 오류가 난다. 인스턴스 변수, 클래스 변수, 매개 변수는 값을 지정하지 않아도 컴파일이 되기는 한다.

하지만, 이렇게 값을 지정하지 않고 개발하는 것은 매우 안좋은 습관이다. 만약 그 변수의 값이 기본 값이라고 할지라도, 명시적으로 기본값을 지정하자.

아래 코드를 컴파일 및 실행해보면 정상적으로 동작한다.

public class PrimitiveTypes {
	int intDefault1;
	public void defaultValues() {
		int intDefault2;
	}
}

여기서 왜 지역 변수인 intDefault2 를 초기화하지 않았는데도 컴파일과 실행이 되는 이유는, intDefault2를 사용하는 부분이 없기 때문이다.

다음과 같이 intDefault2 를 출력하는 코드를 추가하면 컴파일 시 초기화가 되지 않았다는 에러가 난다.

public class PrimitiveTypes {
	int intDefault1;
	public void defaultValues() {
		int intDefault2;
		System.out.println(intDefault1);
		System.out.println(intDefault2);
	}
}

즉, 지역 변수를 만들어 놓고 사용하지 않을 때에는 초기화를 하지 않아도 되지만, 사용할 때에는 반드시 초기화를 해야 한다.

기본 값

  • char를 제외한 모든 숫자의 기본값은 0이다.
  • char의 기본값은 ‘\u0000’ 이다.
  • boolean의 기본값은 false다.

정리해 봅시다.

Q. 네가지 종류 변수는 어떻게 구분할 수 있나요?

Me: 인스턴스 변수, 지역 변수, 매개 변수, 클래스 변수가 있다. 위치로 우선 구분하고, 클래스 변수와 인스턴스 변수는 static으로 구분한다.

Q. 일반 변수의 이름을 지을 때 대문자로 시작하는 것은 일반적인 명명규칙이다.

Me: 아니오

Q. 자료형에는 기본 자료형과 어떤 자료형이 있나요?

Me: 기본 자료형과 참조 자료형이 있다.

Q. 기본 자료형에는 몇가지가 있나요?

Me: 8가지

Q. 기본 자료형 중 정수형에는 어떤 것들이 있나요?

순서를 제대로 쓰지 않으면 구글 폼 제출이 안된다.

Me: int, long, char, byte, short

Q. byte는 몇 비트(bit)로 되어 있나요?

Me: 8비트

Q. byte 타입은 왜 만들었을까요?

Me: 저장공간을 효율적으로 사용하기 위해 int보다 작은 숫자를 사용하는 이미지, 동영상 등에 사용한다.

Q. int와 long중 어떤 타입이 더 큰 숫자를 처리할 수 있나요?

Me: long

Q. 소수점을 처리하는 타입은 어떤 것이 있나요?

Me: float와 double이 있다.

Q. char는 정수형인가요?

Me: 예

Q. a라는 값을 char로 정의할 때 어떤 기호로 감싸주어야 하나요? (기호를 입력하세요)

Me: '’

Q. true와 false 두개의 값만을 가지는 타입은 어떤 것인가요?

Me: boolean

질문

💡 책에 있는 내용이 아닙니다.

책을 읽으며 설명이 더 필요하거나, 추가로 궁금한 점에 대해 질문 형식으로 작성 후, 답을 구해보고 있습니다.
참고한 사이트나 영상은 [출처]로 달아두었으며, 오류 지적은 언제나 환영합니다.

Q. C언어를 공부할 때 전역 변수 개념을 배웠는데, 자바에서는 전역 변수가 없나?

전역변수(global variable)는 함수의 외부에서 선언된 변수이다. 프로그램의 어디에서나 접근할 수 있으며, 프로그램이 종료되어야만 메모리에서 사라진다.

애초에 자바에서는 전역변수를 지원하지 않는다.

참고 사이트

그 이유는 디자인적인 이유에서라고 한다. 자바는 개체지향 언어이고 캡슐화를 통해 은닉성을 보장한다. 전역변수는 해당 언어의 목적과 상반되는 개념이다.

전역변수를 구현하고 싶으면 public static (불변성을 가지고 싶다면 final 을 포함)을 사용할 수 있다.

다만, 위의 이유에서 public static 으로 구현하는 것은 상수를 제외하고는 만들지 않는 게 좋다.

Q 이미지 처리에서 byte를 사용하는 이유가 뭘까?

이미지는 픽셀 단위로 구성되어 있는데, 이미지의 종류에 따라 다르지만 1픽셀이 1Bit(이진 영상)이기도 하고, 1Byte이기도 하다. 굳이 int나 long을 써서 사용하지 않는 메모리도 잡는 것보단, 최소 단위인 Byte를 쓰는 게 아닌가 한다.

유의미한 결과는 못 찾았고, 아래 사이트만 찾았다.

검색 결과: Why Images are represented by byte array?

A collection of bytes is the simplest way to represent an image file as data. A string would not be suitable as it contains character codes, and an image file does not consist of characters. There is no special class for holding the data of an image file, as a byte array works just fine for that.

Any file can be treated as a collection of bytes, so a byte array is the result of reading a file as binary data. A file can also be decoded as a specific format, like a text file which results in a string, or a compressed image format (JPEG, GIF, PNG et.c.) which results in a Bitmap object containing the decompressed image.

이미지 뿐만 아니라 모든 파일은 바이트로 처리할 수 있다. 일단 이 정도만 알고 넘어가자. 나중에 이미지 처리 책을 한 번 찾아봐야겠다.

Q. C에서는 byte를 계산해주는 sizeOf 함수가 자바에도 있는가?

자바에서는 length와 size라는 길이를 구하는 함수를 제공하고 있다. 또한 byte로 변환하는 함수도 있어서 변환 후 length 체크하는 식으로 구할 수 있다.

찾아보니 “{기본자료형의 래퍼클래스}.BYTES” 로도 쓸 수 있는 모양이다.

Q. byte, short, int, long 에 문자열(String) 담으면?

당연히 다른 자료형을 아래처럼 초기화하는 것은 오류가 난다.

Q. char 는 홑따옴표(’’)를 사용하는데, 만약 쌍따옴표를 사용한다면?

당연히 오류가 난다. 쌍따옴표는 String을 뜻하기 때문이다.

Q. char는 총 2Byte 인데, 한 글자만 입력할 수 있는 이유는 뭘까?

Java는 2Byte를 사용하는 유니코드 문자 체계를 사용하기 때문이다. C 언어같은 경우엔 ASCII 코드를 사용하기 때문에 char가 1Byte이다.

Q. boolean 값에 0과 1을 넣을 수 있을까?

if문에서 논리적으로 0은 false로, 1은 true로 사용되지만, boolean과 int는 다른 형이기 때문에 숫자를 넣어줄 수는 없다. (자동 형 변환은 안된다)

Q. 왜 변수에 초기값을 선언해주는 게 좋을까?

C언어에서는 초기화하지 않으면 쓰레기 값이 들어가므로 반드시 초기화해주는 것이 좋았다. 그렇다면 기본값을 넣어주는 자바에서는 왜 초기값을 선언해주는게 좋을까?

지역 변수의 경우에는 자동으로 기본값을 넣어주지 않으므로, 미연의 사고를 방지하기 위함인 것 같다.

그리고 개인적인 생각이지만, 초기값을 선언해주는게 프로그램을 이해하는데 더 편리할 거 같다. ‘이 변수는 기본값이 이거구나’ 하는 게 가시적으로 보이니까.

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글