카테고리 없음

[내일배움캠프] 12월 2주차 WIL 회고록

tft4rollz 2022. 12. 18. 14:31

알고리즘

월요일 : OX 퀴즈

문제 설명 및 제한사항 , 입출력 예, 입출력 예 설명

풀이 :.split 을 이용해 문자열을 " "  로 잘랐다 .자르면 "X" , "+", "Y" , "=", "Z" 이런 식으로 잘라진다.

그 후에 변수 num1 , num2, num3 에 Integer.parseInt(String 타입의 숫자를 int 타입으로 변환해 주는 함수) 를 이용해

stringArr[0] , [2] , [4] 를 담았다. 

stringArr[0] = X 이고, stringArr[2] = Y 이고, stringArr[4] = Z 이다.

stringArr[0] = X , stringArr[1] = + , stringArr[2] = Y,  stringArr[3] 은 = , stringArr[4] = Z 이다.

그 후에 if문을 이용해 num1과 num2를 더한 값이나 뺀 값이 num3과 같다면 answer[i]에 "O" 나 "X"를 저장해서 리턴시켰다.

    class Solution {
        public String[] solution(String[] quiz) {
            String[] answer = new String[quiz.length];
            for (int i = 0; i < quiz.length; i++ ){
                String[] stringArr = quiz[i].split(" ");
                int num1 = Integer.parseInt(stringArr[0]);
                int num2= Integer.parseInt(stringArr[2]);
                int num3 = Integer.parseInt(stringArr[4]);

                if (stringArr[1].equals("+")) {
                    if(num1 + num2 == num3) {
                        answer[i] = "O";
                    } else {answer[i] = "X"; }
                }

                if (stringArr[1].equals("-")){
                    if(num1 - num2 == num3) {
                        answer[i] = "O";
                    } else {
                        answer[i] = "X";
                    }
                }

            }
            return answer;
        }
    }

수요일 : 평행 

문제 설명, 제한사항, 입출력 예 , 입출력 예 설명

풀이: 먼저 기울기를 구해야 해서 int[] dot1, int[] dot2를 변수로 받는 double 형 findSlope를 선언했다.

double로 받는 이유는 원래 기울기를 구하려면 분수 형태로 구해야 하기 때문이다. 기울기를 구하는 공식: (y2 - y1) / (x2 - x1) 

그래서 dot2의 첫번째 값과 dot1의 첫번째 값을 빼고 dot2의 0번째 값과 dot1의 0번째 값을 뺀 후 나눈 값을 (double)형으로 리턴시켰다

그 후 if문을 써서 findSolpe의 dots 0번째와 1번째 값이 findSlope의 2번째, 3번째 값과 동일하면 1을 리턴시켰다.

나머지도 마찬가지로 dots의 0번째 값, 두번째값과 첫번째 값, 세번째 값이 같으면 1을 리턴 시켰고

dots의 0번째 값, 세번째 값과 첫번째 값, 두번째 값이 같으면 1을 리턴시켰다. 그 후 answer를 리턴시켰다.

class Solution {

        // 기울기 구하는 법 (y2 - y1) / (x2 - x1) 원래 분수 나누는거라서 double로 선언
        public double findSlope(int[] dot1, int[] dot2) {
            return (double) (dot2[1] - dot1[1]) / (dot2[0] - dot1[0]);
        }

        public int solution(int[][] dots) {
            int answer = 0;

            // (0,1) == (2,3)
            if (findSlope(dots[0], dots[1]) == findSlope(dots[2], dots[3])) {
                return 1;
            }
            // (0,2) == (1,3)
            if (findSlope(dots[0], dots[2]) == findSlope(dots[1], dots[3])) {
                return 1;
            }
            // (0,3) == (1,2)
            if (findSlope(dots[0], dots[3]) == findSlope(dots[1],dots[2])) {
                return 1;
            }


            return answer;

        }
    }

목요일 : 문자열 내 마음대로 정렬하기

문제 설명, 제한 조건, 입출력 예 , 입출력 예 설명

풀이 :

1. 반환할 배열 answer의 길이는 strings의 배열과 같으므로 strings.length로 지정한다.

2. n번째 문자를 기존 문자열에 붙여 넣을 새로운 문자열을 넣을 ArrayList를 생성한다.

