2021-07-31

0731 일대다 관계 조회 + 페이징 최적화하기

 순서!

1. 일대일관계까지는 일단 limit랑 offset지정해서, 페이징한다. (lazy와 with fetch join은 당연!)

2. 일대다관계의 쿼리 -> lazy초기화할때 땡겨올건데 - 이때 설정하는 옵션!!

hibernate.default_batch_fetch_size !!

이것을 이용하면 - in 쿼리 안에 날라가는 파라메터의 갯수를 조정할 수 있다.

일반적으로는 100~1000개로 잡는다고 한다.

이 옵션을 설정한 후 쿼리를 날리면 - 

1) 일단 일대일관계 쿼리 날리고 ->

2) 일대 다 관계 쿼리를 IN( ?,?,?...)로 날리고 ->

3) 일대 다 관계로 끌어온 값 안에 또 다른 연관관계 있으면 그것도 IN절로 각각 날려준다!!


3. 이렇게 함으로써 - 만약에 batch size설정이 없었다면

1대일쿼리 조회 결과 2개-> 2개 안에 orderitems 2개 -> 각각의 orderitem이 일대일관계로 item 정보 1개 =

2 * 2* 2 해서 날라가는 쿼리를

1 + 1+ 1로 단번에 줄일 수 있다!!

4. distinct fetch join 은 페이징이 안된다는 한계가 있는데 - 이것을 이러한 방식으로 극복할 수 있는 것이다!


5. distinct fetch join : 일대다관계의 쿼리 끌어올때 - 데이터 개수가 뻥튀기 된다.

이것을 JPA가 묶어주는 역할을 한다 ( 단, 쿼리결과는 그냥 평범한 SQL이고. 이건 어쩔수없다. JPA가 메모리상에서 distinct하게 처리한다)

2021-07-30

0730 api 조회 쿼리 성능 최적화하기 & 그외 jpa배운것들 정리

 <성능최적화 순서>

1. DTO클래스를 만든다(필수!!!! entity 와 api 스펙을 분리하여 유연한 설계를 하기위함!)

2. fetch join을 이용한다 

3. 필요하다면 dto직접반환쿼리를 짜본다 (단, 이 경우 - 따로 Repository를 작성하길 권장함. 프레젠테이션레이어의 로직이 들어가기 때문에)

-> 이 방법 - 과연 어느정도까지 성능최적화가 되는가?? 에 대해서는 테스트해보아야 한다. 컬럼 몇개 select에서 뺀다고 그렇게까지 급격한 성능최적화가 되지는 않음. 결국엔 조인을 하는 거 자체에서 성능이~~~!! 


<join fetch와 join차이>

1. join fetch : 순수한 엔티티 그대로 가져온다. 

2. join : 필요한 특정 컬럼만 뽑을 때 사용한다. 


<스프링 data JPA의 @Modifying 어노테이션?>

엔티티매니저가 쿼리를 땡겨올때 select해서 결과값 가져오는 게 있고. update나 delete처럼 단순히 실행한 결과의 갯수를 가져오는 것이 있다( 결국엔 executeQuery랑 executeUpdate 인 것) - 이에 따라 . @Modifying 어노테이션을 붙여서 - 이것은 조회가 아니라 업데이트용입니다. 라고 명시해주는 것이다.


<@Transactional 어노테이션>

나는 스프링 data JPA를 사용하면서 이 어노테이션을 사용한 적이 손에 꼽는다 ( 여러 트랜잭션을 하나로 묶어야 하는 상황제외) - 왜 였냐면!! 알고보니 이미 JpaRepository구현체가 @Transactional어노테이션을 전부 걸어주었었던 것이다!!! 

참고로 - 기본값은 @Transactional(readOnly = True) 로 되어있고. save같이 영속성컨텍스트랑 비교해야하는 경우에는 다시 @Transactional 덮어쓰기 해두었더라.

readOnly = True일 경우, 영속성컨텍스트에 초기화한 객체 넣어두고 비교하는 과정을 거치지 않기 때문에 약간의 성능최적화가 있다고 한다. 


<JPA에서 상속관계를 풀어내는 법>

1. 일반상속 : 

1) 테이블 하나에 전체 컬럼 때려박기(Single table전략)

