Merge 된 브랜치 취소하기
git reset --merge 60f3339(<-머지된 커밋)git push -f origin HEAD:머지를 하기전 브랜치이름, 머지를 수행한 브랜치
Merge 된 브랜치 취소하기
git reset --merge 60f3339(<-머지된 커밋)회사 꼬맹이 한테 explain 해보라고 하고선,
정작 나는 다 까먹었다.
http://www.24w.jp/blog/?p=250
type 에 index라고 되어있으면 index 테이블을 풀스캔하고 있는거라 느린거라고함.
key_len이 생각한대로 수치가 나오는지(int는 4바이트) 호가인
쿼리 뒤에 \G 를 넣어서 세로로 출력
그리고 팁으로
MySQL 성능 죽이는 17가지 방법
https://denodo1.tistory.com/310?category=357842
에서 "- 타입 컬럼에 index 써있는거랑 Extra 컬럼에 index 써있는거랑 “매우 큰” 차이 있음" 가 위에 type 에 대한 말임.
정규화는 필수. 그냥 막 테이블에 새칼럼 쑤셔넣는짓은 하지마.
정규화화 더불어 쿼리 캐시를 위해서 해야할일이
* 자주 변하는 것과 변하지 않는 것을 쪼개는게 중요하다 이 말임.
새로운 프로젝트에서 기존의 springboot + thymeleaf 보다 VueJs를 사용하려고 했더니 NuxtJs라는 놈이 있어서 서버구축까지 간단하게 된다는 것을 알게되었다.
NextJs라는 ReactJs의 프레임워크를 VueJs로 포팅(?) 했다는 건데 사용법이 매우 간단했다.
thymeleaf 는 html에 이런저런 지저분한 자체태그옵션과 문법, 그리고 Jquery 등을 이용해서 정말 구린방식으로 개발해야되었는데, 콤포넌트 기반의 VueJs로 개발해보니 정말 내가 원했던 프레임워크였다는 생각이든다.
개발 소프트웨어 요구사항에 작업하면서 간단히 정리 한것을 올려보겠다.
공식홈페이지 (https://nuxtjs.org/guide)
Server Side Rendering (SSR)이 가능한 FrontEnd Framework
VueJs의 장점을 SSR로 구축가능하도록 해줌
자동으로 webpack 빌드
직관적인 스캐폴딩
MIT 라이센스
컴포넌트 기반의 프레임워크
양방향 데이터 바인딩 가능 (MVVM 패턴)
가상돔(일부만 렌더링)
각 컴포넌트마다 라이프사이클이 존재
개발팁
Vuejs Style Guid - 중요도 A
컴퍼넌트 이름은 html 태그(앞으로 존재할지도 모르는)와 충돌되지 않도록 하이픈( - ) 으로 연결된 케밥스타일로 한다.
(예 : https://vuejs.org/v2/style-guide/#Multi-word-component-names-essential)
컴퍼넌트내의 data 선언부분은 반드시 함수로 지정하여 같은 컴퍼넌트가 여러군데 사용될 경우에도 내부 데이터가 각각의 컴퍼넌트 인스턴스 객체데이터로서 보관될수 있도록한다.
(예:https://vuejs.org/v2/style-guide/#Component-data-essential)
컴퍼넌트내의 pops 변수는 가능한 타입, 필수여부, 밸리데이터(이건 필요한경우만) 를 지정하여 타입 및 값에 대한 안정성체크를 한다.
(예: https://vuejs.org/v2/style-guide/#Prop-definitions-essential)
v-for 에는 key 를 반드시 사용한다.
(예:https://vuejs.org/v2/style-guide/#Keyed-v-for-essential)
같은 태그 또는 디렉티브에서 v-if 와 v-for 는 결코 같이 사용하지 않는다.
(예 : https://vuejs.org/v2/style-guide/#Avoid-v-if-with-v-for-essential)
컴퍼넌트내에서만 사용할 css style 라면 scope 를 지정하여 다른 컴퍼넌트와 style속성이 충돌나지 않도록 한다.
(예: https://vuejs.org/v2/style-guide/#Component-style-scoping-essential)
컴퍼넌트 내부에서만 사용하는 변수,함수는 내부접근제한자( $_ )를 지정한다.
(예: https://vuejs.org/v2/style-guide/#Private-property-names-essential)
Vuejs Style Guid - 중요도 B
컴퍼넌트는 반드시 하나의 독립된 파일로 생성한다.
(예 :https://vuejs.org/v2/style-guide/#Component-files-strongly-recommended )
컴퍼넌트 파일 이름은 케밥스타일로 한다.
(예 : https://vuejs.org/v2/style-guide/#Single-file-component-filename-casing-strongly-recommended)
일관된 컴포넌트 이름 규칙을 청한다.
(예 : https://vuejs.org/v2/style-guide/#Base-component-names-strongly-recommended )
(예 : https://vuejs.org/v2/style-guide/#Tightly-coupled-component-names-strongly-recommended )
Props 선언시 스크립트 에서는 camelCase , 템플릿에서 사용시에는 케밥
(예 : https://vuejs.org/v2/style-guide/#Prop-name-casing-strongly-recommended)
템플릿에서 컴퍼넌트 props를 전달할떄는 한속성당 한줄 사용
(예 : https://vuejs.org/v2/style-guide/#Multi-attribute-elements-strongly-recommended)
템플릿에서 복잡한 연산은 하지않도록, 대신 cmputed 변수를 사용
(예 : https://vuejs.org/v2/style-guide/#Multi-attribute-elements-strongly-recommended)
computed 속성에 사용하는 로직은 최대한 심플하게 작성하도록 한다. 되도록 세분화된 여러로직으로 나누어 [일기좋고, 추가변경에 용이하고, 테스트하기 좋은] 코드로 만든다.
(예:https://vuejs.org/v2/style-guide/#Simple-computed-properties-strongly-recommended)
디렉티브 단축어 (: for v-bind:, @ for v-on: and # for v-slot) 항상쓰거나 , 아예쓰지않거나 한다.
(예: https://vuejs.org/v2/style-guide/#Directive-shorthands-strongly-recommended)
Vuejs Style Guid - 중요도 C - 통과
Vuejs Style Guid - 중요도 B
부모컴퍼넌트와 자식컴퍼넌트가 통신할떄 규칙은 부모->자식은 props , 자식->부모는 event로 해서 dsep coupling 을 피하도록 한다.
(예 :https://vuejs.org/v2/style-guide/#Component-files-strongly-recommended )
data 지시어
변수나 함수를 선언.
단방향 데이터
컴퍼넌트 내부에서만 사용하는 변수는 접근제한자 $_ 를 사용하여 선언하길 권장.
스코프를 제한하기위해서 선언시 data : functuon() { } 으로 지정
소스코드내에서의 변수 이름은 카멜케이스, 템플릿에서는 케밥케이스로 지정
(예 : https://vuejs.org/v2/api/#data)
props 속성
부모컴퍼넌트에서 하위 컴퍼넌트에 데이터를 전달하기위한 변수나 함수를 선언.
같은 이름의 변수를 data 와 props 에 지정하는건 금지.
type, default, required, validator(function) 을 지정해서 전달받은 값에 대한 안정성을 검증가능.
(예 : https://vuejs.org/v2/api/#props)
computed 속성
get/set 을 별도로 지정가능한 변수 선언가능
내부로직이 컴퍼넌트 내부의 어떤 변수에도 의존되지 않는경우(즉 외부 함수를 단순히 불러내는 Date.now() 같은경우) 맨처음 캐싱된 데이터를 돌려주기 때문에 이럴경우에는 메쏘드를 사용한다.
(예: https://kr.vuejs.org/v2/guide/computed.html#computed-%EC%86%8D%EC%84%B1%EC%9D%98-%EC%BA%90%EC%8B%B1-vs-%EB%A9%94%EC%86%8C%EB%93%9C)
model
양방향 통신을 하기위해서는 v-model 을 활용.
prop, event 속성 설정
라이프 사이클 참고 자료 (https://medium.com/witinweb/vue-js-%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-7780cdd97dd4)
created
컴퍼넌트의 초기화에 필요한 데이터 가져오기, 변수에 할당하기 등을 작업한다. DOM 요소에는 접근할수없다.
부모->자식 순서로 실행된다.
mounted
DOM요소가 화면에 렌더링이 된후에 실행된다. created 에서 처리된 데이터를 화면표시 전에 DOM 에서 이용할수있다.
단, 자식컴퍼넌트의 mounted 가 끝나야 부모 컴퍼넌트의 mounted 가 실행된다.
updated
화면단에서 데이터의 변경에 의해 재렌더링이 일어날 필요가 있을경우 실행된다.
destroy
뷰인스턴스(컴퍼넌트)가 제거된 후 에 실행된다. 단, 이벤트제거등은 beforeDestroy 에서 한다.
내장디렉티브목록(https://vuejs.org/v2/api/#Directives)
v-text : {{ }} 와 같다.
v-html : XSS 공격의 위험성이 있으므로 신뢰할수 있는 컨텐츠에서만 사용
v-show : display CSS 적용해줌
v-if : if
v-else : if else
v-else-if : else if
v-for : for
v-on : 약어 @, 일반 DOM에는 표준 DOM 이벤트발생, 사용자 컴퍼넌트에서는 사용자 이벤트 발생가능
(상세참고 : https://kr.vuejs.org/v2/api/#v-on, https://kr.vuejs.org/v2/guide/components.html#search-query-nav)
v-bind : 컴퍼넌트 속성 또는 표현식을 바인딩, class 또는 style 지정, 하위컴퍼넌트의 속성에 바인딩가능
v-model : 폼인풋또는 컴퍼넌트에 양방향 바인딩
v-slot : 컴퍼넌트를 재사용하기 위해서, 컴퍼넌트의 내부에 한개혹은 다수의 slot 을 배치해, 해당컴퍼넌트를 사용하고자할때 slot 영역을 상황에 따라 다른 컴퍼넌트등으로 대치가능하도록 해준다.
v-once : 컴퍼넌트를 한번만 렌더링. 갱신이 필요없는 statless 컴퍼넌트에 사용
재사용 원칙
컴퍼넌트에 직접 데이터 전달은 props
내장 $smit 메소드로 직접 이벤트 발생가능, $emit의 발생 이벤트 이름을 커스텀 컴퍼넌트의 v-on 이벤트 이름으로 동일하게 작성시 또는 메쏘드 생성시 가능.
(예 : https://kr.vuejs.org/v2/guide/components-custom-events.html)
slot 속성을 통해 컴퍼넌트의 내용을 상황에 따라 바꿔치기 가능하게하여 재사용성 향상가능
(예 : https://kr.vuejs.org/v2/guide/components-slots.html)
v-bind:is 속성으로 동적으로 컴퍼넌트 전환 가능
v-bind:is 사용시 keep-alive 속성으로 컴퍼넌트 전환후에도 컴퍼넌트의 뷰상태 유지가능
(예 : https://kr.vuejs.org/v2/guide/components-dynamic-async.html#keep-alive-%EB%8F%99%EC%A0%81-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8)
ref 속성을 자식 컴퍼넌트등에서 정의하여 부모컴퍼넌트등에서 레퍼런스를 참조가능 (this.$refs.레퍼런스이름)
(예:https://vuejs.org/v2/api/#ref)
META TAG를 페이지별로 적절하게 수정하기 위해서 NuxtJs 의 head 속성을 오버라이드 한다. (https://vue-nuxt.gitbook.io/nuxt/tutorials/making-blog/undefined) (https://medium.com/vue-mastery/best-practices-for-nuxt-js-seo-32399c49b2e5)
https://heropy.blog/2018/01/31/sass/
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:30 (project):
No CMAKE_C_COMPILER could be found
가 나오면
Xcode Commandline Tools 가 미쳐서 그런거니
sudo xcode-select --reset
하면 됨.
물론 CMake는 최신판으로다가 받앙
GOPATH 에 대한 이해
http://amazingguni.github.io/blog/2016/05/go-chapter-2-1-%EC%84%A4%EC%B9%98_%EB%B0%8F_%EC%8B%9C%EC%9E%91
초간단 웹서버 제작
http://amazingguni.github.io/blog/2016/06/go-chapter-6-%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0
-계속 추가중-
도커안의 젠킨스 루트로 들어가서
wget -O /tmp/docker.tgz https://download.docker.com/linux/static/stable/x86_64/docker-19.03.8.tgz
tar -xzf /tmp/docker.tgz -C /tmp
mv /tmp/docker/* /usr/bin/
groupadd -o -g $DOCKER_GROUP_GID docker
usermod -g docker jenkins
슬랙에서 app추가에서 Jenkins CI를 추가함. 그러면 인터그레이션 설정토큰과 채널명,설정방법이나옴.
젠킨스에 슬랙 플러그인을 설치한다.
젠킨스설정(configure)에 가서
워크스페이스를 슬랙의 워크스페이스이름으로
인증을 kind: SectetText , Secret: 슬랙에서 준 토큰, ID: 워크스페이스이름 이름으로 저장
채널명은 알림할 채널명으로 지정
테스트해보면 메시지가 감.
젠킨스 프로젝트 설정에 가보면
빌드후조치->Slack notification 이 적당한 것들을 체크하면 빌드시에 슬랙에 문자옴
fuck-curtaincall - #13 Started by user kim (Open)
일단 Docker 에 jenkins/jenkins 이미지를 다운로드 받는다.
* 주의 kitematic 에서의 jenkins는 잘안됨
docker pull jenkins/jenkins:lts <- lastest도 괘안
받아서 기동후 쉘로 들어가서 암호찾아내서 일단 스탠다드 인스톨.
인스톨이 다 되었다면 /var/jenkins_home 폴더는 로컬폴더에 연결하고 다시 기동.
왠지 jenkins에서 nodejs 플러그인을 설치하면 될것같지만, 안된다.
그래서 젠킨스 컨테이너의 쉘을 root 권한으로 들어간다.
$ docker exec -it --user root YourContainer /bin/bash
애네들을 실행한다.
apt-get update
apt-get install -y git curl vim sudo apt-utils
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
apt-get install -y nodejs
rm -rf /var/lib/apt/lists/*
또는
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.0/install.sh | bash
를 실행해서 nvm 을 설치하고
nvm install 12.6.3
해서 node를 설치하면
/root/.nvm/versions/node/v12.16.3
이딴 폴더가 생기지만 root 폴더밑에 있어서 jenkins가 읽지 못함.
단순무식으로 v12.16.3 의 모든 내용을 /var/jenkins_home/nodes/ 밑에 복사하자.
그리고나서 젠킨스 빌드시의 execute shell 에서
cd /var/jenkins_home/workspace/Fuck-curtaincall
/var/jenkins_home/nodes/bin/npm install
/var/jenkins_home/nodes/bin/npm run build
하면 nuxtjs 가 빌드된다.
그걸 웹서버에 올리고 재가동 하면 끄읕.
참. 젠킨스설정에서
이 빌드는 매개변수가 있습니다 . 에서
매개변수 branch 기본밸류 master
하고 소스코드관리에서 branch to build 항목에서
*/${branch} 하면됨
1. nuxtjs
Dockerfile 생성후
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.war
COPY ${JAR_FILE} web-backend.war
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=local","-jar","/web-backend.war"]
#docker build --build-arg "JAR_FILE=build/libs/*.war" -t web-backend:1.0.0 .
#docker run --name hehe3 -p 8081:8081 web-backend:1.0.0
Vuejs 와 Nuxtjs 는 문서화가 잘 되어있으니까 그냥 쓰면 되고,
컴퍼넌트라는 단위로 만드는 것은 좋으나, 컴퍼넌트에 너무 많은 비지니스 로직이 들어가지 않도록 하는게 좋을거 같다.
또 컴퍼넌트에서 직접 서버와 통신하여 자료를 for 로 출력하는것은 테스트를 어렵게 만들기 때문에 되도록 Repositry 를 이용하여 컴퍼넌트에 props 나 mixin 형태로 주입(?) 하는 것이 좋다.
참고 : https://markus.oberlehner.net/blog/tight-coupling-vs-loose-coupling-in-vuejs/
혹시 화면단에서 i18n 지원이 필요하면 다음을 참고하자
https://dev.to/astagi/how-to-build-a-jamstack-multi-language-blog-with-nuxt-js-3gah
SEO 대응도 하고싶다면 이거.
https://vuedose.tips/optimize-seo-and-social-media-sharing-in-a-nuxt-blog
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration@EnableSwagger2public class SwaggerConfig {
@Bean public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any()) //모든 url 리스트 찾아내줘 스웍 .paths(PathSelectors.any()) // 모든 패스 전부. .build();
}
}
이것만으로 잘 안되서..
@Overridepublic void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/api/v2/api-docs", "/v2/api-docs");
registry.addRedirectViewController("/api/swagger-resources/configuration/ui", "/swagger-resources/configuration/ui");
registry.addRedirectViewController("/api/swagger-resources/configuration/security", "/swagger-resources/configuration/security");
registry.addRedirectViewController("/api/swagger-resources", "/swagger-resources");
}
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/api/swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
registry.addResourceHandler("/api/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");...}했더니 localhost:8080/api/swagger-ui.html 에서 보게 되었다.http://localhost:8081/swagger-api/swagger-ui.html#/