3. String의 길이만큼 반복문을 사용해 새로운 문자열을 넣어준다. (arrayList.add(strings[i].charAt(n) + strings[i])

4. strings가 ["sun","bed","car] 이고  strings[i] 가 0이라고 치고, charAt(n)이 1이라고 치면 sun.charAt(1) = u 가 되고

     string[i] 는 sun 이니까 u + sun = usun으로 변환 후 ArrayList에 add 된다.

5. Collections.sort 함수로 정렬한다.

6. arrayList.size()만큼 반복문을 사용한다.

7. answer[i] 번째에 arrayList.get(i)를 substring(1)을 사용한 후 값을 넣는다.

    i를 0이라고 치면, arrayList.get(0)은 acar 이고, substring(1)로 1번째 문자열부터 출력한다.

    0번째 문자열이 잘려서 나온다. ex ) acar = car , ebed = bed, usun = sun

8. answer를 return 시킨다.

class Solution {
        public String[] solution(String[] strings, int n) {

            // 반환할 배열 answer의 길이는 strings의 배열과 같으므로 strings.length로 지정한다.
            String[] answer = new String[strings.length];

            // n번째 문자를 기존 문자열에 붙여 넣을 새로운 문자열을 넣을 ArrayList를 생성한다,
            ArrayList<String> arrayList = new ArrayList<>();

            //String의 길이만큼 반복문을 사용해 새로운 문자열을 넣어준다. (arrayList.add(strings[i].charAt(n) + strings[i])
            //strings가 ["sun","bed","car] 이고  strings[i] 가 0이라고 치고, charAt(n)이 1이라고 치면
            // sun.charAt(1) = u 가 되고 string[i] 는 sun 이니까 u + sun = usun으로 변환 후 ArrayList에 add 된다.
            for(int i = 0 ; i < strings.length; i ++) {
                arrayList.add(strings[i].charAt(n) + strings[i]);
            }

            // Collections.sort 함수로 정렬한다.
            Collections.sort(arrayList);

            // arrayList.size()만큼 반복문을 사용한다.
            // answer[i] 번째에 arrayList.get(i)를 substring(1)을 사용한 후 추가한다.
            // i를 0이라고 치면, arrayList.get(0)은 acar 이고, substring(1)로 1번째 문자열부터 출력한다.
            // 0번째 문자열이 잘려서 나온다. ex ) acar = car , ebed = bed, usun = sun
            for (int  i = 0 ; i < arrayList.size() ; i ++)
                answer[i] = arrayList.get(i).substring(1);
            return answer;
        }
    }

월요일에 공부한 내용

 

영속성 컨텍스트 : 영속성 컨텍스트란 엔티티를 영구 저장하는 환경이라는 뜻이다. 어플리케이션이 데이터베이스에서 꺼내온 데이터

객체를 보관하는 역할을 한다. 영속성 컨텍스트는 엔티티 매니저를 통해 엔티티를 조회하거나 저장할때 엔티티를 보관하고 관리한다.

 

JPA 엔티티의 상태

  • 비영속(New) : 영속성 컨텍스트와 관계가 없는 새로운 상태, 해당 객체의 데이터가 변경되어도 실제 DB 데이터에는 관계가 없다.       
  • 영속(Managed) : 엔티티 매니저를 통해 엔티티가 영속성 컨텍스트에 저장되어 관리되고 있는 상태이다. 이와 같은 경우 데이터의 생성, 변경등을 JPA 추적하면서 필요하면 DB에 반영한다.
  • 준영속(Detached) : 영속성 컨텍스트에서 관리되다가 분리된 상태
  • 삭제(Removed) : 영속성 컨텍스트에서 삭제된 상태
// 엔티티를 생성 (비영속 상태)
Member minsook = new Member();
member.setId("minsook");
member.serUsername("민숙");
// 엔티티 매니저를 통해 영속성 컨텍스트에 엔티티를 저장 ( 영속 상태 )
em.persist(minsook);
// 엔티티를 영속성 컨텍스트에서 분리 ( 준영속 상태 )
em.detach(minsook);
// 영속성 컨텍스트를 비우기
em.clear();
// 영속성 컨텍스트를 종료
em.close();
// 삭제
em.remove(minsook)

영속성 컨텍스트의 특징

  • 1차 캐시라는 것을 가지고 있다.
  • "쓰기 지연 SQL 저장소" 가 있다.
  • DirtyChecking을 통해 데이터의 변경을 감지해서 자동으로 수정해준다.
  • 데이터의 어플리케이션 단의 동일성을 보장해준다.

@Entity 관련

  1. 기본 생성자는 필수이다. 
  2. final 클래스 , enum, interface 등에는 사용할 수 없다.
  3. 저장할 필드라면 final을 사용하면 안된다.

@Table 관련

  1. 엔티티와 매핑할 테이블의 이름이다. 생략하는 경우 매핑한 엔티티 이름을 테이블 이름으로 사용

@Column 관련

  1. 객체 필드를 테이블 컬럼에 매핑하는데 사용한다.
  2. 생략이 가능하다.
  3. 속성들은 자주 쓸 일이 없고, 특정 속성은 effect가 있으니 이름을 지정할 때 아니고는 보통 생략한다.

@Enumerated 관련

  1. Java Enum을 테이블에서 사용한다.
  2. 속성으로는 Ordinal, String 이 있는데, String 인 경우 해당 문자열 그대로 저장해서 비용은 많이 들지만, 나중에 Enum이 변경되어도 위험할 일이 없기 때문에 일반적으로는 String 을 사용한다.

프록시 : Proxy란 사전적으로는 대리인이라는 뜻을 가지고 있다. Java에서 프록시는 RealSubject는 자신의 기능에만 집중을 하고 그 이외 부가 기능을 제공하거나 접근을 제어하는 역할을 Proxy 객체에게 위임한다.

 

즉시 로딩 : 엔티티를 조회할 때 연관된 엔티티도 함께 조회한다. (연관된 엔티티를 조인해서 다 긁어온다.)

// 즉시 로딩 어노테이션
@ManyToOne(fetch = FetchType.EAGER)

지연 로딩 : 연관된 엔티티를 실제 사용할 때 조회한다. ( 실제로 가짜 객체를 이용하면, 그때 별도의 쿼리가 나간다.)

// 지연 로딩 어노테이션
@ManyToOne(fetch = FetchType.LAZY)

즉시로딩은 처음부터 모든 테이블의 조인을 걸어버리고 별도로 쿼리가 나가는 경우가 생기기에, 연관관계가 많고 복잡할수록 비용이 

기하급수적으로 늘어나기에, 정확하게 이해하고 필요한 상황이 아니라면, 가급적 모두 지연로딩을 걸어두는게 일반적이다.

(쓸지 안쓸지 모르는데 비용은 가장 많이 드는 작업일 수도 있기 때문에)


영속성 전이 : 특정 엔티티를 역송 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을때 사용되는 기능 , JPA는 cascade 옵션으로 영속성 전이를 제공한다. 예를 들면 유저 테이블과 메모 테이블이 있는데 영속화한 유저객체가 있으면 메모 테이블도 같이 관리되는 것을 영속성 전이라고 한다.

// 예시
@OneToMany(mappedBy = "person" , cascade = CascadeType.ALL)
private List<Address> address;

화요일에 공부한 내용

 

인증과 인가

인증: 인증(Authentication)은 해당 유저가 실제 유저인지 인증하는 개념이다. 스마트폰에 지문인식, 이용하는 사이트에 로그인 등과 같이, 실제 그 유저가 맞는지를 확인하는 절차이다.

인가: 인가(Authorization)는 해당 유저가 특정 리소스에 접근이 가능한지 허가를 확인하는 개념이다. 예를 들어 관리자 페이지- 관리자 권한 같은 것이다.

 

인증의 방식 

웹 어플리케이션의 인증

  • 일반적으로 서버 - 클라이언트 구조로 되어있고, 실제로 이 두가지 요소는 아주 멀리 떨어져있다.
  • 그리고 HTTP 라는 프로토콜을 이용하여 통신하는데, 그 통신은 비연결성(Connectionless) 무상태(Stateless)로 이루어진다.

비연결성(Connectionless)

- HTTP는 기본이 연결을 유지하지 않는 모델

- 일반적으로 초 단위의 이하의 빠른 속도로 응답

- 1시간동안 수천명이 서비스를 사용해도 실제 서버에서 동시에 처리하는 요청은 수십개 이하로 매우 작음

  >> 예) 웹 브라우저에서 계속 연속해서 검색 버튼을 누르지는 않는다.