2) 각각의 테이블로 만들고 - join해서 가져오는 방식 (Joined 전략) 

이때에는 abstract 클래스로 부모 클래스 만들고 - extends해서 하위클래스들 각각 만들고. 

@Inheritance관련 어노테이션을 활용하면 된다.

DTYPE이라는 컬럼이 자동적으로 추가된다. 옵션으로 컬럼명 바꾸거나 DTYPE안에 들어가는 변수 명 바꿀 수 있음. 

https://ict-nroo.tistory.com/128


2. 공통 컬럼 상속 :

이 경우에는. 상속 이라는 특성을 이용하기는 하지만 - 도메인 내용과는 관계 없고. 그냥 중복코드를 제거하는 의미에서의 상속. 

이를 테면 createdDate , updateDate같은 컬럼은 대개 모든 엔티티에 포함되므로 - 이러한 엔티티를 abstract클래스인 BaseEntity로 만들고, 상속하게 하는 방식. 

@EnableJpaAuditing 이용. 스프링 data JPA를 사용하면 어노테이션만으로 createdDate랑 @updateDate만들수있음. 

@MappedBySuperClass어노테이션 : 나는 실제테이블이 아니얌~~ 만들지 마시오! 라는 뜻. 


2021-07-29

0729 샘플데이터 만들기

 1. 만드는 중에 @Transactional을 안걸었더니.

너 entitymanager 쓰는데 왜 transaction안해?? 하고 스프링이 에러 뿜뿜. 

엔티티매니저와 트랜잭션은 정확히 어떤 관계인가...

스프링 data JPA를 쓰면. 트랜잭션 관리를 알아서 해주던데 ( 뭐 Modifying이런식으로 추상화해놓긴 하지만. ) 

으음~~~뭔가 막 확!! 와닿지가 않네.

기본적으로 entityManager는 작업 단위로 생성되고 close되는 걸로 안다.

트랜잭션 단위일수도 있고.. 여러 트랜잭션을 처리할 수 도 있다.

하나의 비지니스 로직의 완성단위 = entityManager의 단위

라고 이해해도 되는걸까!!?!!


2. @PostConstruct

강의 듣던중에 또 새로운 어노테이션 알게되었다.

스프링 빈이 initialized된 후, 실행되도록 보장해준다

초기화실행하고자 하는 메소드 위에 붙이기만 하면 됨!

스프링 빈이 등록 된 후에 실행되기 때문에 - 주입할 빈이 null이 되는 오류를 방지할 수 있다고 한다. 

( 왠지 이거 - commandliner랑 역할이 좀 비슷한 것 같은?? ) 


3. https://www.baeldung.com/running-setup-logic-on-startup-in-spring

<<오오. 참고가 되었다.

스프링은 많은 초기화메서드를 제공한다!!

commandLinerRunner도, @PostContstructor도 그중하나인 것이다.

근데 @PostConstructor가 커맨드라인러너보다 빨리 실행됨.


4. 실행하는 중에 - @Component어노테이션을 안붙였더니. 스프링에서- 그런 애는 스프링빈에 등록되어있지 않아서 주입할수가 없어! 라는 에러가 났었음. 

궁금해져서 @Component와 @Bean어노테이션의 차이도 찾아봄.

@Component는 개발자가 관리하는 객체, @Bean은 그 외의 외부 객체들 (이를테면 - PasswordEncoder같이. 내가 만들지 않았지만 활용하는 객체들) 에 붙인다고 한다!

2021-07-28

0728 JPA 와 API 2

 1 . api 와 entity spec을 반드시 분리하라

2. 용도에 따라서 다양한 api를 만들게 된다. 그때마다 적절한 api스펙을 만들어야함.

entity를 바로 노출하게 되면 이러한 유연성을 챙길 수 없음!

3. 보안 문제도 있다. @JsonIgnore을 한다고 해도 - 그럼 그때마다 api spec이 달라지면 entity spec도 계속 수정할 것인지?? 말도 안됏.

4. 조회요청에 대한 응답JSON은 - 바로 List를 주지말고, 다른 오브젝트 클래스로 한번 더 감싸자. -> why??

count라던지, size라던지.. entity관련 정보 + a의 정보들을 더 담을 수 있게 된다!! 확장성!! good~~~


-------------------------------------------------------------------------------

