5월 09, 2022

[Java] 환경변수 설정 및 java의 프로그램 실행 순서

 javac.exe : 컴파일러

java.exe : JVM구동 명령

자바 컴파일러를 다른 디렉토리에서도 접근할 수 있게 환경변수(path)에 bin 경로를 등록해주려 합니다.

https://nobacking.tistory.com/76 을 그대로 따라해보았으나

source로 적용해주려 하면 


해당 오류가 뜨고 echo $JAVA_HOME으로 확인해보아도 아무것도 뜨지 않습니다.


echo $PATH로 확인했을때 


Javapath는 뜨긴하는데요..


https://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_$JAVA_HOME_%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98_%EC%84%A4%EC%A0%95

해당 링크를 참고하여



로 환경변수를 등록해주고 


echo $JAVA_HOME으로 확인해줍니다.


5월 09, 2022

WSL2에 Java를 설치하고 Eclipse를 통해 프로젝트 생성까지

WSL2에 Eclispe 개발환경을 구축하는 과정을 기록합니다.

이 글은 과도한 CTRL+C,V 및 잘못된 정보를 포함하고 있을 가능성이 매우 높음을 알립니다 ㅎ..


1. JAVA설치 

sudo apt update

sudo apt install openjdk-8-jdk

로 자바를 wsl에 설치해줍니다

java -version

javac --version

으로 버전을 확인해줍니다

 

2. Eclipse IDE와 WSL연동

우선, WSL의 GUI프로그램이 화면에 그래픽 창을 띄울 수 있게 하기 위해 vcxsrv를 설치합니다.

https://sourceforge.net/projects/vcxsrv/

에서 다운로드를 진행해줍니다.


다운로드 시 체크해야 할 사항은

https://hbase.tistory.com/303 를 참고하였습니다.


다음으로 WSL에게 디스플레이 정보를 알려줘야 합니다.

위의 링크를 따라했으나, 