- 서버 자원을 매우 효율적으로 사용할 수 있음.

 

무상태(Stateless)

- 서버가 클라이언트의 상태를 저장하지 않는 것

 

쿠키 - 세션 내용과 JWT 기반 인증은 유튜브를 보면서 공부했다.

 

쿠키 - 세션 방식

더보기
1. 쿠키
- 쿠키는 클라이언트 측에 저장된 키와 함께 들어있는 작은 파일입니다.
- 클라이언트의 상태정보를 로컬에 저장합니다.
- 그래서, 장바구니 기능, '오늘 더이상 창을 보지않음 창 팝업' 등에 사용됩니다.
1) 클라이언트가 페이지를 요청하면
2) 서버에서 쿠키를 생성해, http 헤더에 쿠키를 포함시켜 응답합니다
3) 클라이언트는 이 쿠키를 로컬 pc에서 갖고 있다가, 다시 서버에 요청할 때 HTTP 헤더에 이 쿠키를 함께 전송합니다.
4) 서버에서는 이 쿠키를 읽어 이전 상태정보를 변경할 필요가 있으면 쿠키를 업데이트해 HTTP 헤더에 변경된 쿠키를 넣어 반환합니다.
 
2. 세션 - 세션은 사용자 정보를 서버측에서 관리합니다.
- 즉, 보안성이 좋아 로그인같은 보안중요작업에 사용됩니다.
- 서버는 클라이언트 구분을 위해 세션 ID라는 것을 부여합니다. 웹 브라우저가 서버에 접속하고, 브라우저를 종료할 때 까지 인증상태를 유지합니다.
1) 클라이언트가 페이지를 요청하면
2) 서버는 접근한 클라이언트의 request-header필드의 쿠키를 확인해 클라이언트가 세션id를 보냈는지 확인합니다.
3) 만약 세션id가 존재하지 않으면 서버는 세션id를 생성해 클라이언트에 함께 돌려줍니다. 이 때, 서버측에서는 세션 저장소에 해당 id를 저장해, 차후 구분할 수 있도록 합니다.
4) 클라이언트는 세션id를 받으면, 이걸 쿠키를 사용해 저장하고 가지고 있습니다.
5) 클라이언트는 이제 같은 요청으로 서버에 접속할 때, HTTP요청에 이 세션ID를 같이 서버에 전달해 요청합니다.
6) 서버는 세션 ID를 전달 받고, 세션저장소에서 해당 세션 ID값을 찾아 클라이언트 정보를 가져와서 클라이언트를 구분합니다. 그리고 요구에 맞는 서비스를 제공합니다.
 