converter.HttpMessageNotWritableException: 

No converter found for return value of type


->getter혹은 setter가 없어서 발생하는 오류 이다- 왜??필요하지?

-> json으로 변환하기 위한 과정에서 getter를 이용하기 때문이다. 으음!~~ 뭔가 막 시원하지는 않은데. 여기서 더 파고들면 정말 reflection을 엄청 파야 할것같은..



------------------------------------------------------------------------------------


오 신기하다. 타입 지정 안해도 알아서 쇽 넣어주네?

0728 InvalidDataAccessApiUsageException: id to load is required for loading

 

바부같이... put 으로 update하는 데이터 안에 id를 안넣어서. null 값 오류가 떴었다


로그 찍어보면서 수정 완료!

0728 JPA와 API

 1. Entity 와 API Spec을 분리한다

2. DTO -> Entity로 변경 한후 저장하는 방식 사용하기(반드시!)

3. why??

1) 프레젠테이션 레이어와 DB레이어를 분리하여 결합도를 낮춘다. 

2)Entity Spec이 변경되더라도 API영역에 영향이 없기 때문에 파급효과가 줄어든다.

3) valid로직을 구현할 경우 API영역에서만 처리하면 된다!

4. Entity를 외부에 노출하지 말자!!

5. 둘을 따로따로 분리해서- 자율적이고 독립적으로 협업하도록 만든다!

------------------------------------------------------------

non-static inner classes like this can only by instantiated using default

-> inner클래스를 static클래스로변경해봄. but...

Cannot construct instance of `jpashop.jpabook.api.MemberApiController
$CreateMemberRequest` (although at least one Creator exists): 
cannot deserialize from Object value (no delegate- or property-based Creator);
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException:
-> default 컨스트럭터를 만들어봄



아 이제서야 잘 된다. 이유가 뭐지??
이렇게 안하고 그냥 아예 public한 class로 만들고 - member클래스에 name 컨스트럭터 추가해서 만들었을 땐 문제 없었는데
.
궁금증
1) inner클래스 제약??
2) default constructor왜 필요하지?

----------------------------------------------------------
1번 궁금증 해결!!!

현재 컨트롤러의 컨스트럭터는 RequiredArgs만 있고, 디폴트 컨스트럭터가 없다
따라서 inner클래스를 불러오게된다면

https://stackoverflow.com/questions/12690128/how-to-instantiate-non-static-inner-class-within-a-static-method
<<이렇게!!!
해서 static으로 해야만 inner클래스를 직접 불러올 수 있다

-----------------------------------------------------------
2)에 대해서 일단 내가 이해한것
ObjectMapper ( JSON으로 직렬화, 역직렬화 해주는 녀석)
는 JSON으로 변환하기 위해서 자바 reflection이용.
자바 reflection은 Object클래스로 불러온다음에 -
일단 NoArgs컨스트럭터로 인스턴스를 동적으로 생성.
인스턴스의 정확한 클래스를 몰라도 만들어낼수있다
??

2021-07-24

0724 만들어진 토큰을 api에서 검증하기

 1. ApiLoginFilter에서는 토큰을 만들어주고 (content 에 useremail을 추출해서 넣어주기)

2 . ApiCheckFilter에서는 만들어진 토큰을 검증해서 email이 있을시에만 자원을 보여준다


인증성공시 generateToken을 하고


토큰을 확인해서 email이 있다는 것은 인증을 완료했다는 것!


복호화된 토큰을 Authorization 헤더에 함께 보내면 자원요청에 대한 응답을 확인할수있다

0724 JWT 토큰을 생성하고 검증하기

 


토큰을 생성하는 메소드(위)

토큰을 검증하는 메소드(아래)

를 각각 만든다.

토큰은 : header - payload - signature의 세부분으로 나뉜다.

header에는 contenttype등의 정보,

payload에는 실제 데이터 (이것들을 모아서 claims라고 부른다)

signature는 보안을 위한 암호화 키를 넣는다.

토큰의 만료시간을 설정해야 한다. 다중로그인으로 인한 보안위험을 막기 위한 최소한의 조치. 토큰은 stateless하게 사용되고 session이라는 개념이 없기 때문이다. 또 다른 곳에서 로그인이 되었을때-검증하기가 어렵다.