export DISPLAY=($cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'):0

zsh: parse error near `|'

에러가 발생합니다.

https://psychoria.tistory.com/739 다른 링크를 참조하여 디스플레이 설정을 진행했습니다.


export DISPLAY="`grep nameserver /etc/resolv.conf | sed 's/nameserver //'`:0”

export LIBGL_ALWAYS_INDIRECT=1

해당 명령어를 실행하고, 이를 ~/.bashrc의 최하단에 vim을 통해 입력해두고 저장해줍니다.


이후 https://www.eclipse.org/downloads/packages/ 에서 이클립스 리눅스 버전을 다운로드 합니다.


mnt 디렉토리 하에 있는 해당 파일을 cp명령어를 통해 home으로 옮기고, 

tar -xvf eclipse-jee-2022-03-R-linux-gtk-x86_64.tar.gz

로 압축을 해제합니다.


그리고 

cd eclipse

./eclipse

로 실행을 해주려는데...!

org.eclipse.m2e.logback.configuration: Activated before the state location was initialized. Retry after the state location is initialized.

SWT OS.java Error: Failed to load swt-pi3, loading swt-pi4 as fallback.

Eclipse:

An error has occurred. See the log file

에러가 발생합니다.


https://stackoverflow.com/questions/10165693/eclipse-cannot-load-swt-libraries

해당 스택오버플로우 글을 통해 에러를 해결했습니다.



저는 /usr/lib/jni 디렉토리 자체가 없어서 문제가 발생한 듯합니다.

위의 명령어에서 gtk-3 이 아니라 gtk-4로 바꿔서 명령어를 입력해줍니다.

ln -s /usr/lib/jni/libswt-* ~/.swt/lib/linux/x86_64/

이후 해당 명령어를 실행해줍니다.


이제 ./eclipse로 실행해봅니다.


잘 실행되는 것 같죠....?

pjtTest라는 프로젝트를 만들어보았습니다.


src파일은 실제로 내가 작성한 코드들이 저장된 디렉토리이고,
bin파일은 바이너리, 즉 컴파일 한 이후 컴퓨터가 이해할 수 있는 형식으로 변환된 파일이 담긴 디렉토리 입니다.

패키지 익스플로러에서 
src파일을 우클릭한 이후, New를 클릭하여 새로운 자바 클래스를 만들어줍니다.
자바 프로그램을 구성하는 하나하나의 파일들을 클래스라고 부릅니다.
클래스를 생성했습니다.

main을 입력한 이후, 컨트롤+스페이스로 메인 메소드를 호출합니다

이 메인 메소드는 프로그램을 실행할때, 컴퓨터가 제일 처음 찾아서 실행하는 메소드입니다.
즉, 프로그램의 출발점을 지정해주는 메소드입니다.



귀엽게 Hello World 를 찍어봅니다.
System.out.println(); 은 앞서와 마찬가지로 sysout만 입력하고 컨트롤 + 스페이스 입력하면 저절로 완성됩니다.

Ctrl+S로 저장(저장할때 컴파일까지 됩니다. 
저장 이후 bin파일에 들어가보면 pjtTest안에 MainClass.class파일이 형성된 것을 볼 수 있습니다.

프로젝트를 마우스 우클릭하고, Run as java application을 통해 Hello World를 실행가능합니다.

이렇게 Hello World까지 찍어보았습니다! 







4월 21, 2022

에러 기록) WSL 늦게 켜지는 문제/ Code .

 가상 머신 또는 컨테이너에서 응답을 받지 못했기 때문에 작업 시간이 초과되었습니다.


[코드 4294967295 (0xffffffff)로 프로세스 종료됨]


Powershell에서 WSL을 실행하면 한~참 있다가 이 에러가 뜨고, 그 후에 WSL이 켜집니다.


https://gyunseo.com/devlog/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%B0%BE%EC%9D%84-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%BD%94%EB%93%9C-4294967295-0xffffffff%EB%A1%9C-%ED%94%84%EB%A1%9C/

해당 링크를 따라하니 이제 바로바로 켜지기는 하는데 이제는 code . 으로 vscode 여는 명령이 작동하지 않습니다....


https://www.reddit.com/r/vscode/comments/ilwkhi/cant_launch_vs_code_from_wsl2/

껐다키니깐 되네요 허헛... 


도커와 WSL 관련해서 자잘한 문제가 꾸준히 생기는데, 추후에 정리해서 한번에 포스팅하겠습니다.

4월 20, 2022

TIL)HTTP - Cache와 Cookie

 

Cache

HTTP캐시는 서버의 지연을 줄이기 위하여 주어진 웹 페이지 요소를 임시로 저장하는 기술입니다. 캐시 시스템은 이를 통과하는 문서들의 사본을 저장하며, 특히 이후에 필요할 것 같은 요소들을 저장합니다.


Cookie란

브라우저에 저장돼 있는 "{name} = {value}" pair입니다. 

브라우저는 Response의 Set-Cookie 헤더를 통해 Server에게 전달받은 값을 쿠키를 세팅할 수 있습니다.

이후 브라우저는 Requset의 Cookie 헤더를 통해 이 쿠키를 서버에게 보낼 수 있습니다




언뜻 보기에는 쿠키와 캐시 모두 정보를 저장하는 방법으로 보입니다. 


그러나 둘은 용도 및 성격의 차이점이 있습니다.

쿠키는 사용자의 PC를 인증하고, 커스터마이징 된 웹사이트를 구현하기 위해 존재합니다.

쿠키는 인증 정보 및 사용자의 활동과 성향을 트랙하기 위한 목적으로 고안됐습니다.

사용자가 웹사이트를 방문할 때, login정보와 개인정보 등을 쿠키에 담아서 전송합니다. 

웹사이트를 사용하면서 매번 로그인을 할 필요가 없는 이유는, 브라우저에 있는 쿠키를 이용하여 인증 절차를 대신하기 때문입니다. (매 request마다 쿠키가 서버로 보내집니다)

또한 개인정보의 경우, 유저의 선호사항 등이 담깁니다.

쿠키는 브라우저가 닫히면서 같이 삭제되거나, 일정 시간이 지난 이후 자동으로 expired(만료)됩니다

쿠키는 누구나 삭제 혹은 block할 수 있기에, 쿠키에 의존하는 웹 어플리케이션은 쿠키의 삭제 혹은 블록 이슈에 대해 취약합니다.


반대로 캐시는, 필요한 웹 페이지 리소스를  저장하는 방식입니다. 사실 메모리에 저장돼 있는 캐시 파일은 일종의 쿠키처럼 동작합니다. 

그러나, 쿠키와 다르게 캐시는 웹 페이지가 렌더링을 할 때, 이를 좀 더 빠르게 할 수 있게 도와주는 역할을 합니다. 

쿠키와 다르게 캐시는 유저가 수동으로 삭제해주기 전까지, 메모리에 남아있습니다. 




쿠키와 캐시의 차이점을 기록한 표입니다. 포인트들을 빨간색으로 체크해두었습니다.


참고

https://developer.mozilla.org/ko/docs/Web/HTTP/Caching

https://medium.com/@maheshlsingh8412/cookie-session-story-of-a-stateless-http-3cd09cc01541

https://www.quora.com/What-is-the-difference-between-cookies-and-cache

4월 19, 2022

TIL) HTTP 헤더 : Content-Type

 

HTTP 콘텐트 타입은 리소스의 미디어 타입을 나타내기 위해 존재합니다.

Media Type이란, 파일의 형식을 나타내기 위해 파일과 함께 보내지는 string입니다.

데이터를 받는 서버(request일때), 클라이언트(response일때)는 Content-Type을 보고 데이터의 형식을 파악하고, 이를 어떻게 처리할지 결정하게 됩니다.

예를 들어, 브라우저는 서버로부터의 Response를 보고, 여기의 Content-Type을 통해 컴퓨터에 보여줘야 하는 컨텐트의 타입을 알 수 있습니다. 


이때 브라우저는 MIME sniffing 이라는 작업을 수행하는데요.  

MIME은 "Multipurpose Internet Mail Extensions"의 약자입니다. 원래는 이메일에 있는 non-ASCII Text와 non-text binary를 정의하기 위해 고안됐다고 합니다.

현재, Mime standard에 있는 content-type들은 HTTP 프로토콜에서 request나 response의 컨텐트 타입을 파악하기 위해 쓰입니다.

브라우저는 바로 이 MIME 타입을 Content-Type을 보면서 파악합니다. (Content-Type은 MIME타입의 일부입니다)

개발자들은 Response 내용에 걸맞지 않는 Content-Type을 부여할 수 있습니다, 



사진은 자바스크립트 리소스에 text/plain 의 컨텐트 타입이 잘못 부여된 경우입니다.

브라우저는 이러한 경우에도 웹사이트가 의도대로 작동할 수 있도록 Content-Type이 잘못 표시된 리소스를 분석하여 렌더링 할 수 있습니다.

여기서 MIME Sniffing 이 사용됩니다. Content_Type에 의존하기보다, response의 content에 대해 직접 분석하여서 , 브라우저는 효과적으로 mime type을 Sniffing을 통해 알 수 있습니다. MIME Sniffing의 알고리즘은 브라우저마다 상이합니다.

 

X-Content-Type-Options

보안 이슈를 위하여 , 브라우저가 MIME Sniffing을 하지 않도록 서버의 HTTP Response header에 X-Content-Type-Option을 줄 수 있습니다. 

이 헤더의 유일한 값은 "nosniff"입니다. 

 

문법

type/subtype

type은 카테고리이며, subtype은 개별 혹은 멀티파트 타입입니다.


application/octet-stream

Content-Type에는 수많은 종류가 있습니다. 그 중 주목할만한 application/octet-stream에 대해 얘기해보겠습니다

8 비트(1바이트) 단위의 바이너리 데이터를 의미합니다(...?) 엄밀히 따지면 모든 컴퓨터 상 파일은 binary data이긴 합니다만...

이렇게 두루뭉술하게 표현한 이유는 , 특별히 표현할만한 프로그램이 존재하지 않는 경우에 octet-steam을 사용하기 때문입니다.

보통 브라우저는 해당 타입에 대해 유저에게 실행할지 묻거나, 실행하지 않는다고 합니다.

"Content-Dispostion" 헤더를 "attachment로 줌으로써 해당 데이터를 수신 받은 브라우저가 파일을 저장, 또는 다른 이름으로 저장여부를 설정하게 할 수 있습니다.

뭐라 정의하기 애매한 경우에 해당 Content-Type을 주는 듯 합니다.



참고

https://www.coalfire.com/the-coalfire-blog/mime-sniffing-in-browsers-and-the-security 

https://www.geeksforgeeks.org/http-headers-content-type/

https://pygmalion0220.tistory.com/entry/HTTP-Content-Type

http://www.webmadang.net/community/community.do?action=read&boardid=5001&page=1&seq=3

https://dololak.tistory.com/130

4월 18, 2022

TIL) 구글 코딩 인터뷰 풀이

 https://www.youtube.com/watch?v=XKu_SEDAykw&t=430 

해당 영상을 보고 풀이 과정을 기록한 코드입니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 문제
# collection of numbers
# find matching pair equal to sum(given)
# [1,2,3,9]  sum 8
# [1,2,4,4]  sum 8
 
# 매칭 pair 없는 경우도 있음
# memory에 있고, ordered된 상태(ascending)
# repeating element? : 같은 인덱스에 있는 값 재활용 불가능
# 다른 인덱스에 같은 값은 나올 수 있음
# int, 마이너스도 가능
 
# nested for loop 사용 가능 i Loop과 i+1 Loop
# 그러나 O(n^2) 이기에 time consuming함 
 
# 1이라고 치면, 7을 찾으면 되는데.. sorted 돼있기에 binary search하면 된다
# log algorithm 
# 아직 좀 느림
 
ex = [1,2,3,4,4]
 
def binary_search(array, left, right, ele):
  if right >= left:
    mid = (left+right)//2
    if array[mid] == ele:
      return True
    elif array[mid] > ele:
      return binary_search(array,left,mid-1, ele)
    else:
      return binary_search(array,mid+1, right, ele)
  else:
    return False
    
def slightly_better_pair_sum(array,sum):
  for i in range(len(array)):
    comp=sum-array[i]
    if binary_search(array,i+1,len(array)-1,comp):
      return "yes"
  return "No"
 
# 단방향인 binary search보다 
# 가장 큰 sum은 마지막 두 값일 것임
# 가장 작은 sum은 첫 두 값
# 그러니깐, 첫번째 값보다 작은 것은 없고, 마지막 값보다 큰 것은 없음
# range를 가운데로 줄여가며 linear하게 접근
 
# binary search를 하게된다면, 각 element마다 binary search를 반복해야 하는 반면, 이렇게하면 한번의 흐름으로 끝남
 
# python으로 해보자
def findSumPair(array,sum):
  left = 0
  right = len(array)-1
  while right>left:
    if array[left] + array[right] == sum:
      return "yes"
    elif array[left] + array[right] < sum:
      left += 1
    else:
      right -= 1
  return "No"
 
 
# print(findSumPair([1,2,4,4],8))
# O(n) 의 시간 복잡도 
 
 
# sorted 돼있지 않다면? - error check
# sort 한 이후 해당 코드 반복
 
def SortPairSum(array,sum):
  array.sort()
  left = 0
  right = len(array) -1
  while right>left:
    if array[left] + array[right] == sum:
      return "yes"
    elif array[left] + array[right] < sum:
      left += 1
    else:
      right -= 1
  return "No"
 
# print(findSumPair([4,5,2,3,7],8))
 
# 개선점
# O(nlog n)의 시간복잡도
# O(n) 으로 돌아가기 위하여 
  # array를 가면서 만나는 요소를 딕셔너리에 넣음
  # 현재 요소의 complement(요소와 더해서 sum되는 것)없다는 것은
  # array를 loop하면서 현재 요소의 complement가 딕셔너리에 있는지 확인하고
  # 있으면 yes를 리턴
  # 없으면 no를 리턴하고 현재 element를 딕셔너리에 더함
 
def smartestPairSum(array,sum):
  dictionary = dict()
  for item in array:
    comp = sum - item
    if not comp in dictionary:
      dictionary[item] = True
    else:
      return "YES"
  return "No"
 
print(smartestPairSum([4,5,2,3,7],8))
# 더해서 sum이 되는
# complement1 , complment2이 있을때,
# 먼저 나온 complement1을 기록해두었다가, 이후에 complemnet2 가 나오면 딕셔너리에서 이를 찾아서 합이 되는 수가 있음을 return 하고 끝냄.
# array개수만큼 operation이 늘어나기에 O(n)임
cs

참조 : https://github.com/VicodinAbuser/ZTM-DS-and-Algo-Python/blob/master/venv/Scripts/How%20to%20solve%20coding%20problems/Google%20Interview%20Question.py 


4월 17, 2022

TIL) HTTP메서드 속성

 

1. 안전

: 계속해서 메서드를 호출해도 리소스를 변경하지 않습니다.

GET은 안전 속성을 가지고 있으나, POST,PUT,PATCH 등은 호출했을 때 리소스의 변경이 일어나기 때문에 안전하지 않습니다. 



2. 멱등 Idempotent  => f(f(x) = f(x)

: 호출의 건수와 상관 없이 호출 결과가 항상 동일합니다.

GET은 서버에서 리소스를 불러오는 메서드이기에 멱등합니다.

DELETE 요청을 여러번 하여도, 삭제된 결과 자체는 똑같기에 DELETE는 멱등합니다.

PUT의 경우, 리소스를 완전히 "덮어쓰는" 메서드이기 때문에 여러번 요청하여도 같은 값으로 덮어쓰기에 멱등합니다. 리소스를 매 요청시마다 갱신하기에 멱등성이 생기는 것입니다.

그러나 POST는 멱등하지 않습니다. 예를 들어, POST를 통해 이미지를 업로드 할때, 여러번 POST하게 되면 중복 업로드가 될 수 있습니다.

더 심각하게는, POST를 통해서 결제를 처리하는 상황을 생각해 볼 수 있습니다. 

- 클라이언트는 POST를 통하여 결제 요청을 보냅니다.

- 서버는 결제 요청을 받고, 결제 로직을 실행합니다. 

이때 결제를 3번 요청하게 된다면, 3번의 중복 결제가 이뤄질 것입니다. 클라이언트 입장에서는 한번의 결제를 원하겠지만, 클라이언트의 의도와 다르게 여러번 결제가 중복해서 일어났습니다. 이처럼 POST는 멱등하지 않습니다


PATCH의 경우도 리소스의 일부를 변경하는 작업이기에, 멱등하지 않습니다.


멱등한 메서드들을 이용하여 자동 복구 메커니즘을 구현할 수 있습니다.

DELETE를 요청했는데, 서버에서 응답이 없다면 클라이언트는 다시금 DELETE를 요청할 수 있습니다. 이는 DELETE가 몇 번 호출하든 같은 결과를 내는 메서드라는 점을 활용하여, 클라이언트에서 임의적으로 재차 요청을 하는 것입니다.

이를 통하여 멱등성을 구분하는 이유를 알 수 있습니다.

서버 입장에서, 요청 실패 이후 재전송된 요청을 처리해도 괜찮은가? 에 대한 가이드를 제공해 주는 것이 멱등성입니다.



3. 캐시 가능

캐시 가능이라 함은 , 요청한 응답의 리소스를 향후 재사용을 위해 저장할 수 있는 속성을 의미합니다.

웹 캐시는 중간에 요청을 가로채, 서버로부터 리소스를 직접 다운로드 하는 대신, 리소스의 복사본을 반환합니다.

 응답 결과 리소스를 캐시해서 사용해도 괜찮을까요? 

이론적으로 GET,POST,PATCH 메소드는 캐시가 가능하다고 하지만, 실제로는 GET정도만 캐시를 사용할 수 있습니다. 

웹 캐시는 리소스를 보여주는데 필요한 시간을 줄여서, 웹 사이트를 더 빠르게 만들 수 있는 방법입니다.

캐시에는 두가지 종류가 있습니다.

1. 사설(Private)

2. 공유(Shared)

Shared cache는 한 명 이상의 사용자가 재사용 할 수 있도록 응답을 저장한 캐시인 반면, 

Private cache는 한 명의 사용자만  사용하는 캐시입니다.

대표적인 사설캐시로는 "브라우저 캐시"가 있습니다. 사용자가 http요청 이후 다운로드한 문서들을 저장하고 있다가, 앞뒤로 움직이기, 저장 등을 수행할 때 추가적인 서버 요청 없이 캐시를 활용합니다.

프록시캐시는 대표적인 공유 캐시입니다. 회사 혹은 ISP(Internet Service Provider)는 여러 사용자들을 위해 로컬 네트워크의 일부로 웹 프록시를 설치할 수 있습니다. 이를 통해 공통적으로 조회가 많이 되는 리소스들은 재사용되어 성능을 향상할 수 있습니다.