list.jsp에서 table 이 안나와서 왜 그런가 알아보다가, 

<table id="list" width="90%">

<c:forEach items="${list}" var="u">

 

즉, c:forEach에서 ${list}를 못 읽어오는것 같아서 찾아보니, jstl 라이브러리를 import하지 않아서 그런거였다...

 

 

외부 css 파일 참조하게 만들기:

<link rel="stylesheet" href="${path}/resouces/css/liststyle.css">

 

 

No Mapping found for HTTP request Error:

www.baeldung.com/spring-mvc-404-error

 

 

 

 

 

 

servlet-context.xml에서 /* 와 /** 차이점이 궁금해졌다: 

Ant path style patterns 을 이용한 방법이라 한다. ( stackoverflow.com/questions/2952196/ant-path-style-patterns )

 

? : 1개의 문자와 매칭 (matches single character)

* : 0개 이상의 문자와 매칭 (matches zero or more characters)

** : 0개 이상의 디렉토리와 파일 매칭 (matches all files / directories)

 

stackoverflow.com/questions/12569308/spring-difference-of-and-with-regards-to-paths

  1. ? matches one character
  2. * matches zero or more characters
  3. ** matches zero or more 'directories' in a path

2021/03/31:

servlet-context.xml : 

interceptor에서 exclude-mapping

elfinlas.tistory.com/343

 

 

 

 

 

m.blog.naver.com/PostView.nhn?blogId=kkson50&logNo=220564174258&proxyReferer=https:%2F%2Fwww.google.com%2F

 

1) serialization: 객체를 바이트 형식으로 전환시켜 DB, memory, file 에 저장했다가 나중에 deserialization을 통해 객체를 만들어서 사용하는것

deserialization: 

 

2) 객체 형태로 들어갔다가 객체 형태로 나와야 하니까, 

FileOutputStream() => ObjectOutputStream() 

 

3) serialVersionUID로 특정 객체를 인식하는데에 사용한다.

m.blog.naver.com/PostView.nhn?blogId=kkson50&logNo=220564273220&proxyReferer=https:%2F%2Fwww.google.com%2F

위 블로그 보기) 이렇듯 serialVersionUID값을 파일등으로 저장을 할때 해당하는 클래스의 버전이 맞는지를 확인하는 중요한 장치입니다.

그런데 이 serialVersionUID를 작성하지 않으면 Java VM에서 내부 알고리즘에 따라서 자동으로 작성을 하게 되는데, 이것은 어떤 Java VM을 사용하는지에 따라서 달라지게 됩니다.

따라서 무조건 serialVersionUID 값을 설정하기를 권장을 합니다.

 

 

Points to remember:

1) static으로 선언되지 않은 변수들만 serialization 을 통해 저장이 된다.

2) Static 멤버와 transient 멤버는 Serialization을 할때 저장되지 않는다. 그래서 static으로 선언하지 않은 변수들 중에 저장하고 싶지 않은 내용은 무조건 modifier를 transient으로 만들어줘라.

3) 만약 부모 클래스가 Serializable 인터페이스를 implement했다면, 자식 클래스는 할 필요가 없다. 하지만 자식 클래스가 Serializable을 사용하고자 한다면, 부모 클래스는 무조건 Serializable 인터페이스를 먼저 implement해야만 subclass(자식)클래스가 사용할 수 있다.

4) 객체가 Deserialization을 거칠때 constructor는 실행되지 않는다.

5) 


1. If a parent class has implemented Serializable interface then child class doesn’t need to implement it but vice-versa is not true.
2. Only non-static data members are saved via Serialization process.
3. Static data members and transient data members are not saved via Serialization process.So, if you don’t want to save value of a non-static data member then make it transient.
4. Constructor of object is never called when an object is deserialized.
5. Associated objects must be implementing Serializable interface.
Example :

 

--

www.geeksforgeeks.org/serialization-in-java/

가령 a변수를 transient, ㅠb변수를 static으로 선언했다고 쳐보자.

Serialization 과정에서 transient변수는 serialize가 안되고, deserialization과정에서 default 값으로 세팅이 된다. int는 0, 객체는 null로...)

Serialization 과정에서 static변수는 serialize가 안되고, deserialization과정에서 현재 상태의 클래스 멤버변수가 가지는 값으로 deserialize되어 세팅이 된다. 

 

You have seen while deserializing the object the values of a and b has changed. The reason being a was marked as transient and b was static.
In case of transient variables:- A variable defined with transient keyword is not serialized during serialization process.This variable will be initialized with default value during deserialization. (e.g: for objects it is null, for int it is 0).
In case of static Variables:- A variable defined with static keyword is not serialized during serialization process.This variable will be loaded with current value defined in the class during deserialization.

 

transient keyword를 사용하는 이유는 serialization 과정에서 bytestream 단위로 변화시키는 것을 막기 위함이다. bytestream으로 변환이 안되면 파일에 저장이 안되게 할 수 있기 때문이다. 주로 정보 보안을 위해서 transient를 사용한다. 이 키워드를 사용하면 JVM에게 해당 변수는 persistent Java variable이 아니라는 것을 명시해준다.

 

이상하게 mapper.xml에서 sql 쿼리가 정상적으로 작동을 안하는지 결과가 엉뚱하게 테이블 내의 모든 row를 리턴해서 보여주고 있는 것이었다. 그리고 에러 메시지도 안뜨고...

내가 원하는건 딱 keyword를 포함하고 있는 게시글들이었는디...

참으로 답답했는데 다시 검색 기능 구현하기를 검색해본 결과 아래와 같이 코드를 변경해주니 정상 작동하였다. (감격 ㅠㅜㅜ)

 

요약: 

like '%'||#{keyword}||'%'
부분을 ->
CONCAT ('%', #{keyword},'%')

문제였던 구역: (전)

<!-- sql code 조각 -->
	<!-- 반복되는 sql의 일부를 sql태그를 이용하여 따로 빼둘수 있다.
	검색 조건 sql -->
	<sql id="search">
		<choose>
			<!-- 검색옵션이 전체 검색일 경우 -->
			<when test="searchOption == 'all'">
				WHERE 
					writer like '%'||#{keyword}||'%'
				OR 
					content like '%'||#{keyword}||'%'
				OR 
					title like '%'||#{keyword}||'%'
			</when>
			<!-- 전체 검색이 아닐 경우 -->
			<otherwise>
				WHERE ${searchOption} like '%'||#{keyword}||'%'
			</otherwise>
		</choose>
	</sql>

 

문제였던 구역: (후)

<sql id="search">
		<choose>
			<!-- 검색옵션이 전체 검색일 경우 -->
			<when test="searchOption == 'all'">
				WHERE 
					writer like CONCAT ('%', #{keyword},'%')
				OR 
					content like CONCAT ('%', #{keyword},'%')
				OR 
					title like CONCAT ('%', #{keyword},'%')
			</when>
			<!-- 전체 검색이 아닐 경우 -->
			<otherwise>
				WHERE ${searchOption} like CONCAT ('%', #{keyword},'%')
			</otherwise>
		</choose>
	</sql>

board-mapper.xml 전체 코드

<mapper> 태그 안에 아래 코드: 

<!-- 01. 게시글 전체 목록 조회 및 검색조회까지 -->
	<select id="listAll" resultType="board">
			SELECT*FROM
				LF_Product_Test
			<!-- 검색조건 -->
			<include refid="search"></include>
			ORDER BY seq
		<!-- 페이징 -->
		<!-- <include refid="pagingFooter"></include>	 -->
	</select>
	<!-- 02_02. 게시글 레코드 갯수 -->
	<select id="countArticle" resultType="int">
		SELECT COUNT(*) FROM LF_Product_Test
		<!-- WHERE절을 include 태그로 삽입 -->
		<include refid="search"></include>
	</select>
	<!-- sql code 조각 -->
	<!-- 반복되는 sql의 일부를 sql태그를 이용하여 따로 빼둘수 있다.
	검색 조건 sql -->
	<sql id="search">
		<choose>
			<!-- 검색옵션이 전체 검색일 경우 -->
			<when test="searchOption == 'all'">
				WHERE 
					writer like CONCAT ('%', #{keyword},'%')
				OR 
					content like CONCAT ('%', #{keyword},'%')
				OR 
					title like CONCAT ('%', #{keyword},'%')
			</when>
			<!-- 전체 검색이 아닐 경우 -->
			<!-- 따옴표 넣어줬는데 맞나...? -->
			<otherwise>
				WHERE ${searchOption} like CONCAT ('%', #{keyword},'%')
			</otherwise>
		</choose>
	</sql>

직접 공부를 하면서 이론 정리를 위해서 내용을 정리를 해보았다.

구글 로그인을 구현하기 위해서 아래 단계를 따르면 좋을 것 같다.

1. Oauth에 대해야 알아보기

2. Access Token 이란?

3. Google login을 위한 세팅 작업

4. 로그인 코드 구현 흐름 파악하기

 

빠른 숏컷을 위하면 아래 블로그를 살펴보면 대략 전체적인 흐름을 빠르게 살펴볼수 있습니다.

github.com/lyw3447/EveryDay/wiki/Google-Login

 

1. Oauth에 대하여:

Oauth + access token 설명 있음:

opentutorials.org/course/3405

opentutorials.org/course/2473/16571

2. Access Token 이란? (주의!: 세부 내용이다): 전체적인 흐름은 1번 이고잉 선생님 강의 참조

access token: 

velog.io/@silverj-kim/Front-end-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84-1-OAuthJWTSession

 

3. Google login을 위한 세팅 작업:

imweb.me/faq?mode=view&category=29&category2=47&idx=71637

 

4-1. 로그인 코드 구현 흐름 파악하기:

아래 wiki 에서 설명이 잘 되어 있어서 참고하면 좋다.

github.com/lyw3447/EveryDay/wiki/Google-Login

 

4-2. Google 로그인 구현 내용: (다른 분의 블로그 포스트 내용을 참고 했습니다)

gdtbgl93.tistory.com/182

깃헙:

github.com/curiduck/spring-google-oauth

 

 

그냥 참고: (주관적인 제 의견입니다...) 만약에 틀렸다면 편하게 말씀해주시면 감사하겠습니다. 

아래 링크는 이고잉 선생님이 간단하게 로그인을 구현한 내용이다.

그런데 이건 한계가 있다. 같은 페이지 내에서 로그인하고 redirect를 하는것 같다..

그리고 로그인 정보를 유지하는데 토큰을 사용하지 않는것 같다.... 

opentutorials.org/course/3424/22236

A successful Git branching model

 

backlog.com/git-tutorial/kr/stepup/stepup1_5.html

이 운용 모델에서는 크게 나눠 4가지 종류의 브랜치를 이용하여 개발을 진행합니다.

  • 메인 브랜치(Main branch)
  • 피처 브랜치(Feature branch) 또는 토픽 브랜치(Topic branch)
  • 릴리스 브랜치(Release branch)
  • 핫픽스 브랜치(Hotfix branch)

 

참고 자료:

careerkarma.com/blog/git-nothing-to-commit-working-directory-clean/

 

git conflict을 해결하고 난 뒤에 아래와 같은 메세지가 나올때가 있다.

이 뜻은 merge할때 일어난 충돌을 해결하고

$ git add xxx,

$ git commit -m "merge conflict solved"

라고 하고 나면 

origin/master와 master의 상태가 동일함으로 working directory clean이라고 뜨게 되는 것이다.

backlog.com/git-tutorial/kr/stepup/stepup2_7.html

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

 

 

일단,

git pull = git fetch + git merge 이다.

 

git merge를 하는 과정을 살펴보자>

브랜치가 나뉘어지고 feature 브랜치에서 master에 업데이트된 내용을 받기 위해선 두가지 옵션이 있다.

1) merging or

2) rebasing.

 

1) merging 방법:

$git checkout feature (Feature 브랜치로 이동)

$git merge master (Feature에서 master를 가져와서 병합하는 것이다)

또는, 한 명령어 라인으로,

$git merge feature master (컴공에서는 항상 A <- B  이런식이다) 즉, feature에 master를 갖다붙임

git merge가 git rebase에 비해 non-destructive method이라 여겨지는데, 왜냐하면 기존의 브랜치들이 영향을 받아서 바뀌지 않기 때문이다.

하지만, 이 방법은 master가 만약 active하게 계속 업데이트가 되는 상황이라면, 계속 feature브랜치가 새로운 커밋을 git merge해야하기 때문에 나중에 브랜치 히스토리를 복잡하게 만들 수 있다. git log 명령어로 조금 덜 복잡하게 만들 순 있지만 다른 개발자들에게 직관적인 브랜치 히스토리를 주지 못한다. (리뷰할때)

 

Rebasing

Merging의 대안으로 rebasing 명령을 사용하여 feature 브랜치를 master브랜치로 리베이스 할 수 있습니다 .

git rebase를 하면 마치 순차적으로 master를 업데이트 하고 있던 것 처럼 보이게 만들 수 있습니다.

아래 그림과 같이 feature를 master 뒤에 연결함으로써 마치 처음부터 순차적으로(sequentially)하게 작업한 것과 같은 타임라인을 지니게 할 수 있습니다. 대신 commit history가 하나로 묶여지게 되죠. (마스터로 ) 

아래 그림(learngitbranching.js.org/?locale=en_US) (rebase편) 에서의 설명:

$git rebase main(rebase를 c3에서 한 경우) 

c3' 라는 복사본이 main의 위에 (main의 tip) 연결이 되고 c3는 희미하게 트리에 기록이 남아있습니다. 하지만 이 작업은 내 로컬 PC에만 작용이 된 것이기 때문에 remote에도 반영을 해줘야 합니다.

이렇게 main으로 checkout한 뒤에 rebase를 진행해줍니다.

그럼 아래 그럼과 같이 main과 bugFix가 같은 마지막 커밋 위치(HEAD)로 이동함을 알 수 있습니다. 

즉, main이 앞으로 fast-forward되었습니다. (fast-forward는 아래 참조)

 

fast-forward란?

bugFix 브랜치를 만들고 작업하면서 그동안 master에 아무런 변화가 없었다면 master 브랜치의 HEAD를 bugFix 브랜치에 간단히 옮기기만(2가지 방법이 있음: git merge or git rebase) 해도 아무런 충돌없이 진행이 가능합니다. 그저 master 브랜치를 이동시키기만 해도 된다고 하여 fast-forward라고 부릅니다. 이동시키는 방법은 bugFix에서 $git rebase master 또는, $git merge master 를 하면 됩니다. 그럼 알아서 master의 HEAD를 옮기기만 합니다. 

 

여기서는 내 정리)

하지만, 만약 master 브랜치가 계속 업데이트가 되어 바뀌었다면 fast-forward가 되지를 않습니다. 그래서 merge나 git rebase를 하게 되면 commit이 발생하게 되어 commit message를 입력하여야 합니다. 밑에 글 (스크롤 내려서) 참조: 서로 다른 브랜치 병합하기 부제목

backlog.com/git-tutorial/kr/stepup/stepup1_4.html

서로 다른 branch 병합하기 (merge)

yuja-kong.tistory.com/51

commit 5는 원래 마스터가 가지고 있는 내용. 3,4가 exp꺼였는데 master에 병합된 내용

 

 

하지만, 만약 master 브랜치가 계속 업데이트가 되어 바뀌었다면 fast-forward가 되지를 않습니다. 그래서 merge나 git rebase를 하게 되면 commit이 발생하게 되어 commit message를 입력하여야 합니다. 

 

다시 정리하자면 merge commit은 서로 다른 상태의 브랜치를 병합해서 새로운 commit을 만드는 경우이고

fast forward는 동일 내용이 포함되는 브랜치일 경우 브랜치 이동만으로 병합해서 따로 commit을 생성하지 않는 경우입니다.

가령 fontawesome의 이미지를 사용하고 싶을때 cdn bootstrap 을 사용하고 싶을때가 있다.

이때 해당 fontawesome cdn boostrap 을 html 용으로 받아서 위에 <head> 태그 안에 넣어서 사용할 수 있다.

 

사용법 순서)

구글 검색 -> fontawesome bootstrap cdn -> html 용으로 copy! -> html 문서의 <head>태그 안에 넣기 -> <body>태그 안의 코드에 fontawesome class 사용하기! 

 

 

fontawesome 의 버전이 계속 달라지는 것 같은데,

위 버전은 아래 사이트에서 원하는 아이콘을 찾아서 사용하면 된다.

https://fontawesome.com/v4.7/icons/

이게 버전이 안 맞으면 호환성 문제 때문에 제대로 아이콘이 안 뜨기 때문에 버전에 맞춰서 아이콘을 적용해야 한다.

 

2021/09/31 (월) : 오전 12:26

fontawesome 사용 방법이 좀 바뀐것 같다. 이메일 인증 후 할당 되는 고유 fontawesome cdn 으로 사용할 수 있는 것 같다.

 

<head> 태그 안에 아래 코드를 넣어주면 된다. (해당 CDN은 아래 블로그 작성자님의 CDN이다. 

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" integrity="sha384-HzLeBuhoNPvSl5KYnjx0BT+WB0QEEqLprO+NBkkk5gbc67FTaL7XIGa2w1L0Xbgc" crossorigin="anonymous">

https://amango.tistory.com/7

 

폰트어썸 - Font Awesome 아이콘 사용법

폰트어썸 이용하기 폰트어썸 홈페이지 바로가기 ▼ Font Awesome The world’s most popular and easiest to use icon set just got an upgrade. More icons. More styles. More Options. fontawesome.com 무료로..

amango.tistory.com

 

Github pull error

Pull 을 해도 충돌 에러가 발생하면 아래와 같이 Synchronize 탭을 열어서 수동으로 코드를 병합해주고 (오른쪽이 remote에서 받아온 코드인데 이걸 왼쪽에 복붙해서 합쳐주고 저장) 이제 add to index -> commit (commit message 입력) -> pull 받으면 정상으로 해결이 된다.

아래 링크를 참조하길...

 

m.blog.naver.com/PostView.nhn?blogId=lge920904&logNo=220274506449&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

'Github' 카테고리의 다른 글

[git 공부] 이상적인 git branching model  (0) 2021.03.01
[Git공부] git pull vs git rebase  (0) 2021.03.01

+ Recent posts