토큰을 만들때는 compact()메소드를 사용해서 꽉! 묶어주고.

토큰을 검증할때는 parser()메소드를 사용해서 내용을 풀어헤친다.


테스트를 통해 토큰 안의 내용을 확인해 볼 수 있다. 



생성된 토큰을 jwt.io페이지에 넣고 키를 입력하면 - Signature Verified메시지를 확인할 수 있다.



-----------------------------------

만약에 expireDate를 조정한다면 어떻게 될까?


expire를 1초로 해보자!!


그렇다면 위와 같이 토큰이 유효하지 않음을 알려주는 에러 메시지를 확인할 수 있다.

0724 api 인증 처리하기

 Represents the token for an authentication request or for an authenticated principal once the request has been processed by the AuthenticationManager.authenticate(Authentication) method.

Once the request has been authenticated, the Authentication will usually be stored in a thread-local SecurityContext managed by the SecurityContextHolder by the authentication mechanism which is being used. 




api 로그인 페이지를 호출->

request로부터 email과 패스워드를 받아서 -

일치할경우 authentication Manager에게 토큰을 넘겨준다.

그러면 토큰이 security context에 저장된다.

post로 바디에 email과pw를 넣어서 보냈을 경우 -> 인증 OK. 
(다만 현재는 /루트로 가는 페이지가 없어서 404가 뜬다)



틀린패스워드를 넣을경우 -> 인증이 안되었다는 오류메시지를 확인할 수 있음.


0724 api check filter 만들기

 1. api check filter의 역할:

자원이 있는 api의 uri가 들어오면 - 가로채서

authorization 헤더를 체크한다.

헤더에 잘 값이 들어와있으면 인증이 완료된 사용자라는 뜻이므로 다음 filter로 chain하고,

아닌경우 json 에러메시지를 status코드와 함께 전송한다.


헤더에 authorization을 넣어보낸경우 - 자원을 응답 받을 수 있다


authorization 없는경우 - 에러코드와 메시지를 전송한다 response.getWriter를 이용한다.


apicheckFilter는 
pattern이라는 이름의 String을 멤버변수로 가지고 있다.
Securityconfig에서 생성자 멤버변수로 api uri를 넣어준다.
api/**/* 이런식으로!
그래서 해당 patter에 일치할 경우 이 필터를 타고, authorization을 검증한다.



맄리퀘스트 헤더에서 해당 키 (Authorization)을 뽑아서 검사한다.

2021-07-23

0723 Spring Security이해하기

 AuthenticationManager가 적절한 AuthenticationProvider를 선택.

AuthenticationProvider는 다양한 전략으로 구현되어 있음

그중에 쓰게 되는 것은 역시 데이터베이스 기반의 DaoAuthenticationProvider 이다.


UserDetailsService는 AuthenticationProvider가 내부적으로 이용하는 객체이다.(has-a관계)

해당 서비스를 바로 @Service어노테이션만 붙여서 빈 등록 가능.

결론적으로 - 해당 UserDetailsService를 구현하는 것으로 - DB인증이 가능해지게 된다!!
아니면 - SecurityConfig클래스에서 configure 메소드의 AuthenticaitonManagerBuilder에게 던져줘도 된다. 굳이 안써도 @Service어노테이션으로 간편하게 등록하자~~!!

0723 REST api 만들기

 

컨트롤러를 만들고 포스트맨으로 테스트 해보기~~

유의점은 POST이기 때문에 데이터를 body에 담아서 보낸다는 점!!


제대로 num이 넘어오는 것 확인!!

0723 ToString exclude 안했을 경우

 failed to lazily initialize a collection of role: com.mariworld.club.entity.ClubMember.roleSet, could not initialize proxy - no Session


이런 에러가 발생했다!

Note를 select -> note안에있는 writer 같이 left join -> writer안에 있는 role 도 가져오려고 함.but join안 걸어줘서 세션없다고 에러남


해결방법 

1) Writer안의 role속성을 eager로 가져온다  

2) ToString에서 writer는 exclude한다 

3) @Transactional로 건다 -> 이렇게 했더니 select두번 날라감


호호호. 아주 웃기는 녀석일세. JPA제대로 쓰려면 얘네의 동작원리 + DB공부를 더 해야!!!