3. 차이
- 데이터 저장위치는 쿠키는 브라우저, 세션은 서버입니다.
- 보안성은 쿠키가 저장위치가 클라이언트라는 점에서 스니핑을 당할 우려가 있기 때문에 세션측이 좀 더 좋습니다.
- LifeCycle은 쿠키는 브라우저가 종료되어도 쿠키에 저장된 만료일(저장기간) 값이 남아있으면 존재하고, 세션은 브라우저 종료 시, 만료기한에 상관없이 종료됩니다.
- 속도측은 세션이 서버에 정보가 있기 때문에, 쿠키측이 더 빠릅니다. 하지만, 사용자가 많아질수록 서버 메모리를 많이 차지합니다.
 
4. 추가!) 브라우저 저장소(웹 스토리지) - 서버전송 없이 클라이언트에 데이터를 저장할 수 있도록 HTML5부터 추가된 저장소로, 오직 문자형 데이터 타입만 지원합니다.
- 쿠키는 서버가 클라이언트에게 전송하는 데이터 파일로, [이름/값/만료일자] 등 데이터를 포함합니다. 모든 브라우저에서 지원되나, 매번 서버에 전송되고, 저장용량이 작으며, 보안에 취약합니다.
- 웹 스토리지는 쿠키의 단점을 보완하려 등장한 개념입니다.
- 웹 스토리지는 클라이언트에서 저장만 할 뿐, 서버로 전송하지 않기 때문에 전송에 따른 위험이 없습니다.
- 웹 스토리지는 지속성에 따라 두 가지로 나뉘는데, 로컬 스토리지(Local Storage)는사용자가 데이터를 지우지 않는 이상, 브라우저나 OS를 종료해도 계속 브라우저에 남아있습니다. 즉, 영구적 저장 특성을 가집니다.
- 하지만, 세션 스토리지는 데이터가 브라우저 탭에 종속되기 때문에, 윈도우나 브라우저 탭을 닫을 경우 제거됩니다.
 