0723 EntityGraph를 사용해서 join날리기

 

fetch type을 lazy로 했을 경우, 일반적인 select문을 치면 join나가지 않고 해당 entity만 가져온다. 하지만 lazy로 하면서 다른 entity를 조인해서 가져오고싶다면??



@EntityGraph의 attributePath에- 해당 변수명을 적고 LOAD옵션을 주면 해당 attribute는 join으로 가져온다(이때만 eager적용)


아까와 달리 left조인이 되어서 쿼리가 나가는 것을 확인할 수 있다!


2021-07-22

0722 자바 직렬화란?(Serializable 인터페이스)

 1. 왜 직렬화를 할까??

-> 자바 객체의 상태를 다른 환경(파일, DB등) 에 저장하기 위함이다.

-> 결국 자바객체는 컴퓨터 메모리에 잠깐 올라오고 사라지는.. 녀석.. 프로그램이 종료되면 당연히 해당 정보도 없어진다. 그런 자바 객체가 가지고 있는 상태정보를 저장하고 싶을때!! 사용한다.

이때 Serializable 인터페이스를 붙임으로써- 얘는 직렬화해도 괜찮은 애예요! 하고 알려준다.

2. Serializable 인터페이스는 단순 마커 인터페이스. 알려주는 역할 외에는 없다.

3. Deserialize할때는 반드시 해당 클래스 타입으로 풀어야 한다. 멤버변수 메소드 다똑같다고 하더라도 패키지가 다르다던가 하면 역직렬화시 데이터가 이상하게 변환됨.

4. 반드시 Serializable 을 해야할까?

-> 그렇지 않다!! JSON처럼.. 공통된 좋은 규약이 존재하기 때문에. 다른 형식의 정보전달을 생각해볼 수 있다.

5. transient  키워드: 직렬화에서 제외하고 싶을 때 사용하는 키워드. 예를 들어- 주민번호같은 중요 개인정보는 직렬화하지 않도록 해당 키워드를 사용할 수 있다.

0722 자바의 volatile, synchronized 키워드란

 멀티 스레드 환경에서 발생하는 부적절한 결과를 예방하기 위한 방법

1. volatile :

해당 변수의 값을 바로 메인 메모리에서 가져올 수 있게 해주는 키워드이다.

CPU캐시로부터 값을 읽어오면- 다른 스레드에서 값을 변경했을때 두 변수의 값의 일관성이 깨지기 때문이다.

따라서 메인 메모리로부터 직접 읽기/쓰기를 가능하게 하여 데이터 값의 일관성을 보장한다.

2. synchronized :

여러 스레드가 하나의 자원을 공유할 때, 점유중인 스레드 이외에는 못 사용하도록 로킹하는 키워드.

volatile키워드를 사용한다고 하더라도, 동시에 읽기가 이루어지고 쓰기가 이루어질 경우, 결과의 일관성을 보장할 수 없다.

따라서, 로킹을 통해 스레드의 접근을 제어함으로써 동시성문제를 해결한다!!

추가)) synchronized의 사용기법 - 1) 메소드 전체에 사용하기 2) 메소드 안의 특정 구간에 대해서 사용하기 가 있다.

1)의 경우 개발자는 편하지만,,, 메소드 전체를 로킹해버리기 때문에 그만큼 성능이 저하되게 된다(다른 스레드는 그만큼 기달려야 하기 땜에. ㅜㅅㅜ)

따라서 2)를 쓰도록 노력하는 개발자가 되자!! 

2021-07-20

0720 자바의 메모리 구조

 자바의 메모리 구조는 크게 세 부분으로 나눌 수 있다.

1. Class 영역

: 클래스 정보, 메소드 정보, 클래스 변수(static변수) 등을 저장한다. 일반 new로 만든 객체와 달리, static변수를 클래스 명으로 호출하는 것도 이렇게 메모리 영역이 달라서이다!!

static변수))

 - 한번 메모리에 할당되면 어플리케이션이 종료될 때까지 상주한다.

 - 객체를 생성하지 않아도 호출할 수 있기 때문에 속도가 빠르다.

 - 동일한 값이 전체 객체로부터 공유된다. 프로그램 내에서 공통으로 사용되는 자료가 있다면 static을 사용하는 것을 고려한다. ex) 사원 세금 비율 계산 할때의 tax 비율 같은것. 모두 공통적으로 적용되는 숫자들!


2. Stack 영역

: 연산 중에 발생하는 임시 데이터를 저장한다. 이름에서부터 알 수 있듯이 - FILO구조이다.

3. Heap 영역

: new로 인하여 생성되는 객체들을 저장한다. 사용되지 않는 객체는 GC에 의해 정리된다.

0720 JpaTransactionManager에 대한 탐구

 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html


<< 스프링 도큐먼트에 따르면. 하나의 datasource만을 가지고 있을 경우- jpaTransactionManager는 해당 dataSource를 auto-detect하고, 설령 JDBC직접링크방식과 같은- JPA방식이외의 DB프로그래밍을 하더라도, 하나의 트랜잭션으로 묶을 수 있게끔 처리해준다고 한다!! 이런 똑똑이!!

2021-07-19

0719 커넥션 풀을 사용했을 때와 사용하지 않았을 때의 차이

 1. 일반적인 JDBC직접 링크 방식으로 1000번 커넥션 돌렸을때


반도 못가고 중간에 뻗어버림!!


속도도 상당히 느리다. 약 100번 커넥션하는데만 6초



2. 커넥션 풀을 사용했을 경우


무사히 1000번을 빠르게 달성하고 테스트가 성공된 것을 확인할 수 있다.


성능 면에서도 훨씬!! 우수한 것을 확인할 수 있다. 1초도 안걸림.


//궁금한점-

컨트롤러등등 다른 클래스 많이 만들고 나서는- 이 커넥션 테스트가 안되는 경우가 있었다. MockMVC설정에 대해서 더 알아보아야 할듯하다.

2021-07-18

0718 Synchronized란

 멀티 스레드 환경에서, 하나의 자원에 여러 스레드가 접근할 때 데이터의 안정성을 보장하기 위하여 사용한다. 

Synchronized 키워드를 사용하면 - 현재 자원을 점유하고 있는 스레드 외 다른 스레드들의 접근을 차단하여 준다. 

그러나 단점은 - 이렇게 함으로써 성능저하가 이루어질 수 있다는 것이다. -> 적재적소에 사용해야 한다.

0718 equals, == , hashcode

 1. equals는 객체를 비교 하는 메서드이고,

==는 값을 비교하는 연산자이다. 

equals는 두개의 객체가 동일한지를 검사한다. 기본적으로는 메모리값을 기준으로 하기 때문에, 오버라이딩하지않으면 - 두 객체가 가지고 있는 멤버변수값이 전부 동일하더라도 false가 나온다.

롬복을 이용해서 - @Equals메소드를 간단하게 오버라이딩할 수 있다. 


2. hashcode : 메모리의 주소값을 기준으로 해쉬코드값을 생성.

따라서 equals메서드를 재정의 하는 경우, 사이드이펙트를 줄이기 위하여 해쉬코드도 재정의한다. 해당 객체 equals()가 true라면 hashcode또한 true하도록!!

동일한 객체는 동일한 메모리 주소를 가져야 한다. 

HashMap에 equals()true인 객체를 두개 넣어도 -> size가 1개 나오도록!!

(Hash~~의 자료구조 : 해쉬코드 값을 기준으로 key값을 생성한다.)

0718 파일 업로드 취약점 및 메서드 공부

1. 파일 업로드 확장자 검사

: javascript의 정규식(클라이언트) + content-type검사(서버)


2. 파일의 경로 직접노출 방지

: file을 보여줄때, img src =직접경로 : 절대금지!! 매우 위험. 디렉토리 구조가 노출된다.

따로 메서드를 만들어서 해당 url로 파일을 불러올 수 있도록 한다.


3. 파일이름 검사

: getOriginalFileName을 했을 때의 고민이 있었다. 한글문제는 인코딩 한다고 치더라도...

../../../ <-이런 악의적인 파일이름을 어떻게 할것인가? 하는 문제.

그래서 아예 파일을 저장할때는 filename을 안받고, DB에만 저장하는 식으로 했다.

(파일이름은 전부 UUID로, 사용자가 본인이 올린 파일의 이름을 임의적으로 조정못하도록@@!!) 


4. Path란 -> File클래스의 업그레이드 버전이라고 할 수 있다