5. 캐시
- 리소스 파일들의 임시저장소
- 같은 웹페이지에 접속할 때, 이전에 사용되었던 데이터는 다시 사용될 가능성이 높다라는 생각을 기초로 해서 다시 사용될 확률이 있는 데이터들을 빠르게 접근 가능한 저장소에 저장하는 것이에요!
- 보통 이러한 리소스의 대상은 이미지, 비디오 오디오, CSS/JS 등이에요 이런건 데이터 사용량도 좀 들고, 시간도 걸리니까 매번 서버에서 불러오면 시간이 너무 오래 걸리는 걸 대상으로 해요. 또, 변경사항이 크지 않아요!

출처: https://www.youtube.com/watch?v=OpoVuwxGRDI 

JWT 기반 인증

JWT : JWT (Json Web Token) 이란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token 이다.

 

관련 영상

https://www.youtube.com/watch?v=1QiOXWEbqYQ 

 


수요일에 공부한 내용

 

8시 튜터님 강의 ( 좋은 개발자로 되기 위한 법 )

  • (실력은 기본이지만) 실력이 모든 것을 대변해주지 않는다는 것을 알기
  • (실력이 약하다면) 추가로 어필할 수단이 있는지 스스로 알아보기
  • "No man Left Behind"
  1. 궁금한 부분은 정확하게 정리해본 이후 말해보기
  2. 상대방의 시간은 내 시간만큼 귀하다.
  3. 무작정 에러메세지 복붙보다는 메세지를 읽고 고민 (고민의 흔적을 글로 남겨볼 것)
  4. 알고 있습니다 보다는 "해보았습니다."
  5. 불편한 것들을 '컴퓨터가 해줄 수 있을까?" 고민 / 실행
  6. 분위기 메이커가 있으면 / 된다면 좋다. 실제로 팀 분위기가 좋은 팀이 결과물이 좋은 경우가 다수이다.
  7. 누구와도 잘 어울릴 수 있는 인상이면 좋다.
  8. 스몰토킹에서 시작 (날씨, 출퇴근길 점심식사) , 나와 상대방에 관심사를 엮어보기, 반문보다는 정확한 끝맺음
  9. 문제에 있어 '도전' 해내고 실제로 '구현' 해내며, '소통'도 잘하는 사람이 롱런하는 시대
  10. 신입에게 있어 '소통' 이 최우선, 소통만 잘해도 실력은 순차적으로 따라오게 되어있다.
  11. 당장 오늘부터 실행하면 대접받는 개발자로 성장한다.

내 생각을 온전히 담아야하며 ( 생각의 공감각화 )

내 화법에 상대방이 당황하지 않아야 하며

상대방 답변이 의도와 다르더라도 우선 수용하고 생각하자.

오고가는 대화속에서 결론은 나오게 되어있다.


목요일 , 금요일 - 개인 과제 만들기

 

과제를 하면서 더 공부를 해야겠다는 생각이 많이 들었다.

다음주에 리뷰를 보고 리뷰를 보고 배운 것을 바탕으로 이번 숙련 기능들을 전부 구현해 본 다음 다른 강의를 들어야겠다.

api 명세서 만들기가 생각보다 쉽지 않았다.. Gitbook으로 만들었는데 대충 다 만들고 Github으로 연동했더니

만들어 둔 내용이 다 날아가서 다시 만들고 깃헙으로 보냈더니 이상하게 나오고.. 사용법이 미숙해서 그대로 놔뒀다.

다음주도 열심히 공부해야겠다.