https://stackoverflow.com/questions/6903335/java-path-vs-file

오라클 공식 사이트에서도 File보다 Path를 사용하라고 권고하고 있다. File클래스의 부족한 점이 있기 때문.

  • Many methods didn't throw exceptions when they failed, so it was impossible to obtain a useful error message. For example, if a file deletion failed, the program would receive a "delete fail" but wouldn't know if it was because the file didn't exist, the user didn't have permissions, or there was some other problem.

5. Files.probeContentType 메서드:

파일의 확장자(mime타입)을 검사하는 메서드. 실제 파일을 들여다보는 것이 아니라 뒤의 .을 기준으로 판단한다고 함. 나는 애초에 저장할때 확장자 .뒤로 받아서 저장했기 때문에. null이 나올 우려는 거의(?) 없다. !!

6. file.getParent()

현재파일이 위치하는 곳의 부모 디렉토리 절대경로를 리턴

2021-07-17

0717 자바 웹 개발 개념들 공부

 1. 프레임워크와 플랫폼의 차이점 :

프레임워크 - 그자체로 동작하는 소프트웨어. (스프링부트 바로 run가능한걸 생각하면 . !!)

플랫폼 - 뼈대만을 제공, 동작하지는 않는다

2. 라이브러리 - 잘 만들어진 기능을 가져다 사용할 수 있음

3. model 1방식과 model2방식 :

model1방식 - jsp페이지 안에 view로직과 비지니스 로직이 얽혀있다. 스파게티 코드!!

model2 방식 - view와 비지니스 로직을 분리, 수정 확장이 용이한 구조(MVC패턴)

4. 브라우저에 URL을 입력하면 벌어지는 일 :

URL입력 ->DNS서버에 의해 IP목적지 확인 -> TCP/IP통신으로 소켓 연결 -> 데이터 송수신 -> 요청에 대한 응답을 브라우저가 해석하여 유저에게 보여준다

나는 이 그림을 좋아한다


5. HTML 이란: 텍스트 중심의 , 데이터교환을 위한 매체


2021-07-15

0715 배운것들

 1. Encode, Decode를 하는 이유

1) 컴퓨터가 알아들을 수 있는 2진법 언어로 변환하기 위하여

2) 다양한 언어(영어, 한국어, 일본어...) 를 통일된 규격으로 맞추어 데이터 손실을 방지하기 위하여. 

즉 표준화된 데이터 전송 포맷을 위해 encode decode를 한다!!


2. Base-64 인코딩 방식이란

64개의 문자로 인코딩 하는 것. 데이터 손실을 방지한다!


3. jsp와 javascript의 차이점

jsp는 서버, javascript는 클라이언트에서 사용함

(나는 막 컴파일언어 인터프리터 언어 이렇게 설명했는데... 서버/클라이언트라는 차이점이 훨씬 명확한!!) 

2021-07-14

0714 UDADA프로젝트 README업데이트!!

 https://github.com/MARI2020201101/Udada_Project#readme

<<우다다 프로젝트 리드미를 업데이트 하였다!!!

쫙 정리하고 나니까 맘이 편하다! 이쁘다!

프로젝트를 하면서, 중요한것은 프로그래밍 실력도 실력이지만

나의 성장을 팀 전체의 성장으로 연결시키는 방법을 모색하는 것이었다.

그를 위한 문서화, 매뉴얼 작업 등이 굉장히 중요하다는 것도 배웠다.

다른 사람들을 위한 글을 작성할 수 있도록 노력해야지!!

2021-07-12

0712 이미지 수정시 NPE!!!


서버에 띄우고 게시글 수정시 이미지를 수정하지 않은 경우 null에러가 뜬다!! 

삼중에 걸쳐서 null 입력값을 검증하고, 로그를 찍어보았더니 
마지막의 equals부분만 false뜬다(와 진짜 숨막힌다. 간신히 막네..)
결국 위 에러는 if문 을 통과해서 null인데 변수를 set하려고했기때문에 발생하는 에러.
NPE가 제일 무섭다 흑흑. 

그런데 서버에 띄우기 전 로컬에서는 이 상태로 잘 돌아갔기 때문에... 대체 어떤식으로 돌아가고 있었는지가 의문이다. STS의 자체적인 서비스인가...

0712 서버에 더미데이터 생성하기

 


0712 프로젝트 환경변화에 대응하기

 

다른 팀원보다 3일 먼저 환경설정.

4가지 경우의 수의 root-context.xml을 준비하여 다양한 환경변화에 신속하게 대응할 수 있도록 작성 

2021-07-09

0709 페이지 정돈 + 댓글 기능 추가

 


카드박스를 추가해서 숫자로 유저가 일목요연하게 정보를 확인할 수있게끔 디자인을 개선 하였다.

또한 그래프 차트를 이용하여 시각적으로 명확하게 레시피 정보를 확인할 수 있다.


댓글과 평점을 통해 유저는 레시피에 대한 피드백을 할 수있다.
댓글은 글을 쓴 유저만 수정/삭제가 가능하고, 
로그인을 한 유저에게만 input창이 보이게 된다.

페이지가 유연하게 연결되게끔, 레시피의 재료 정보가 푸드 페이지와 연결되도록 링크 처리를 하였다.


마이 푸드 페이지에서도 같은 작업을 하였다!!

2021-07-08

0708 서버문제 해결

 

1. 백그라운드에서 돌고있던 서버 강제종료



2. 로그인 안되었던 이유: 어째서인지 내 더미데이터의 MEMBER 의 패스워드가 전혀 인코딩 되어있지 않은 상태로 들어가 있었다. 그래서 아예 싹 데이터 없애버림.



3. 이미지 등록 잘된다 ㅜㅜㅜㅜ 우선 로컬은 해결@@!!! 이제 AWS의 문제만남았다....대체 UPLOAD PATH를 어디로 잡아야하는가!!

2021-07-07

0707 중복 메시지 오류해결

 

addIngre버튼 안에- searchBtn버튼이 눌리는 식으로 메서드 안에 메서드를 작성했더니

str이 중복해서 나타나는 문제가 있었다.

addIngre를 부를때마다 str이 계속 쌓이는 것이었다.

메서드를 분리해서. addIngre는 얘대로. searchBtn은 얘대로 따로따로 on클릭 메서드를 적어야한다! onclick안에 onclick을 하면. str이 초기화되지않고 계속 쌓인다!


+ foodmy로 insert한 뒤, foodMy로 이동할수있도록 링크를 추가했다!! ㅎㅎ 쇼핑몰은 이런식으로 장바구니 담기 -> 장바구니 담기로 이동하기 라는 박스를 보여주니까. 그걸 따라해보았다. 지속적인 개선!! 페이지들이 잘 연결되는 흐름을 만들수있도록!!

0707 서버를 올린적이 없는데 자동으로 올라간다?

 

로컬 서버를 올린 적이 없는데 포트가 충돌나서 열수없다고 한다?

혹시몰라서 aws EC2 도 중지시키고 ( 여기 문제는 애초에 아니겠지. 내가 서버를 안띄웠는데?? 게다가 로컬접속인데?)

프로퍼티 파일의 server.port도 바꿔서 시도했는데 또 충돌나서 안된다고 함?? 뭐지 이건??

게다가 로그인도 안됨(??) 뭐야 대체 어디서 실행되고 있는거야!!!

내가 서버를 백그라운드로 올린 적이 있었나? 뭔가 이상하다. 살펴보아야 겠음. ;;  


포트번호 8989로 이상하게 바꾸고 다시 인텔리제이가동시켜도- 똑같이 충돌난다구 함. 왜냐~~ 왜냐구~~

0707 java 메서드를 jsp안에서 사용하기

 1. dto클래스 안에 메서드를 만들기 . static으로 해서 바로 메서드에 접근할 수 있도록 할 것이다.


2. 사용법은 간단하다! 페이지 import를 선언해주고, static이므로 클래스명으로 부르고- 메서드를 사용하면된다!! 변수도 그냥 일반 jstl쓰듯 넣어주면 됨. ㅎㅎ




0328 fdisk, mkfs, mount, fstab

 1. 하드디스크를 붙인다. 2. fdisk -l로 하드디스크를 확인한다.  - interactiive한 커맨드모드 사용하여 (m) 붙인 하드디스크의 파티셔닝을 한다.  - 마지막에 w를 해야 실제로 반영이 된다.  3. mkfs를 하여 어떤 파일시스...