<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>쓰러지면어때일어나면그만인걸</title>
    <link>https://0andwild.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 02:53:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Dev_0andWild</managingEditor>
    <image>
      <title>쓰러지면어때일어나면그만인걸</title>
      <url>https://tistory1.daumcdn.net/tistory/5601098/attach/31ac2af2c973448f960f293427cd8bda</url>
      <link>https://0andwild.tistory.com</link>
    </image>
    <item>
      <title>Scouter JDK 17 이용 시 server 실행 문제</title>
      <link>https://0andwild.tistory.com/44</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #d44c47;&quot; data-token-index=&quot;0&quot;&gt;Scouter server sh 파일을 jdk 17 로 실행시 오류&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scouter 를 사용해보는 과정에서 JDK 17 버전에서 실행이 불가능 한 것을 확인 하였고 해당 문제를 해결 하는 방법을 공유 하고자 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 개발 시 사용중인 jdk 17 에서 scouter\server 경로의 .\startcon.bat(window os에서 실행) 을 실행 시켰을 경우 아래와 같은 에러가 나옴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;lt;Error Log&amp;gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1715613703460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;C:\Users\parkk\OneDrive\바탕 화면\scouter-all-2.20.0\scouter\server&amp;gt;java -Xmx1024m -Dadd-opens=java.base/java.lang=ALL-UNNAMED -Djdk.attach.allowAttachSelf=true -classpath ./scouter-server-boot.jar scouter.boot.Boot ./lib -console
  ____                  _
 / ___|  ___ ___  _   _| |_ ___ _ __
 \___ \ / __/   \| | | | __/ _ \ '__|
  ___) | (_| (+) | |_| | ||  __/ |
 |____/ \___\___/ \__,_|\__\___|_|
 Open Source S/W Performance Monitoring
 Scouter version 2.20.0

5월 13, 2024 11:58:52 오후 com.sun.xml.bind.v2.runtime.reflect.opt.Injector &amp;lt;clinit&amp;gt;
심각: null
java.security.PrivilegedActionException: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:573)
        at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.&amp;lt;clinit&amp;gt;(Injector.java:197)
        at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:81)
        at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:171)
        at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:285)
        at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.&amp;lt;init&amp;gt;(SingleElementNodeProperty.java:94)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
        at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:128)
        at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.&amp;lt;init&amp;gt;(ClassBeanInfoImpl.java:181)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:514)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.&amp;lt;init&amp;gt;(JAXBContextImpl.java:331)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.&amp;lt;init&amp;gt;(JAXBContextImpl.java:139)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1156)
        at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:165)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:297)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:286)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:409)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662)
        at scouter.server.Configure.&amp;lt;clinit&amp;gt;(Configure.java:78)
        at scouter.server.Logger$.&amp;lt;init&amp;gt;(Logger.scala:153)
        at scouter.server.Logger$.&amp;lt;clinit&amp;gt;(Logger.scala)
        at scouter.server.Logger.println(Logger.scala)
        at scouter.server.Main.main(Main.java:42)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at scouter.boot.Boot.main(Boot.java:45)
Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain)
        at java.base/java.lang.Class.getMethod(Class.java:2227)
        at com.sun.xml.bind.v2.runtime.reflect.opt.Injector$3.run(Injector.java:201)
        at com.sun.xml.bind.v2.runtime.reflect.opt.Injector$3.run(Injector.java:197)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)
        ... 36 more

java -cp ./boot.jar scouter.boot.Boot [./lib]
Exception in thread &quot;main&quot; java.lang.NoClassDefFoundError: Could not initialize class scouter.server.Logger$
        at scouter.server.Logger$$anonfun$1.apply$mcV$sp(Logger.scala:145)
        at scouter.server.util.ThreadScala$$anon$1.run(ThreadScala.scala:12)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ExceptionInInitializerError [in thread &quot;main&quot;]
        at scouter.server.Logger$.&amp;lt;init&amp;gt;(Logger.scala:153)
        at scouter.server.Logger$.&amp;lt;clinit&amp;gt;(Logger.scala)
        at scouter.server.Logger.println(Logger.scala)
        at scouter.server.Main.main(Main.java:42)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at scouter.boot.Boot.main(Boot.java:45)
java.lang.ExceptionInInitializerError
        at scouter.server.Logger$.&amp;lt;init&amp;gt;(Logger.scala:153)
        at scouter.server.Logger$.&amp;lt;clinit&amp;gt;(Logger.scala)
        at scouter.server.Logger.println(Logger.scala)
        at scouter.server.Main.main(Main.java:42)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at scouter.boot.Boot.main(Boot.java:45)
Caused by: java.lang.NullPointerException: Cannot invoke &quot;java.lang.reflect.Method.invoke(Object, Object[])&quot; because &quot;com.sun.xml.bind.v2.runtime.reflect.opt.Injector.defineClass&quot; is null
        at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:311)
        at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:97)
        at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:87)
        at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:171)
        at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:285)
        at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.&amp;lt;init&amp;gt;(SingleElementNodeProperty.java:94)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
        at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:128)
        at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.&amp;lt;init&amp;gt;(ClassBeanInfoImpl.java:181)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:514)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.&amp;lt;init&amp;gt;(JAXBContextImpl.java:331)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.&amp;lt;init&amp;gt;(JAXBContextImpl.java:139)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1156)
        at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:165)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:297)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:286)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:409)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662)
        at scouter.server.Configure.&amp;lt;clinit&amp;gt;(Configure.java:78)
        ... 9 more&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련 문제를 서칭하다 페이스북 스카우터 그룹에 올라온 글을 발견함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.facebook.com/groups/scouterapm/posts/3522272424754246/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.facebook.com/groups/scouterapm/posts/3522272424754246/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1715613728605&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;로그인 또는 가입하여 보기&quot; data-og-description=&quot;Facebook에서 게시물, 사진 등을 확인하세요.&quot; data-og-host=&quot;www.facebook.com&quot; data-og-source-url=&quot;https://www.facebook.com/groups/scouterapm/posts/3522272424754246/&quot; data-og-url=&quot;https://www.facebook.com/login/?next=https%3A%2F%2Fwww.facebook.com%2Fgroups%2Fscouterapm%2Fposts%2F3522272424754246%2F&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.facebook.com/groups/scouterapm/posts/3522272424754246/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.facebook.com/groups/scouterapm/posts/3522272424754246/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;로그인 또는 가입하여 보기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Facebook에서 게시물, 사진 등을 확인하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.facebook.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는 agent 실행 시 에는 발생하지 않으나 server 실행은 jdk 1.8 에서만 구동되는 것으로 보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 정상적인 실행을 위해선 jdk 1.8을 설치하고 startcon.bat 실행파일 옵션을 jdk 1.8 로 설정해줌.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715613764638&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;window 에서 파일 수정 시 (powershell 이용)
 
 notepad .\startcon.bat&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 startcon.bat 파일을 메모장으로 열어 jdk 1.8 경로를 지정&lt;/p&gt;
&lt;pre id=&quot;code_1715613833786&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(기존)
java -Xmx512m -classpath ./scouter-server-boot.jar scouter.boot.Boot ./lib -console

(변경 - jdk 1.8 경로 지정) [ 일반적으로 윈도우에서 jdk 설치 시 위치는 C:\Program Files 에 있음 ]
&quot;C:\Program Files\Eclipse Adoptium\jdk8u412-b08\bin\java&quot; -Xmx1024m -classpath ./scouter-server-boot.jar scouter.boot.Boot ./lib -console&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 사항 저장 후 다시 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715613904881&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(현재 경로)
C:\Users\parkk\OneDrive\바탕 화면\scouter-all-2.20.0\scouter\server

(server 패키지에 있는 startcon.bat 을 실행)
.\startcon.bat&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상 실행 시 다음과 같이 로그 마지막에 실행이 된 것을 확인 할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;00:12:41.874 [scouter.server.http.HttpServer] INFO org.eclipse.jetty.server.Server[444] - Started @823ms&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGSIE8/btsHpKN1GvU/z7ZTKlm1nuRiEg84pJiNy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGSIE8/btsHpKN1GvU/z7ZTKlm1nuRiEg84pJiNy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGSIE8/btsHpKN1GvU/z7ZTKlm1nuRiEg84pJiNy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGSIE8%2FbtsHpKN1GvU%2Fz7ZTKlm1nuRiEg84pJiNy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1704&quot; height=&quot;798&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy/Java</category>
      <category>Java</category>
      <category>JDK1.8</category>
      <category>jdk17</category>
      <category>scouter</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/44</guid>
      <comments>https://0andwild.tistory.com/44#entry44comment</comments>
      <pubDate>Tue, 14 May 2024 00:26:23 +0900</pubDate>
    </item>
    <item>
      <title>Garbage Collection(GC)</title>
      <link>https://0andwild.tistory.com/43</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1sWw5/btsyX0x47L3/gAeHNvgnxTHhZI4EyIZffk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1sWw5/btsyX0x47L3/gAeHNvgnxTHhZI4EyIZffk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1sWw5/btsyX0x47L3/gAeHNvgnxTHhZI4EyIZffk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1sWw5%2FbtsyX0x47L3%2FgAeHNvgnxTHhZI4EyIZffk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;Garbage Collection Concept&lt;/h2&gt;
&lt;br&gt;
GC가 이루어지는 영역은 young generation 과 old generation 으로 나뉘며 JVM 의 heap 영역에 할당된다.
young generation 은 Eden 과 2개의 survivor space 로 나뉜다.
old generation 은 old space 로 나뉜다.
&lt;br&gt;
&lt;br&gt;
young generation 이 꽉 차게 되면 minor gc 가 이루어지고, 살아남은 객체는 old 영역으로
이동을 하게 된다. old 영역은 minor 영역보다 메모리 공간이 더 많고 큰 객체나 young 영역에서 살아남은 =
객체들을 보관한다. old 영역도 young 영역에서 이루어지는 minor gc 와 마찬가지로 공간이 꽉차게 되면
garbage collecting 을 실행하게 되는데 이를 major gc 라고 한다.

&lt;br&gt;

&lt;hr&gt;
&lt;br&gt;


&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMIntS/btsyYoZWIDY/TqQhTJWCQvewxOZfJuTK21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMIntS/btsyYoZWIDY/TqQhTJWCQvewxOZfJuTK21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMIntS/btsyYoZWIDY/TqQhTJWCQvewxOZfJuTK21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMIntS%2FbtsyYoZWIDY%2FTqQhTJWCQvewxOZfJuTK21%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Young&lt;/h3&gt;
&lt;br&gt;
객체가 새로 할당되면 young generation 의 eden 영영에 할당이 이루어지고, eden 영역이
꽉 차게 되면 garbage collecting 을 실시하게 된다. 이때 아직 사용되고 있는 객체들은 survivor 영역으로 이동을
하게 된다. survivor 영역은 2개로 나뉘어져 있고, 이 중 하나는 항상 비어있는 상태로 유지가 된다.

&lt;pre&gt;&lt;code&gt;eden 영역 꽉참 -&amp;gt; garbage collecting 실시 -&amp;gt; 살아남은 객체 survivor(0 - from space) 영역으로 이동
-&amp;gt; 다시 eden 영영 꽉참 -&amp;gt; garbage collecting 실시 -&amp;gt; survivor(0 - from space) 의 살아남은 객체들을 survivor(1 - to space)로 옮긴다.
-&amp;gt; 이 같은 과정을 반복하다 survivor(1 - to space)의 영역의 살아남은 객체들은 old generation 영역으로 옮기게 된다.&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;

&lt;hr&gt;
&lt;br&gt;

&lt;h3&gt;Old&lt;/h3&gt;
&lt;br&gt;
old 영역은 young generation 영역에서 계속해서 살아남은 객체들이 넘어오는 영역이며 마찬가지로 꽉차게 되었을 때
gc 가 발생한다. 이때 발생하는 gc 가 major gc 이다. Old 영역은 young 영역보다 공간이 크기 때문에 gc가 발생하는 숫자는 적지만 major gc 는 minor gc 보다 시간이 오래 걸린다.
&lt;br&gt;
** old 영역이 JVM의 heap 영역에 할당되는 default 값은 heap 영역의 2/3 이며 young gen은 1/3을 차지하게 된다.
하지만 초기 young gen에 할당되는 공간이 적으면 적을수록 빠르게 minor gc 가 발생하고 그만큼 old 영역으로 넘어가는 객체가 많아지게 된다.
old 영역으로 객체가 빠르게 넘어오게 되면 major gc 의 발생 횟수가 많아지게 되고 이는 성능상의 문제와 연결될 수 있다. 따라서 초기에 JVM 설정을 통해 heap 공간의 young 영역의 공간 할당을 늘려주는 것이 좋다.
&lt;br&gt;

&lt;pre&gt;&lt;code&gt;-Xms, -Xmx - Heap 사이즈의 최소, 최대값
-XX:NewSize - Young Generation의 영역의 초기 사이즈
-XX:MaxNewSize - Young Generation의 최대 사이즈
-XX:NewRadio - 위와 같을 경우 Old Generation은 Young Generation의 2배의 크기를 갖는다.&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;

&lt;hr&gt;
&lt;br&gt;
Hotspot JVM 에서는 eden 영역에 객체를 빠르게 할당시키기 위해 bump the pointer 방식을 사용한다.
bump the pointer 방식은 eden 영역의 시작 주소를 가리키는 포인터를 두고, 객체를 할당할 때마다 포인터를 이동시키는 방식이다.
따라서 새로운 객체를 할당시킬 공간을 탐색하기 위해 시간을 소용하지 않고 마지막으로 할당된 객체가 가리키고 있는 pointer를 이용하여 다음공간에 바로 할당을 하개된다.
&lt;br&gt;
&lt;br&gt;
멀티쓰레드 환경에서는 객체 할당에 있어 동기화 문제가 발생할 수 있기 때문에 lock 관리를 해주어야한다. 하지만 이는 성능상의 이슈로 이어질 수 있다.
이를 해결하기 위해 Hotspot JVM 에서는 thread-local allocation buffer(TLAB) 를 사용한다. TLAB 는 각각 쓰레드마다 eden 영역의 객체를 할당하기 위한 주소를
부여해주게 되고 이를 통해 동기화 작업 필요 없이 객체를 할당할 수 있게 된다.</description>
      <category>DailyStudy/Java</category>
      <category>garbage collection</category>
      <category>GC</category>
      <category>heap</category>
      <category>Java</category>
      <category>JVM</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/43</guid>
      <comments>https://0andwild.tistory.com/43#entry43comment</comments>
      <pubDate>Sun, 22 Oct 2023 00:50:39 +0900</pubDate>
    </item>
    <item>
      <title>Oracle SQL Developer 접속 오류(The Network Adapter could not establish the connection)</title>
      <link>https://0andwild.tistory.com/42</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEIksu/btr0rhtzMqY/H820m8AvtJ5QLxPv1Ga5o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEIksu/btr0rhtzMqY/H820m8AvtJ5QLxPv1Ga5o0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEIksu/btr0rhtzMqY/H820m8AvtJ5QLxPv1Ga5o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEIksu%2Fbtr0rhtzMqY%2FH820m8AvtJ5QLxPv1Ga5o0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;275&quot; height=&quot;183&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQLD 자격증을 공부하려 다운 받았던 Oracle XE 21c Developer SQL 이 분명 어제까지만 해도 접속이 잘 되다가 오늘 접속을 하려니 다음과 같은 에러가 나왔다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;931&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J0WFK/btr0nNgfxCc/S0kWG2ynDp0VflJx8sCBDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J0WFK/btr0nNgfxCc/S0kWG2ynDp0VflJx8sCBDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J0WFK/btr0nNgfxCc/S0kWG2ynDp0VflJx8sCBDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ0WFK%2Fbtr0nNgfxCc%2FS0kWG2ynDp0VflJx8sCBDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;741&quot; height=&quot;329&quot; data-origin-width=&quot;931&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 해보니 Listner 설정 문제라길래 리스너 설정을 다시 확인해보았습니다. =(&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;오라클 리스너는 네트워크를 이용하여 클라이언트에서 오라클 서버로 연결하기 위한 오라클 네트워크 관리자이다.&lt;br /&gt;네트워크를 통한 연결은 모두 리스너가 담당을하고 리스너와 연결되기 위해선 클라이언트에 오라클 NET8이 설치되어 있고 이를 통해 접속을 해야한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;890&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v8FMf/btr0mcVaMzd/8iwsOA9V9aJA5uUhZlDGj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v8FMf/btr0mcVaMzd/8iwsOA9V9aJA5uUhZlDGj1/img.png&quot; data-alt=&quot;경로 : C:\app\사용자이름\product\21c\dbhomeXE\network\admin\sample\listener.ora&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v8FMf/btr0mcVaMzd/8iwsOA9V9aJA5uUhZlDGj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv8FMf%2Fbtr0mcVaMzd%2F8iwsOA9V9aJA5uUhZlDGj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;428&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;890&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;경로 : C:\app\사용자이름\product\21c\dbhomeXE\network\admin\sample\listener.ora&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.....??? LocalHost로 잘 잡혀있다.....?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 리스너가 잘 동작하는지 확인이 필요할 것 같네요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzrHyO/btr0okSqmqf/RkSCUS0DCmLkMRDMJBxmok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzrHyO/btr0okSqmqf/RkSCUS0DCmLkMRDMJBxmok/img.png&quot; data-alt=&quot;명령어: lsnrctl service&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzrHyO/btr0okSqmqf/RkSCUS0DCmLkMRDMJBxmok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzrHyO%2Fbtr0okSqmqf%2FRkSCUS0DCmLkMRDMJBxmok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1051&quot; height=&quot;352&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;명령어: lsnrctl service&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리스너가 동작을 하고 있지 않는것 같다....&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;lsnrctl service&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;lsnrctl status&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 리스너의&amp;nbsp; 상태를 확인이 가능합니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677078924629&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;lsnrctl help --도움말
lsnrctl status --현재 상태
lsnrctl start --시작
lsnrctl stop --중지
lsnrctl reload --재시작
lsnrctl --관리자모드 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 위의 명령어를 이용해 리스너를 기동시켜주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;983&quot; data-origin-height=&quot;257&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BxfnQ/btr0o6znwQ6/mzZbEHQtLFE5lZUmRT6YAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BxfnQ/btr0o6znwQ6/mzZbEHQtLFE5lZUmRT6YAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BxfnQ/btr0o6znwQ6/mzZbEHQtLFE5lZUmRT6YAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBxfnQ%2Fbtr0o6znwQ6%2FmzZbEHQtLFE5lZUmRT6YAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;692&quot; height=&quot;181&quot; data-origin-width=&quot;983&quot; data-origin-height=&quot;257&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;....??!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 관리자 모드로 다시 도즈언&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dy3T1J/btr0o5HfFem/6KubnMLuBHPbc8oSMXSeik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dy3T1J/btr0o5HfFem/6KubnMLuBHPbc8oSMXSeik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dy3T1J/btr0o5HfFem/6KubnMLuBHPbc8oSMXSeik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdy3T1J%2Fbtr0o5HfFem%2F6KubnMLuBHPbc8oSMXSeik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1051&quot; height=&quot;339&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;....????.....!!?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어가 먹지 않는다....?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고보니 윈도우에서 cmd 를 이용해 해당 명령어를 사용할 때&lt;b&gt; cmd 를 관리자 권한으로 실행&lt;/b&gt;시켜주어야 한다는 것을 발견했습니다....!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R3Ch7/btr0m5nWp2r/m7NRYqzf9o3VHeWgQTGaH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R3Ch7/btr0m5nWp2r/m7NRYqzf9o3VHeWgQTGaH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R3Ch7/btr0m5nWp2r/m7NRYqzf9o3VHeWgQTGaH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR3Ch7%2Fbtr0m5nWp2r%2Fm7NRYqzf9o3VHeWgQTGaH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1157&quot; height=&quot;528&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자권한으로 cmd 를 실행시킨뒤 다시 lsnrctl start !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태도 한번 체크를 해주도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5G7Ug/btr0n8EvVCe/aPuFkzNtzWRcK9tPuemSr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5G7Ug/btr0n8EvVCe/aPuFkzNtzWRcK9tPuemSr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5G7Ug/btr0n8EvVCe/aPuFkzNtzWRcK9tPuemSr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5G7Ug%2Fbtr0n8EvVCe%2FaPuFkzNtzWRcK9tPuemSr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1131&quot; height=&quot;367&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;367&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 잘 연결되었군요 ! +_+&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 cli 를 이용해 명령어로 리스너를 다루는 방법도 있지만 gui 를 통해 오라클 리스너를 실행시켜 줄 수도 있습니다 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L8WnE/btr0nNUOSbl/aqu5WoD34hwdE9U4pXGn8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L8WnE/btr0nNUOSbl/aqu5WoD34hwdE9U4pXGn8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L8WnE/btr0nNUOSbl/aqu5WoD34hwdE9U4pXGn8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL8WnE%2Fbtr0nNUOSbl%2Faqu5WoD34hwdE9U4pXGn8k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;347&quot; height=&quot;508&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;812&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lDSyv/btr0n7r5cvc/d3ZGRRtYSvKnhsjDDeq1F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lDSyv/btr0n7r5cvc/d3ZGRRtYSvKnhsjDDeq1F1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lDSyv/btr0n7r5cvc/d3ZGRRtYSvKnhsjDDeq1F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlDSyv%2Fbtr0n7r5cvc%2Fd3ZGRRtYSvKnhsjDDeq1F1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;58&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 서비스를 검색하거나 cmd 에서 services.msc 를 입력해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;903&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xLUCo/btr0mdGyl5g/EJlyXkF27MaSaacHy9Xr51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xLUCo/btr0mdGyl5g/EJlyXkF27MaSaacHy9Xr51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xLUCo/btr0mdGyl5g/EJlyXkF27MaSaacHy9Xr51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxLUCo%2Fbtr0mdGyl5g%2FEJlyXkF27MaSaacHy9Xr51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;682&quot; height=&quot;532&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;903&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 요런 인터페이스가 나오는데 Oracle 어쩌구 Listner 를 찾아서 클릭을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle sql developer 가 정상적으로 설치 되었다면 존재할겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;689&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BfBG4/btr0n7r5h2Y/Nrgt4aEv7dixsYaYDcA87K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BfBG4/btr0n7r5h2Y/Nrgt4aEv7dixsYaYDcA87K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BfBG4/btr0n7r5h2Y/Nrgt4aEv7dixsYaYDcA87K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBfBG4%2Fbtr0n7r5h2Y%2FNrgt4aEv7dixsYaYDcA87K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;445&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;689&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 요런 녀석이 나올텐데 필자는 이미 명령어로 리스너를 실행시킨 상태이기 때문에 실행 중 이라고 뜨는군요.&amp;nbsp; =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서도 시작과 중지를 할 수 있습니다. ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자 그럼 리스너도 정삭 작동을 하니 이제 다시 접속 테스트를 해보겠습니다 !&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8zx64/btr0m5g9gxU/BlMlniBriRbfU1kMVqLG5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8zx64/btr0m5g9gxU/BlMlniBriRbfU1kMVqLG5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8zx64/btr0m5g9gxU/BlMlniBriRbfU1kMVqLG5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8zx64%2Fbtr0m5g9gxU%2FBlMlniBriRbfU1kMVqLG5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;787&quot; height=&quot;611&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아주아주 잘 작동하는군요 !&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;흡족...!&amp;nbsp; *ㅁ*&lt;/b&gt;&lt;/p&gt;</description>
      <category>TroubleShooting</category>
      <category>Developer</category>
      <category>oracle</category>
      <category>SQL</category>
      <category>sqld</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/42</guid>
      <comments>https://0andwild.tistory.com/42#entry42comment</comments>
      <pubDate>Thu, 23 Feb 2023 00:47:35 +0900</pubDate>
    </item>
    <item>
      <title>오픈소스 라이브러리 배포해보기 =)</title>
      <link>https://0andwild.tistory.com/41</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;224&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tUJs6/btrVewXtcms/op5k1bTwvghWdp6ycLzZe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tUJs6/btrVewXtcms/op5k1bTwvghWdp6ycLzZe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tUJs6/btrVewXtcms/op5k1bTwvghWdp6ycLzZe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtUJs6%2FbtrVewXtcms%2Fop5k1bTwvghWdp6ycLzZe1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;224&quot; height=&quot;224&quot; data-origin-width=&quot;224&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jitpack 을 이용하여 간단하게 오픈소스 프로젝트를 배포하고 해당 디펜던시를 추가하여 정상적인 작동이 이루어지는지 확인해보도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-01-02 오후 11.34.59.png&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;1552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRbAwO/btrU7HMvmYf/qogNJhcmJdEEKbkwaXdWI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRbAwO/btrU7HMvmYf/qogNJhcmJdEEKbkwaXdWI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRbAwO/btrU7HMvmYf/qogNJhcmJdEEKbkwaXdWI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRbAwO%2FbtrU7HMvmYf%2FqogNJhcmJdEEKbkwaXdWI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;581&quot; height=&quot;329&quot; data-filename=&quot;스크린샷 2023-01-02 오후 11.34.59.png&quot; data-origin-width=&quot;2738&quot; data-origin-height=&quot;1552&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자의 경우 다음과 같이 Github을 이용하여 Public 레포지토리를 생성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 작업은 Intellij IDE 를 사용하였고 스프링 프로젝트가 아닌 Java 프로젝트로 생성을 해주었습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672670260323&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apply plugin: 'java'
apply plugin: 'maven-publish'

group 'io.github._0AndWild'
version '1.0-SNAPSHOT'

sourceCompatibility = 11
targetCompatibility = 11

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    //lombok
    compileOnly('org.projectlombok:lombok:1.18.24')
    //test code
    testImplementation('org.assertj:assertj-core:3.21.0')

}

java {
    withSourcesJar()
    withJavadocJar()
}

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
    }
}


test {
    useJUnitPlatform()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 build.gradle 은 위와 같이 설정해주었고 jitpack 의 경우 java 8 버전만 지원한다는 글들이 있지만 아래와 같이 프로젝트의 root 경로에 jitpack.yml 파일을 만들어준 후 다음과 같이 사용하고자 하는 jdk 버전을 명시해주면 사용이 가능합니다. =)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Don9b/btrVcLHlb0z/LhO8TJOkw9b588hULvmjkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Don9b/btrVcLHlb0z/LhO8TJOkw9b588hULvmjkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Don9b/btrVcLHlb0z/LhO8TJOkw9b588hULvmjkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDon9b%2FbtrVcLHlb0z%2FLhO8TJOkw9b588hULvmjkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;559&quot; height=&quot;392&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 연습용으로 만들어본 프로젝트 이기에 간단하게 특수문자 유효성을 검사해주는 validator를 만들어주었고 배포를 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672671422966&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package io.github._0AndWild;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Validator {

    /**
     * &amp;lt;pre&amp;gt;
     *  사용가능한 특수문자 이외의 특수문자가 있는지 검사하는 메서드
     * &amp;lt;/pre&amp;gt;
     * @param s 검사할 String
     * @param specialCharacters 포함가능한 특수문자, 특수문자를 []에 감싸서 입력
     * @return boolean - 통과 시 true, 포함할 수 없는 특수문자 존재 시 false
     */

    public static boolean validateSpecialCharacters(String s, String specialCharacters){
        boolean result = true;
        Pattern pattern = Pattern.compile(&quot;\\W&quot;);
        Pattern isOkPattern = Pattern.compile(specialCharacters);
        String removeEmptySpace = s.replace(&quot; &quot;, &quot;&quot;);

        for (int i = 0; i &amp;lt; removeEmptySpace.length(); i++) {
            String character = String.valueOf(removeEmptySpace.charAt(i));
            Matcher matcher = pattern.matcher(character);
            if (matcher.find()) {
                Matcher checkPattern = isOkPattern.matcher(character);
                if (!checkPattern.find()) {
                    result = false;
                    break;
                }
            }
        }
        return result;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 간단하게 코드를 짜본 후 아래처럼 테스트코드로 검증을 해보았습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672671494567&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package io.github._0AndWild;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

class ValidatorTest {

    @Nested
    class validateSpecialCharacters {
        @Test
        @DisplayName(&quot;특수문자 형식 검사 성공 케이스&quot;)
        void successCase() {

            String s = &quot;Hello Wor#ld. This is! Test+&amp;amp;&quot;;
            String isOkPattern = &quot;[!+&amp;amp;%:,^@#.]&quot;;

            boolean check = Validator.validateSpecialCharacters(s,isOkPattern);

            Assertions.assertThat(check).isEqualTo(true);
        }

        @Test
        @DisplayName(&quot;특수문자 형식 검사 실패 케이스&quot;)
        void failCase() {

            String s = &quot;Hello Wor#ld. This is! Test+&amp;amp;&quot;;
            String isOkPattern = &quot;[#.!+]&quot;;

            boolean check = Validator.validateSpecialCharacters(s,isOkPattern);

            Assertions.assertThat(check).isEqualTo(false);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 검증을 완료한 후 코드를 원격 레포지토리에 푸쉬해주었고 다음과 같이 release를 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;962&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cImMHU/btrVcNrGNXW/yrH9yp9d1jZoHl34tNFeqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cImMHU/btrVcNrGNXW/yrH9yp9d1jZoHl34tNFeqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cImMHU/btrVcNrGNXW/yrH9yp9d1jZoHl34tNFeqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcImMHU%2FbtrVcNrGNXW%2FyrH9yp9d1jZoHl34tNFeqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;472&quot; height=&quot;386&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;962&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레포지토리를 들어가면 Releases라는 부분이 있고 해당 버튼을 클릭하면 배포를 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbe8LO/btrU6YAOx8w/mYtaA4vEEFEdfDDaGv7Fh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbe8LO/btrU6YAOx8w/mYtaA4vEEFEdfDDaGv7Fh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbe8LO/btrU6YAOx8w/mYtaA4vEEFEdfDDaGv7Fh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbbe8LO%2FbtrU6YAOx8w%2FmYtaA4vEEFEdfDDaGv7Fh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;532&quot; height=&quot;395&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 태그를 이용해 버전을 명시한 후 간단한 설명을 추가하여 배포를 진행해주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;1388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPVb1Q/btrU9dLcNXr/ZeXWMgDbdTEdFR1Tayabo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPVb1Q/btrU9dLcNXr/ZeXWMgDbdTEdFR1Tayabo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPVb1Q/btrU9dLcNXr/ZeXWMgDbdTEdFR1Tayabo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPVb1Q%2FbtrU9dLcNXr%2FZeXWMgDbdTEdFR1Tayabo1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;325&quot; data-origin-width=&quot;2532&quot; data-origin-height=&quot;1388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 다음과 같이 버그를 수정한 후 다시 배포를 진행해주었습니다. ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 jitpack 사이트로 들어가 아래와 같이 자신의 github 레포지토리 url 을 검색해주세요.&lt;/p&gt;
&lt;figure id=&quot;og_1672672098376&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;JitPack | Publish JVM and Android libraries&quot; data-og-description=&quot;JitPack makes it easy to release your Java or Android library. Publish straight from GitHub or Bitbucket.&quot; data-og-host=&quot;jitpack.io&quot; data-og-source-url=&quot;https://jitpack.io/&quot; data-og-url=&quot;https://jitpack.io&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b7QB9l/hyQ82xSCnx/EQ11plwNCxHTxmqBHazgeK/img.png?width=200&amp;amp;height=200&amp;amp;face=0_0_200_200,https://scrap.kakaocdn.net/dn/pRwog/hyQ6XkE8hi/J5nVIQragbygmNQEyKXLG0/img.png?width=962&amp;amp;height=342&amp;amp;face=0_0_962_342,https://scrap.kakaocdn.net/dn/ciyDsE/hyQ8Y94PD8/KqzoKtkuuI9GqBP97CoD50/img.png?width=706&amp;amp;height=375&amp;amp;face=0_0_706_375&quot;&gt;&lt;a href=&quot;https://jitpack.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jitpack.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b7QB9l/hyQ82xSCnx/EQ11plwNCxHTxmqBHazgeK/img.png?width=200&amp;amp;height=200&amp;amp;face=0_0_200_200,https://scrap.kakaocdn.net/dn/pRwog/hyQ6XkE8hi/J5nVIQragbygmNQEyKXLG0/img.png?width=962&amp;amp;height=342&amp;amp;face=0_0_962_342,https://scrap.kakaocdn.net/dn/ciyDsE/hyQ8Y94PD8/KqzoKtkuuI9GqBP97CoD50/img.png?width=706&amp;amp;height=375&amp;amp;face=0_0_706_375');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;JitPack | Publish JVM and Android libraries&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JitPack makes it easy to release your Java or Android library. Publish straight from GitHub or Bitbucket.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jitpack.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/etbMzn/btrVf8uQ6Tp/99zN0yJBKlKwZjhOiFRtLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/etbMzn/btrVf8uQ6Tp/99zN0yJBKlKwZjhOiFRtLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/etbMzn/btrVf8uQ6Tp/99zN0yJBKlKwZjhOiFRtLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FetbMzn%2FbtrVf8uQ6Tp%2F99zN0yJBKlKwZjhOiFRtLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;563&quot; height=&quot;337&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1056&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색을하고 시간이 조금 지나면 Log 부분의 색상이 빨간색 또는 초록색으로 바뀌게 됩니다. 만약 빨간색이 뜬다면 Report 를 확인하여 주세요. 초록색이 뜬다면 정상적으로 배포가 완료된거고 이제 다른 프로젝트에서 의존성을 추가하여 사용할 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1880&quot; data-origin-height=&quot;1390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cby3jv/btrVfs797sZ/VvEmrjsvmkjvtKA63bqNI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cby3jv/btrVfs797sZ/VvEmrjsvmkjvtKA63bqNI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cby3jv/btrVfs797sZ/VvEmrjsvmkjvtKA63bqNI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcby3jv%2FbtrVfs797sZ%2FVvEmrjsvmkjvtKA63bqNI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;464&quot; data-origin-width=&quot;1880&quot; data-origin-height=&quot;1390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크롤을 조금만 아래로 내려주시면 의존성을 어떻게 추가하면 사용할 수 있는지 친절하게 설명도 나와있군요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 필자는 다른 프로젝트에서 위와 같이 의존성을 추가한 후 정상적으로 작동을 하는지 테스트를 진행해보도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSRIak/btrVexa4Zsi/IZ80MjDyQcC9c0ZS13L0e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSRIak/btrVexa4Zsi/IZ80MjDyQcC9c0ZS13L0e0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSRIak/btrVexa4Zsi/IZ80MjDyQcC9c0ZS13L0e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSRIak%2FbtrVexa4Zsi%2FIZ80MjDyQcC9c0ZS13L0e0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;202&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4wVd1/btrVcmVcho4/ikbxnSLtsownvV6lzn2YvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4wVd1/btrVcmVcho4/ikbxnSLtsownvV6lzn2YvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4wVd1/btrVcmVcho4/ikbxnSLtsownvV6lzn2YvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4wVd1%2FbtrVcmVcho4%2FikbxnSLtsownvV6lzn2YvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;706&quot; height=&quot;64&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 의존성을 추가해주었고 외부 라이브러리에 잘 다운이 되었는지 확인을 해주겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2338&quot; data-origin-height=&quot;1366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9icPf/btrVeWIrtMf/8AqxXyBzeSu4RmsI2Fkoz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9icPf/btrVeWIrtMf/8AqxXyBzeSu4RmsI2Fkoz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9icPf/btrVeWIrtMf/8AqxXyBzeSu4RmsI2Fkoz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9icPf%2FbtrVeWIrtMf%2F8AqxXyBzeSu4RmsI2Fkoz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;657&quot; height=&quot;384&quot; data-origin-width=&quot;2338&quot; data-origin-height=&quot;1366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 잘 받아와졌군요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhEE2W/btrVeckuvVe/Rxd1f9MG8CxqmHYuvbPzKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhEE2W/btrVeckuvVe/Rxd1f9MG8CxqmHYuvbPzKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhEE2W/btrVeckuvVe/Rxd1f9MG8CxqmHYuvbPzKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhEE2W%2FbtrVeckuvVe%2FRxd1f9MG8CxqmHYuvbPzKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1580&quot; height=&quot;234&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 간단하게 컨트롤러를 하나 만들어주고 포스트맨으로 작동을 확인해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허용가능하게 할 특수문자를 대괄호로 감싼 후 테스트를 진행해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ev60n/btrU8EB5HF5/gEMhKiwx7EMzzrYSLOHRaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ev60n/btrU8EB5HF5/gEMhKiwx7EMzzrYSLOHRaK/img.png&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;798&quot; data-is-animation=&quot;false&quot; width=&quot;445&quot; height=&quot;283&quot; style=&quot;width: 52.8676%; margin-right: 10px;&quot; data-widthpercent=&quot;53.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ev60n/btrU8EB5HF5/gEMhKiwx7EMzzrYSLOHRaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEv60n%2FbtrU8EB5HF5%2FgEMhKiwx7EMzzrYSLOHRaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1256&quot; height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnQ9Eo/btrValWxroT/90dz9K5QW1y6Iee4CNYcik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnQ9Eo/btrValWxroT/90dz9K5QW1y6Iee4CNYcik/img.png&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;700&quot; data-is-animation=&quot;false&quot; width=&quot;406&quot; height=&quot;297&quot; data-widthpercent=&quot;46.51&quot; style=&quot;width: 45.9696%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnQ9Eo/btrValWxroT/90dz9K5QW1y6Iee4CNYcik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnQ9Eo%2FbtrValWxroT%2F90dz9K5QW1y6Iee4CNYcik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;958&quot; height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 간단하게 테스트까지 정상적으로 작동하는 것을 확인하였습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상으로 Jitpack 을 활용한 라이브러리 생성과 배포 테스트까지 진행해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 새해에는 좋은 일만 가득하고 행복한 하루 보내시길 바랍니다. =)&lt;/p&gt;</description>
      <category>DailyStudy/Spring</category>
      <category>Jitpack</category>
      <category>라이브러리</category>
      <category>오픈소스</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/41</guid>
      <comments>https://0andwild.tistory.com/41#entry41comment</comments>
      <pubDate>Tue, 3 Jan 2023 00:15:02 +0900</pubDate>
    </item>
    <item>
      <title>Junit Repository Test 에러( Error creating bean with name 'dataSource')</title>
      <link>https://0andwild.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단위테스트를 진행하던중 repository test 시 문제 발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bseVDf/btrTLIF68Nx/WOvyrnLxngXOLxhmI4wbP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bseVDf/btrTLIF68Nx/WOvyrnLxngXOLxhmI4wbP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bseVDf/btrTLIF68Nx/WOvyrnLxngXOLxhmI4wbP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbseVDf%2FbtrTLIF68Nx%2FWOvyrnLxngXOLxhmI4wbP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;520&quot; height=&quot;277&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 DB는 이중화가 되어있는 상태에서 MariaDB를 사용하고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Repository Test를 할 때 H2 인메모리 DB는 진행중인 프로젝트의 DB설정과 맞지않아 사용할 수 없는 상태이기에 현재 사용중인 물리DB를 사용하여 테스트를 진행하기 위해 @AutoConfigureTestDatabase 의 replace.none을 설정하여(기본값은 ANY) 연결시켜주려 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@DataJpaTest 어노테이션을 타고 들어가면 @Transactional 이 존재하믄로 따로 명시해주지 않음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정을 진행하고 테스트를 진행하였을 때 아래와 같은 에러가 발생함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Failed to load ApplicationContext java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248) at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:283) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272) at java.base/java.util.Optional.orElseGet(Optional.java:369) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271) at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94) at com.sun.proxy.$Proxy5.stop(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193) at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60) at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71) at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69) at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at app//org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at app//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) at app//org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) at app//org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at app//org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) at app//org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at app//org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90) ... 88 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at app//org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at app//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) at app//org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ... 108 more Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ... 122 more Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:182) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:123) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:48) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:90) at java.base@11.0.17/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base@11.0.17/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base@11.0.17/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base@11.0.17/java.lang.reflect.Method.invoke(Method.java:566) at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 123 more&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Failed to load ApplicationContext java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248) at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:283) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272) at java.base/java.util.Optional.orElseGet(Optional.java:369) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271) at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79) at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94) at com.sun.proxy.$Proxy5.stop(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193) at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60) at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71) at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69) at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at app//org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at app//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) at app//org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) at app//org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at app//org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) at app//org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at app//org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90) ... 88 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at app//org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at app//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at app//org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) at app//org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ... 108 more Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ... 122 more Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class at app//org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:182) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:123) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:48) at app//org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:90) at java.base@11.0.17/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base@11.0.17/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base@11.0.17/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base@11.0.17/java.lang.reflect.Method.invoke(Method.java:566) at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 123 more&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 에러로그를 살펴보면 dataSource 빈을 생성하는데 실패하였다고 뜨는데 현재 연결하고자 하는 DB와의 연결에 문제가 생긴것으로 보임.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gradle설정과 yml 파일 설정을 살펴보았을 때 DB에 대한 설정은 모두 올바르게 되어 있는 상태이고 프로젝트 실행 및 포스트맨으로 POST 테스트를 해보았을 때 DB에도 값이 정상적으로 들어오는 것을 확인하였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결법을 찾아보았지만 대부분 gradle의존성 및 yml 의 DB설정이 잘못되었거나, @AutoConfigureTestDataBase의 Replace설정을 제대로 해주지 않아 기본값인 ANY를 사용하게 되고 H2 인메모리를 사용하게되어 그렇다는 것이었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위 해결법들은 현재의 설정에서 모두 정상적으로 설정이 되어 있는 상태였음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;(해결방법)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF2JtE/btrTLFWVFYC/yQ9ugikTtKGMnc2X6mX0Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF2JtE/btrTLFWVFYC/yQ9ugikTtKGMnc2X6mX0Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF2JtE/btrTLFWVFYC/yQ9ugikTtKGMnc2X6mX0Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF2JtE%2FbtrTLFWVFYC%2FyQ9ugikTtKGMnc2X6mX0Hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;749&quot; height=&quot;336&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@DataJPATest 어노테이션을 빼주고 @SpringBootTest, @AutoConfigureTestEntityManager 어노테이션으로 교체해주고 테스트를 하였을 때 정상적으로 테스트가 진행되었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bewrzf/btrTNZUIMJi/NyZlrjknovo3kPaeDHRCw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bewrzf/btrTNZUIMJi/NyZlrjknovo3kPaeDHRCw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bewrzf/btrTNZUIMJi/NyZlrjknovo3kPaeDHRCw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbewrzf%2FbtrTNZUIMJi%2FNyZlrjknovo3kPaeDHRCw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;213&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;@DataJpaTest ?&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;@DataJpaTest 는 아래와 같이 오직 JPA 테스트와 연관된 config만 적용을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;713&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/riKNA/btrTK5uPXvM/BnqxjbwLxqMAd6Pl7qdyVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/riKNA/btrTK5uPXvM/BnqxjbwLxqMAd6Pl7qdyVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/riKNA/btrTK5uPXvM/BnqxjbwLxqMAd6Pl7qdyVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FriKNA%2FbtrTK5uPXvM%2FBnqxjbwLxqMAd6Pl7qdyVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;406&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;713&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@DataJpaTest 는 @AutoConfigureTestDatabase 가 디폴트로 잡혀 있어 설정해놓은 물리DB 등이 아닌 인메모리 DB를 사용하여 Test를 진행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 현재 사용중인 물리 DB를 그대로 사용하고자 한다면 @AutoConfigureTestDatabase 의 설정을 (replace=AutoConfigureTestDatabase.NONE) 으로 하면 인메모리 DB가 아닌 물리 DB를 사용하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;그럼 @SpringBootTest는 어떤걸까?&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAIMVU/btrTPi0Msq8/rEkf5Iku6MtdPR1CPSawG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAIMVU/btrTPi0Msq8/rEkf5Iku6MtdPR1CPSawG1/img.png&quot; data-alt=&quot;(일반적으로 통합테스트 시 사용)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAIMVU/btrTPi0Msq8/rEkf5Iku6MtdPR1CPSawG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAIMVU%2FbtrTPi0Msq8%2FrEkf5Iku6MtdPR1CPSawG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;189&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(일반적으로 통합테스트 시 사용)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@SpringBootTest 어노테이션은 설정해놓은 config, context, components를 모두 로드하고 DataSource bean을 그대로 사용한다.&lt;/li&gt;
&lt;li&gt;@DataJpaTest 어노테이션과 달리 @Transactional을 포함하고 있지않아 테스트할 때마다 DB가 롤백되지 않기 때문에 @Transactional 을 추가로 달아주어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@AutoConfigureTestEntityManager&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;@TestEntityManager&lt;/span&gt; 를 사용하면 persist, flush, find 등과 같은 EntityManager 에 있는 메소드들을 제공해주어 JPA 테스트를 할 수 있게 해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgO24F/btrTPQo9hqH/2dpf3kyPcAriZvf43CwmX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgO24F/btrTPQo9hqH/2dpf3kyPcAriZvf43CwmX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgO24F/btrTPQo9hqH/2dpf3kyPcAriZvf43CwmX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgO24F%2FbtrTPQo9hqH%2F2dpf3kyPcAriZvf43CwmX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;531&quot; height=&quot;273&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 문제는 설정되어 있는 dataSource를 @JPADataTest 로 하였을 때 정상적으로 불러오지 못하여 위와 같이 임시 방편으로 해결을 하였음.&lt;/p&gt;</description>
      <category>TroubleShooting</category>
      <category>JUnit</category>
      <category>RepositoryTest</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/40</guid>
      <comments>https://0andwild.tistory.com/40#entry40comment</comments>
      <pubDate>Fri, 16 Dec 2022 14:36:17 +0900</pubDate>
    </item>
    <item>
      <title>웹(Web) 이란?</title>
      <link>https://0andwild.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CkXlP/btrRMEq7YG7/kIVe180PeXKHdtZL3KQF40/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CkXlP/btrRMEq7YG7/kIVe180PeXKHdtZL3KQF40/img.jpg&quot; data-alt=&quot;https://medium.com/web-design-online-marketing/difference-between-web-2-0-and-web-1-0-1d33e1e049f9&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CkXlP/btrRMEq7YG7/kIVe180PeXKHdtZL3KQF40/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCkXlP%2FbtrRMEq7YG7%2FkIVe180PeXKHdtZL3KQF40%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;357&quot; height=&quot;184&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;161&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://medium.com/web-design-online-marketing/difference-between-web-2-0-and-web-1-0-1d33e1e049f9&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;웹의 개념&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;World Wide Web&lt;/b&gt; 을 말하며 &lt;b&gt;WWW&lt;/b&gt; 또는 &lt;b&gt;W3&lt;/b&gt; 라고도 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹은 인터넷에 연결된 사용자들끼리 서로 통신을 하며 정보를 공유할 수 있는 공간을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;웹의 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹은 텍스트, 이미지, 영상, 소리 등을 하이퍼텍스트(hypertext) 방식으로 연결하여 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;하이퍼 텍스트(Hypertext) 란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tOUjS/btrRM0m5rJY/DR1NaVyxgOq1ME92kWuj7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tOUjS/btrRM0m5rJY/DR1NaVyxgOq1ME92kWuj7k/img.png&quot; data-alt=&quot;https://poizon.tistory.com/23&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tOUjS/btrRM0m5rJY/DR1NaVyxgOq1ME92kWuj7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtOUjS%2FbtrRM0m5rJY%2FDR1NaVyxgOq1ME92kWuj7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;328&quot; height=&quot;246&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://poizon.tistory.com/23&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하이퍼텍스트는 건너편의,초월,과도한 이라는 뜻을 가진 hyper와 text 를 합성하여 만들어진 단어입니다. 인터넷과 결합하여 HTML의 주된 기술로 사용이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하면 우리가 어떤 페이지 내에서 하이퍼링크가 걸려 있는 버튼을 클릭하거나 주소를 클릭하면 해당 페이지로 이동하는 것을 말하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 우리는 웹상에서 작성자의 의도대로가 아닌 사용자의 자유에 따라 웹 서핑을 하며 새로운 정보를 습득하게 되죠. 이부분이 기존 아날로그 방식의 순차적인 지식의 습득과는 다른점이 아닐까 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;웹의 구성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹에서는 HTML로 작성된 하이퍼텍스트 문서를 웹 페이지 라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 웹페이지들 중 서로 관련된 웹페이지들의 집합을 웹사이트라고 하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;웹의 발전&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1989년 팀 버너스리가 연구원 간에 아이디어를 주고받을 때 항상 전자 우편이나 파일을 통해 주고받는 것이 비효율적이라고 생각하여 제안한 웹은 공통된 공간에 각자의 정보를 올리고 관리할 수 있는 일종의 정보 관리 시스템에서 시작되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqlxAs/btrRMUHfBn0/wWKq1LQlykF56wUdz33Lvk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqlxAs/btrRMUHfBn0/wWKq1LQlykF56wUdz33Lvk/img.jpg&quot; data-alt=&quot;https://enlear.academy/web-1-0-vs-web-2-0-vs-web-3-0-e428cfe09dde&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqlxAs/btrRMUHfBn0/wWKq1LQlykF56wUdz33Lvk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqlxAs%2FbtrRMUHfBn0%2FwWKq1LQlykF56wUdz33Lvk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;527&quot; height=&quot;295&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://enlear.academy/web-1-0-vs-web-2-0-vs-web-3-0-e428cfe09dde&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Web 1.0&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹의 초기인 web 1.0 에서는 사용자가 웹 사이트에서 미리 분류하고 정리해 놓은 자료들만을 일방적으로 전달받아야 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Web 2.0&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web 2.0 부터는 사용자가 직접 정보를 생산하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게시판, 블로그, 댓글, 위키백과 등 사용자가 참여를하여 만들어나가고 이 정보들을 공유하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beiOh2/btrRMAJbn70/L5ZXKcm1qjsJ89C1q7EaK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beiOh2/btrRMAJbn70/L5ZXKcm1qjsJ89C1q7EaK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beiOh2/btrRMAJbn70/L5ZXKcm1qjsJ89C1q7EaK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeiOh2%2FbtrRMAJbn70%2FL5ZXKcm1qjsJ89C1q7EaK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;367&quot; height=&quot;417&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web 1.0 과의 가장큰 차이점은 단순히 만들어져 있는 정보를 볼 수 만 있는 것이 아닌 사용자가 추가적인 정보를 생산해내고 이를 공유해나가며 서로서로 소통을 하게 된 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 일상에서 정보를 검색하고 커뮤니티 서비스에서 사람들과 소통을 하며 정보를 교류 하는 것들이 모두 web 2.0 의 기술 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web 1.0과 web 2.0을 분리해서 생각을 하는 것 보단 이 web의 생태계가 확장되었다고 생각을 하면 좋을 것 같습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 필자가 글을 작성하는 순간에도 수 많은 데이터(정보)가 생성되고 있고 우리는 그 정보의 늪에 빠져있죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 web 3.0으로 넘어가보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Web 3.0&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 떠오르고 있는 주제인 web 3.0은 web 2.0과 비교하자면 좀 더 고도화된 web이라고 생각을 하면 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 특성을 이해하고 분석하여 이에 맞는 맞춤형 정보를 사용자에게 제공하는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이렇게만 본다면 사실 web 2.0과 큰 특징이 없어보이지만 web 3.0의 가장 핵심적인 특징은 바로 탈중앙화에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmIVQ6/btrRMU1EClY/kWaE22UEtV21Wqywtjk26K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmIVQ6/btrRMU1EClY/kWaE22UEtV21Wqywtjk26K/img.jpg&quot; data-alt=&quot;https://www.irsglobal.com/bbs/rwdboard/14077&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmIVQ6/btrRMU1EClY/kWaE22UEtV21Wqywtjk26K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmIVQ6%2FbtrRMU1EClY%2FkWaE22UEtV21Wqywtjk26K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;317&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.irsglobal.com/bbs/rwdboard/14077&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 web 2.0에서는 크리에이터 즉, 사용자가 만들어네 정보(=데이터)는 만든 장소(=플랫폼)에 소유권이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 유튜브에 동영상을 올리면 실질적인 해당 동영상에 대한 권리와 소유권은 유튜브라는 플랫폼이 가지게 되는거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 web 3.0에서는 이러한 중앙화에서 벗어나 사용자가 자신이 만든 정보에 대해 소유권을 가지게 되는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 핵심 기술의 근간에는 블록체인이 있고 이를 통해 탈중앙화를 하는 것 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 2.0에서 사용자 간 연결은 중개자인 플랫폼을 통해서만 가능했기 때문에 플랫폼이 갖는 권력이 존재했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인은 이러한 방식과 달리 중앙 서버없이 노드(Node)들이 자율적으로 연결되는 P2P(Peer to Peer)방식을 기반으로 각 노드에 데이터를 분산 저장하는 데이터 분산처리 기술입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인에서의 데이터는 불특정 다수의 노드에 의해 관리되기 때문에 중앙관리자가 존재하지 않고 이를통해 분산화된 블록체인 플랫폼을 통해 데이터를 암호화하고 개인이 데이터를 소유할 수 있게 함으로써 중앙의 통제로부터 자유로워질 수 있는겁니다.=)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web 3.0으로의 변화는 이미 시작이 되었습니다. web 3.0이라는 단어가 단순히 마케팅 용어일 수&amp;nbsp; 있지만 플랫폼 독점의 문제점을 해결하기 위한 탈중앙화 기술이 계속되는 도전과 실패를 통해 언젠가 web 2.0이 그랬듯 우리 삶의 일부가 될 것 같다는 생각이 듭니다. =)&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy</category>
      <category>web</category>
      <category>WEB 1.0</category>
      <category>Web 2.0</category>
      <category>WEB 3.0</category>
      <category>블록체인</category>
      <category>탈중앙화</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/39</guid>
      <comments>https://0andwild.tistory.com/39#entry39comment</comments>
      <pubDate>Mon, 21 Nov 2022 20:38:55 +0900</pubDate>
    </item>
    <item>
      <title>Jenkins&amp;amp;Springboot CI/CD 정리 마지막(4) [Gitea &amp;amp; Sonar-bot]</title>
      <link>https://0andwild.tistory.com/38</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RSCsK/btrQY1of2Zb/HIx6eJFPjJg0GpBnyRCvtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RSCsK/btrQY1of2Zb/HIx6eJFPjJg0GpBnyRCvtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RSCsK/btrQY1of2Zb/HIx6eJFPjJg0GpBnyRCvtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRSCsK%2FbtrQY1of2Zb%2FHIx6eJFPjJg0GpBnyRCvtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span&gt;Jenkins&amp;amp;Springboot CI/CD 정리(4) &amp;lt;Sonar-bot&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgeXdd/btrQ0GC7r0g/xdqAgj5NBU1YwNNpekc3A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgeXdd/btrQ0GC7r0g/xdqAgj5NBU1YwNNpekc3A0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgeXdd/btrQ0GC7r0g/xdqAgj5NBU1YwNNpekc3A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgeXdd%2FbtrQ0GC7r0g%2FxdqAgj5NBU1YwNNpekc3A0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;477&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3편에 이어 Jenkins CI/CD 정리 시리즈 마지막 4편을 작성해볼까 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마지막 편은 오픈소스인 Sonar-bot 과 Community-branch-plugin 을 이용하여 SonarQube의 분석 결과를 Gitea의 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PR Comment로 남겨주는 작업입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번 편은 Sonar-bot이 Gitea를 사용하는 경우에만 해당하며 그 외에 깃헙을 사용하는경우 Community-branch-plugin 설치만 참고를 하시면 좋을 것 같습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선 Sonar-bot 을 Docker Container 로 띄워 사용을 하게 되었는데 그 이유에 대해 말씀을 드리도록 하겠습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SonarQube 에는 Github, Gitlab, Azure, Bitbucket 등 을 지원하여 분석 결과를 PR comment 로 남기게 하는 기능을 지원하고 있습니다. 하지만 현재 필자가 사용하고 있는 Gitea의 경우 SonarQube Community의 공식 답변에도 Gitea는 지원을 하지 않고 있는 것으로 나옵니다. =(&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그래서 이부분에 대해 연결할 방법을 찾다 한 Gitea의 project를 보았고 Sonar-bot이라는 오픈소스 프로젝트로 Gitea와의 연결을 지원하게 해주는 것을 발견 하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선 Sonar-bot을 사용하기 위해선 SonarQube 내의 PR 설정을 해야 하지만 SonarQube는 이 기능을 유료버전인 Developer 또는 Enterprise 버전이 필요합니다. 이 기능을 무료로 사용하기 위한 플러그인이 Community-branch-plugin 이며 이것 또한 오픈소스 프로젝트로 구성되어져 있습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Gitea가 아니더라도 Github, Gitlab 등 도 SonarQube의 PR Comment 관련 작업을 무료로 사용하기 위해선 Community-branch-plugin이 필요로 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 필자가 겪었던 트러블과&amp;nbsp; 트러블 슈팅을 하였던 과정들을 모두 설명을 하며 Sonar-bot 연결을 완성해보도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;SonarQube 버전과 Community-branch-plugin 버전&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 구축을 하며 경험을 한 것을 토대로 작성을 하다보니&lt;span&gt; SonarQube&lt;/span&gt;버전과 Community-branch-plugin의 &lt;span&gt;jar&lt;/span&gt;파일의 버전에 혼동이 올 수 있어 미리 필자가 사용한 &lt;span&gt;SonarQube &lt;/span&gt;버전과 &lt;span&gt;Sonarqube Community Branch Plugin &lt;/span&gt;설치시 다운받는 &lt;span&gt;jar&lt;/span&gt;파일의 버전을 먼저 말씀드리도록 하겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;필자의 경우 &lt;span&gt;SornarQube&lt;/span&gt;와 &lt;span&gt;Sonarqube Community Branch Plugin &lt;/span&gt;사이 연동에 있어 &lt;span&gt;SonarQube &lt;/span&gt;버전 문제가 발생하여 &lt;span&gt;SonarQube&lt;/span&gt;는 &lt;span&gt;8.4.2&lt;/span&gt;버전&lt;span&gt;, Sonarqube Community Branch Plugin &lt;/span&gt;설치시 다운로드 받아야 할 &lt;span&gt;jar&lt;/span&gt;파일은 &lt;span&gt;1.5.0 &lt;/span&gt;버전을 다운 받았습니다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(Flow&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. Gitea feature branch&lt;/span&gt;에서 &lt;span&gt;dev branch&lt;/span&gt;로 &lt;span&gt;pr&lt;/span&gt;을 날리고 모든 코드리뷰 후 merge&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2. Jenkins CI&lt;/span&gt;를 통해 &lt;span&gt;sonarqube analysis &amp;amp; sonarqube qualitygate job&lt;/span&gt;을 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3. Sonarqube&lt;/span&gt;의 분석내용을 웹훅을 통해 &lt;span&gt;Sonar-bot&lt;/span&gt;으로 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4. Sonarbot&lt;/span&gt;에서 &lt;span&gt;Gitea&lt;/span&gt;로 분석내용을 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 &lt;span&gt;Sonarqube&lt;/span&gt;에서 위의 내용을 적용시키려면 두 가지 방법이 존재합니다&lt;span&gt;. &lt;/span&gt;유료버전인&lt;span&gt; Developer Edition&lt;/span&gt;을 사용하거나 오픈소스 &lt;span&gt;Plugin&lt;/span&gt;을 직접 설치 및 설정하여 사용하는 방법이 있습니다&lt;span&gt;. &lt;/span&gt;필자의 경우 무료로 사용을 위해 &lt;span&gt;Sonarqube Community Branch Plugin&lt;/span&gt;을 사용하여 진행해보도록 하겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;span&gt;Sornaqube &lt;/span&gt;버전에 맞는 &lt;span&gt;Sonarqube Community Branch Plugin&lt;/span&gt;을 설치해주도록 합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 링크를 통해&lt;span&gt; plugin jar&lt;/span&gt;파일을 다운받도록 하겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668189465638&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and pull request decoration in the Comm&quot; data-og-description=&quot;A plugin that allows branch analysis and pull request decoration in the Community version of Sonarqube - GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; data-og-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cas8FR/hyQxKdJyx9/Z9oxhiEKV9jQTOfQ95JWJ1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cas8FR/hyQxKdJyx9/Z9oxhiEKV9jQTOfQ95JWJ1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and pull request decoration in the Comm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A plugin that allows branch analysis and pull request decoration in the Community version of Sonarqube - GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;여기부터는 필자가 겪은 트러블에 대한 내용입니다 설치방법만 참고만 해주세요 !&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sonar-bot 설치방법과 셋팅 방법은 동일하니 이부분만 동일하게 수행해주시길 바랍니다. =)&lt;/b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9lJdO/btrQZQTSOmw/xd3lmIM7M3aVpmMNQoRRU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9lJdO/btrQZQTSOmw/xd3lmIM7M3aVpmMNQoRRU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9lJdO/btrQZQTSOmw/xd3lmIM7M3aVpmMNQoRRU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9lJdO%2FbtrQZQTSOmw%2Fxd3lmIM7M3aVpmMNQoRRU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;79&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 처음 시도를 하였을 때&amp;nbsp;&lt;span&gt;SonarQube&lt;/span&gt;를 &lt;span&gt;9.7&lt;/span&gt;버전으로 사용하고 있었기 때문에 &lt;span&gt;1.12.0&lt;/span&gt;버전의 최신버전 &lt;span&gt;jar&lt;/span&gt;파일을 다운받아주었습니다. ()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;459&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZdPKr/btrQ2fdJAmb/SA8VSEQTXXLFVRuH5K1CXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZdPKr/btrQ2fdJAmb/SA8VSEQTXXLFVRuH5K1CXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZdPKr/btrQ2fdJAmb/SA8VSEQTXXLFVRuH5K1CXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZdPKr%2FbtrQ2fdJAmb%2FSA8VSEQTXXLFVRuH5K1CXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;459&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;459&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 jar 파일을 &lt;span&gt;SonarQube&lt;/span&gt;의 &lt;b&gt;&lt;span&gt;extensions/plugin &lt;/span&gt;&lt;/b&gt;디렉토리 안에 넣어주어야 합니다&lt;span&gt;. &lt;/span&gt;필자의 경우 도커 컨테이너로 &lt;span&gt;SonarQube&lt;/span&gt;를 띄우고 있기 때문에 다음과 같이 컨테이너 내부에 접속하여 위치를 확인해보았습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCnrWQ/btrQZtdyYK5/1VKT3BY1JLpU0Ie2V7GOSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCnrWQ/btrQZtdyYK5/1VKT3BY1JLpU0Ie2V7GOSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCnrWQ/btrQZtdyYK5/1VKT3BY1JLpU0Ie2V7GOSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCnrWQ%2FbtrQZtdyYK5%2F1VKT3BY1JLpU0Ie2V7GOSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;50&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668189607069&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker cp C:\Users\Bryant\Desktop\sonar-plugin\sonarqube-community-branch-plugin-1.12.0.jar 8d08b007a19b:opt/sonarqube/extensions/plugins&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬환경의 파일을 위와 같은 명령어로 &lt;span&gt;SonarQube&lt;/span&gt;의 컨테이너 디렉토리 경로 안으로 붙여넣기를 진행해주었습니다&lt;span&gt;. &lt;/span&gt;도커에서는 파일을 전송하려할 때 &lt;span&gt;cp &lt;/span&gt;명령어를 사용합니다&lt;span&gt;. =)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(필자의 경우 SonarQube를 로컬환경인 윈도우 운영체제에서 컨테이너를 띄운 상태입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 위의 명령어를 입력하였을 때&lt;b&gt;&lt;span&gt; copying between containers is not supported&amp;nbsp;&lt;/span&gt;&lt;/b&gt;라는 에러가 나왔는데요&lt;span&gt;. &lt;/span&gt;이부분은 &lt;span&gt;Stackoverflow&lt;/span&gt;의 글을 참고해보니 필자의 경우 &lt;b&gt;윈도우 환경에서 도커 컨테이너를 띄우고 있는데 경로표시에 있어 &lt;span&gt;C:/ &lt;/span&gt;에서 &lt;span&gt;C&lt;/span&gt;를&lt;span&gt;: &lt;/span&gt;를 컨테이너 이름으로 인식할 수도 있다고 하네요&lt;span&gt;. =)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;46&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQDl8/btrQZ4j1zni/FiKQWdTOxn5YT9skdXJrM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQDl8/btrQZ4j1zni/FiKQWdTOxn5YT9skdXJrM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQDl8/btrQZ4j1zni/FiKQWdTOxn5YT9skdXJrM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQDl8%2FbtrQZ4j1zni%2FFiKQWdTOxn5YT9skdXJrM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;46&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668189943137&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker cp &quot;C:\Users\Bryant\Desktop\sonar-plugin\sonarqube-community-branch-plugin-1.12.0.jar&quot; 8d08b007a19b:opt/sonarqube/extensions/plugins&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다음과 같이 &lt;span&gt;C: 로 시작하는 &lt;/span&gt;경로 부분을 &lt;span&gt;&amp;ldquo; &amp;ldquo; &lt;/span&gt;로 묶어주어 해결하였습니다&lt;span&gt;. =)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmJkHI/btrQ0YQ6mfc/DxRTYCO8bYJtq4iRRDi1jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmJkHI/btrQ0YQ6mfc/DxRTYCO8bYJtq4iRRDi1jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmJkHI/btrQ0YQ6mfc/DxRTYCO8bYJtq4iRRDi1jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmJkHI%2FbtrQ0YQ6mfc%2FDxRTYCO8bYJtq4iRRDi1jk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;277&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Sonarqube &lt;/span&gt;컨테이너 내부에 들어와 확인을 하였을 때 정상적으로 &lt;span&gt;jar &lt;/span&gt;파일이 들어온 것을 확인하였습니다&lt;span&gt;. =)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 해주어야 할 일은&lt;span&gt; sonar.properties&lt;/span&gt;를 통해&lt;span&gt; SonarQube&lt;/span&gt;의 설정을 변경해주어야 합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668190025800&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=web
sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=ce&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 맨 뒤에 &lt;span&gt;jar&lt;/span&gt;파일의 버전을 자신이 &lt;span&gt;SonarQube&lt;/span&gt;버전에 맞추어 다운 받은 &lt;span&gt;jar&lt;/span&gt;파일의 버전과 동일하게 입력하여 주시면 됩니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFB3js/btrQ1gKOfI1/v7haHPK9z3eXKuWPKvFZOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFB3js/btrQ1gKOfI1/v7haHPK9z3eXKuWPKvFZOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFB3js/btrQ1gKOfI1/v7haHPK9z3eXKuWPKvFZOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFB3js%2FbtrQ1gKOfI1%2Fv7haHPK9z3eXKuWPKvFZOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;159&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 위 설정을 컨테이너 내에 접속하여 직접 입력하는 방법도 있겠지만 필자의 경우&lt;span&gt; Sonar.properties&lt;/span&gt;를 &lt;span&gt;Jenkins&lt;/span&gt;에서 관리하고 있기 때문에 위 설정 내용을 다음과 같이 &lt;span&gt;jenkins&lt;/span&gt;에 추가해주었습니다&lt;span&gt;. 다른 방식으로는 프로젝트 내에 sonar.properties 를 만들어 관리하거나 Jenkinsfile에 Sonar-Scanner Stage부분에서 직접 명시를 할 수 도 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;976&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPO2N6/btrQZ4dgnqi/L8kXODBoIQvvjoGnakoRdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPO2N6/btrQZ4dgnqi/L8kXODBoIQvvjoGnakoRdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPO2N6/btrQZ4dgnqi/L8kXODBoIQvvjoGnakoRdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPO2N6%2FbtrQZ4dgnqi%2FL8kXODBoIQvvjoGnakoRdK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;976&quot; height=&quot;107&quot; data-origin-width=&quot;976&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트를 위해&lt;span&gt; SonarQube &lt;/span&gt;컨테이너를 재시작 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ6utr/btrQZyZ7wLZ/fveA5VzLyp1Z7JZw6e47Ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ6utr/btrQZyZ7wLZ/fveA5VzLyp1Z7JZw6e47Ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ6utr/btrQZyZ7wLZ/fveA5VzLyp1Z7JZw6e47Ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ6utr%2FbtrQZyZ7wLZ%2FfveA5VzLyp1Z7JZw6e47Ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;315&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재시작을 해주었고 위와 같이 &lt;span&gt;Marketplace&lt;/span&gt;에 &lt;span&gt;Community Branch Plugin&lt;/span&gt;이 잘 설치된 것을 확인할 수 있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;Sonar-bot &lt;/span&gt;설치 및 셋팅&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 아래 링크를 통해 프로젝트 파일을 다운받아줍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668190326842&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;gitea-sonarqube-bot&quot; data-og-description=&quot;Decorate Gitea Pull Requests with SonarQube analysis results&quot; data-og-host=&quot;codeberg.org&quot; data-og-source-url=&quot;https://codeberg.org/justusbunsi/gitea-sonarqube-bot&quot; data-og-url=&quot;https://codeberg.org/justusbunsi/gitea-sonarqube-bot&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/80BOj/hyQxOf9jiB/Fam5vqj1UDEdN4CofZwFdk/img.png?width=290&amp;amp;height=290&amp;amp;face=0_0_290_290&quot;&gt;&lt;a href=&quot;https://codeberg.org/justusbunsi/gitea-sonarqube-bot&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://codeberg.org/justusbunsi/gitea-sonarqube-bot&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/80BOj/hyQxOf9jiB/Fam5vqj1UDEdN4CofZwFdk/img.png?width=290&amp;amp;height=290&amp;amp;face=0_0_290_290');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;gitea-sonarqube-bot&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Decorate Gitea Pull Requests with SonarQube analysis results&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;codeberg.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;171&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vyaox/btrQ1e7hHfw/i9wVRl9hKqfD6UG4RqXlsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vyaox/btrQ1e7hHfw/i9wVRl9hKqfD6UG4RqXlsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vyaox/btrQ1e7hHfw/i9wVRl9hKqfD6UG4RqXlsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvyaox%2FbtrQ1e7hHfw%2Fi9wVRl9hKqfD6UG4RqXlsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;171&quot; height=&quot;132&quot; data-origin-width=&quot;171&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;849&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7YP16/btrQ2fkvrIQ/jXRNu8o3nXFk1zMpvUjlT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7YP16/btrQ2fkvrIQ/jXRNu8o3nXFk1zMpvUjlT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7YP16/btrQ2fkvrIQ/jXRNu8o3nXFk1zMpvUjlT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7YP16%2FbtrQ2fkvrIQ%2FjXRNu8o3nXFk1zMpvUjlT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;677&quot; height=&quot;150&quot; data-origin-width=&quot;849&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바탕화면이나 사용하고자 하는 경로에 디렉토리를 하나 만들어줍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 다운받은 프로젝트의&lt;span&gt; config &lt;/span&gt;디렉토리 안에 있는 &lt;span&gt;config.yaml&lt;/span&gt;파일을 복사하여 바탕화면에 생성한 디렉토리에 붙여넣어주겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 아래와 같이 &lt;span&gt;config.yml을 수정하여&lt;/span&gt;자신의 &lt;span&gt;gitea&lt;/span&gt;에 대한 정보와 &lt;span&gt;sonarqube&lt;/span&gt;에 대한 정보를 기입해줍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRt6oo/btrQY21IK4M/Wq6KgWkvAIn50kRX9b4Yw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRt6oo/btrQY21IK4M/Wq6KgWkvAIn50kRX9b4Yw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRt6oo/btrQY21IK4M/Wq6KgWkvAIn50kRX9b4Yw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRt6oo%2FbtrQY21IK4M%2FWq6KgWkvAIn50kRX9b4Yw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;577&quot; height=&quot;443&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;597&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VZIOU/btrQZ4qNoVR/8plUAEOYKV73O7iPT8xx9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VZIOU/btrQZ4qNoVR/8plUAEOYKV73O7iPT8xx9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VZIOU/btrQZ4qNoVR/8plUAEOYKV73O7iPT8xx9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVZIOU%2FbtrQZ4qNoVR%2F8plUAEOYKV73O7iPT8xx9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;473&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;모든 정보를 입력하였다면 이제 Sonar-bot Container 를 띄우도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uwE3i/btrQY1PlrMz/kIRP7OYuCSEn8YvyiKs5lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uwE3i/btrQY1PlrMz/kIRP7OYuCSEn8YvyiKs5lk/img.png&quot; data-alt=&quot;(출처: https://codeberg.org/justusbunsi/gitea-sonarqube-bot)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uwE3i/btrQY1PlrMz/kIRP7OYuCSEn8YvyiKs5lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuwE3i%2FbtrQY1PlrMz%2FkIRP7OYuCSEn8YvyiKs5lk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;648&quot; height=&quot;348&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(출처: https://codeberg.org/justusbunsi/gitea-sonarqube-bot)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdPf9k/btrQ0GQGfUd/xuT47ROpUaisVi0tmlDke1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdPf9k/btrQ0GQGfUd/xuT47ROpUaisVi0tmlDke1/img.png&quot; data-alt=&quot;도커 컨테이너 띄우기 전 tag 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdPf9k/btrQ0GQGfUd/xuT47ROpUaisVi0tmlDke1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdPf9k%2FbtrQ0GQGfUd%2FxuT47ROpUaisVi0tmlDke1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;265&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 컨테이너 띄우기 전 tag 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 최신 버전인 v0.2.2 버전의 태그를 이용하여 컨테이너를 실행시켜주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b661Kd/btrQZXyDJHr/JNLRa4aDfRdyh500RVH9e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b661Kd/btrQZXyDJHr/JNLRa4aDfRdyh500RVH9e0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b661Kd/btrQZXyDJHr/JNLRa4aDfRdyh500RVH9e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb661Kd%2FbtrQZXyDJHr%2FJNLRa4aDfRdyh500RVH9e0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;199&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668190894058&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run -d -it -p 9001:9001 -e &quot;GITEA_SQ_BOT_PORT=9001&quot; -v &quot;C:\Users\Bryant\Desktop\testSonarBot\config.example.yaml:/home/bot/config/config.yaml&quot; justusbunsi/gitea-sonarqube-bot:v0.2.2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 테스트를 위해 &lt;span&gt;Desktop &lt;/span&gt;경로에 &lt;span&gt;testSonarBot &lt;/span&gt;이라는 디렉토리를 만들어준 후 그 안에 설정이 수정된 &lt;span&gt;yml &lt;/span&gt;파일을 위치시켜주었습니다&lt;span&gt;. -v 옵션인 볼륨설정을 통해 로컬환경에 위치시킨 수정된 .yml 파일을 Sonar-bot 컨테이너 내부의 /home/bot/config/config.yaml 과 싱크를 시켜줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6taOn/btrQZicbfM5/SwcRkKd2xKhui9VcfXMKHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6taOn/btrQZicbfM5/SwcRkKd2xKhui9VcfXMKHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6taOn/btrQZicbfM5/SwcRkKd2xKhui9VcfXMKHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6taOn%2FbtrQZicbfM5%2FSwcRkKd2xKhui9VcfXMKHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;66&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 컨테이너는 잘 띄워졌고&lt;span&gt; Config&lt;/span&gt;의 설정변경 사항이 잘 적용 되어 졌는지 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciDMR4/btrQ0GwmTli/RnKHSkd01eQKKvo7e8k3eK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciDMR4/btrQ0GwmTli/RnKHSkd01eQKKvo7e8k3eK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciDMR4/btrQ0GwmTli/RnKHSkd01eQKKvo7e8k3eK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciDMR4%2FbtrQ0GwmTli%2FRnKHSkd01eQKKvo7e8k3eK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;499&quot; height=&quot;43&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668191041653&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Exec -it (컨테이너ID[두글자정도만 입력해줘도 무방합니다]) /bin/bash&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6xOFh/btrQ0YKiaLv/mujEZvNJkuQkGbKKm3InpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6xOFh/btrQ0YKiaLv/mujEZvNJkuQkGbKKm3InpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6xOFh/btrQ0YKiaLv/mujEZvNJkuQkGbKKm3InpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6xOFh%2FbtrQ0YKiaLv%2FmujEZvNJkuQkGbKKm3InpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;354&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668191134187&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Sonar-bot 컨테이너 내부 접속 후

cd config
cat config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cat 명령어를 이용해 컨테이너 내부의 .yml 파일이 수정된 파일로 잘 변경되어 있는지 확인해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 볼륨 옵션이 정상적으로 작동하여 설정변경이 잘 이루어진걸 확인할 수 있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIhEzz/btrQYXzsDCH/120y2RU2kg5oDIO8Du7OIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIhEzz/btrQYXzsDCH/120y2RU2kg5oDIO8Du7OIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIhEzz/btrQYXzsDCH/120y2RU2kg5oDIO8Du7OIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIhEzz%2FbtrQYXzsDCH%2F120y2RU2kg5oDIO8Du7OIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;564&quot; height=&quot;56&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsAjFp/btrQ0YjfeSL/8WaUUSEmQllD39g7wsXGZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsAjFp/btrQ0YjfeSL/8WaUUSEmQllD39g7wsXGZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsAjFp/btrQ0YjfeSL/8WaUUSEmQllD39g7wsXGZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsAjFp%2FbtrQ0YjfeSL%2F8WaUUSEmQllD39g7wsXGZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;315&quot; height=&quot;92&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost:9001로 접속을 해보면 404 page not found 가 뜰텐데 정상입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다음은 Sonar-Qube 서버에 접속 후 사용하고 있는 프로젝트 내의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Project Setting - webhook&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에 들어가 webhook을 설정해주었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TR0ZG/btrQZcJSqeU/LE8cThA9K3EzazQ4lmL4ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TR0ZG/btrQZcJSqeU/LE8cThA9K3EzazQ4lmL4ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TR0ZG/btrQZcJSqeU/LE8cThA9K3EzazQ4lmL4ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTR0ZG%2FbtrQZcJSqeU%2FLE8cThA9K3EzazQ4lmL4ek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;381&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668191351538&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;https://&amp;lt;bot IP:9001&amp;gt;/hooks/sonarqube&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;bot IP는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;span&gt;sonarbot &lt;/span&gt;컨테이너가 띄워져 있는 서버의 IP를 입력해주세요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;필자의 경우 Jenkins CI/CD 시리즈의 3편에서 말했듯 SonarQube와 Sonar-bot을 로컬환경에 컨테이너로 띄워 사용하기 위해 공유기 포트포워딩을 해주었고 bot IP에는 필자의 공유기 Ip 주소를 입력하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAq7L7/btrQ1Kx7uSf/crvyr9B0lBTJ8HJXHh3411/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAq7L7/btrQ1Kx7uSf/crvyr9B0lBTJ8HJXHh3411/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAq7L7/btrQ1Kx7uSf/crvyr9B0lBTJ8HJXHh3411/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAq7L7%2FbtrQ1Kx7uSf%2Fcrvyr9B0lBTJ8HJXHh3411%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;576&quot; height=&quot;317&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다음은 Security&lt;/span&gt;에 들어가 &lt;span&gt;Browse&lt;/span&gt;를 허용해줍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;461&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rTnx6/btrQZgFtnd6/KdyfCLG8UmgTBahs8doPgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rTnx6/btrQZgFtnd6/KdyfCLG8UmgTBahs8doPgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rTnx6/btrQZgFtnd6/KdyfCLG8UmgTBahs8doPgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrTnx6%2FbtrQZgFtnd6%2FKdyfCLG8UmgTBahs8doPgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;548&quot; height=&quot;387&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;461&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668191721463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://{bot IP:9001}/hooks/gitea&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Gitea&lt;/span&gt;도 다음과 같이 Sonar-bot에 대한 webhook 설정을 해줍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 모든 셋팅이 끝났고 테스트를 진행해보아야 하는데 필자의 경우&lt;span&gt; Jenkins &lt;/span&gt;빌드시 다음과 같은 에러가 나왔습니다&lt;span&gt;.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm1e94/btrQYXe6T3i/RRsHN8quchKtCKSD8cB2Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm1e94/btrQYXe6T3i/RRsHN8quchKtCKSD8cB2Wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm1e94/btrQYXe6T3i/RRsHN8quchKtCKSD8cB2Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm1e94%2FbtrQYXe6T3i%2FRRsHN8quchKtCKSD8cB2Wk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;137&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 원인을 파악해보려 하던 중 필자의 &lt;span&gt;SonarQube&lt;/span&gt;의 버전은 &lt;span&gt;9.7 &lt;/span&gt;버전 이였지만 Community-branch-plugin 은 아직 &lt;span&gt;SonarQube&lt;/span&gt;의 &lt;span&gt;9.6&lt;/span&gt;버전까지 지원을 안 한다는 것을 확인하여 버전을 낮추기로 결정하였습니다&lt;span&gt;. =(&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;해당 문제에 대한 &lt;span&gt;issue &lt;/span&gt;링크입니다&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668191820008&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Plugin v1.12.0 incompatible with SonarQube v9.7.0 &amp;middot; Issue #674 &amp;middot; mc1arke/sonarqube-community-branch-plugin&quot; data-og-description=&quot;Describe the bug The v1.12.0 version of this plugin doesn't seem to be compatible with SonarQube v9.7.0. To Reproduce Install v1.12.0 to SonarQube v9.7.0. Expected behavior I'd expect the p...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/674&quot; data-og-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/674&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/2Txb8/hyQxCGLPuH/mlDfW6Umm88WwVnrHu3wd0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/674&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/674&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/2Txb8/hyQxCGLPuH/mlDfW6Umm88WwVnrHu3wd0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Plugin v1.12.0 incompatible with SonarQube v9.7.0 &amp;middot; Issue #674 &amp;middot; mc1arke/sonarqube-community-branch-plugin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Describe the bug The v1.12.0 version of this plugin doesn't seem to be compatible with SonarQube v9.7.0. To Reproduce Install v1.12.0 to SonarQube v9.7.0. Expected behavior I'd expect the p...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;SonarQube&lt;/span&gt;버전을 &lt;span&gt;downgrade &lt;/span&gt;하려 했으나 레퍼런스도 많지 않아 보이고 과정이 쉽지 않을 것 같다는 판단과 현재는 구축해보는 것에 초점을&amp;nbsp; &lt;span&gt;SonarQube&lt;/span&gt;의&lt;span&gt; 8.4&lt;/span&gt;버전의 이미지를 다시 받아 구축을 해보기로 하였습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;8.4 &lt;/span&gt;버전을 선택한 이유는 위의 에러에 대한 원인을 찾던 중 &lt;span&gt;Sonarqube Community Branch Plugin&lt;/span&gt;을 설치 할 때 컨테이너에 넣어준 &lt;span&gt;jar&lt;/span&gt;파일을&lt;span&gt; /opt/sonarqube/lib/common&lt;/span&gt;에도 넣어주어야 하는데 필자가 사용했던&amp;nbsp;&lt;span&gt;9.7&lt;/span&gt;번전에서는 이경로가 존재하지 않았고 이게 특정 버전부터 &lt;span&gt;/lib/common &lt;/span&gt;경로가 사라진것으로 확인되었습니다&lt;span&gt;.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn3nIf/btrQZ3ZKYv5/J4Yy2k5DTkW0XB28dKzpp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn3nIf/btrQZ3ZKYv5/J4Yy2k5DTkW0XB28dKzpp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn3nIf/btrQZ3ZKYv5/J4Yy2k5DTkW0XB28dKzpp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn3nIf%2FbtrQZ3ZKYv5%2FJ4Yy2k5DTkW0XB28dKzpp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;237&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;해당 이슈에 대한 링크&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668191924755&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Plugin doesn't work with sonarqube 8.9 - No more lib/common folder &amp;middot; Issue #350 &amp;middot; mc1arke/sonarqube-community-branch-plugin&quot; data-og-description=&quot;Describe the bug I've upgraded my sonarqube server to version 8.9 released yesterday and the plugin does not work anymore. There are no more lib/common folder in this latest version of sonarqub...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/350&quot; data-og-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/350&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vMsbB/hyQxGPWq4K/kVnVkJIVDIUCRhBxNRx0rK/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_121_1064_205&quot;&gt;&lt;a href=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/350&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/350&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vMsbB/hyQxGPWq4K/kVnVkJIVDIUCRhBxNRx0rK/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_121_1064_205');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Plugin doesn't work with sonarqube 8.9 - No more lib/common folder &amp;middot; Issue #350 &amp;middot; mc1arke/sonarqube-community-branch-plugin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Describe the bug I've upgraded my sonarqube server to version 8.9 released yesterday and the plugin does not work anymore. There are no more lib/common folder in this latest version of sonarqub...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;(이 부분 부터는 정상작동 가능한 설정을 담은 설명입니다 !)&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PHgZ6/btrQZsyUNtM/3x0KAvBoEZR8uXmkzzv4YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PHgZ6/btrQZsyUNtM/3x0KAvBoEZR8uXmkzzv4YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PHgZ6/btrQZsyUNtM/3x0KAvBoEZR8uXmkzzv4YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPHgZ6%2FbtrQZsyUNtM%2F3x0KAvBoEZR8uXmkzzv4YK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;672&quot; height=&quot;144&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 SonarQube를 8.4 버전으로 설치해주었습니다. 만약 이번 시리즈를 잘 따라오셨다면 이미 SonarQube 는 8.4.2 버전으로 잘 설치되어 있을 겁니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이후&lt;span&gt; SonarQube 8.4.2 &lt;/span&gt;버전에 맞는 &lt;span&gt;sonarqube-community-branch-plugin-1.5.0.jar 파일을 다시 다운받아 주었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668192307281&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and pull request decoration in the Comm&quot; data-og-description=&quot;A plugin that allows branch analysis and pull request decoration in the Community version of Sonarqube - GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; data-og-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cas8FR/hyQxKdJyx9/Z9oxhiEKV9jQTOfQ95JWJ1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/mc1arke/sonarqube-community-branch-plugin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cas8FR/hyQxKdJyx9/Z9oxhiEKV9jQTOfQ95JWJ1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and pull request decoration in the Comm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A plugin that allows branch analysis and pull request decoration in the Community version of Sonarqube - GitHub - mc1arke/sonarqube-community-branch-plugin: A plugin that allows branch analysis and...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt90XO/btrQZ3SXdAi/aRTyggfU0Lud2DlmCk3L20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt90XO/btrQZ3SXdAi/aRTyggfU0Lud2DlmCk3L20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt90XO/btrQZ3SXdAi/aRTyggfU0Lud2DlmCk3L20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt90XO%2FbtrQZ3SXdAi%2FaRTyggfU0Lud2DlmCk3L20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;80&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668192472497&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker cp &quot;C:\Users\Bryant\Desktop\sonar-plugin\sonarqube-community-branch-plugin-1.5.0.jar&quot; 7faa39a9853e:opt/sonarqube/extensions/plugins

docker cp &quot;C:\Users\Bryant\Desktop\sonar-plugin\sonarqube-community-branch-plugin-1.5.0.jar&quot; 7faa39a9853e:opt/sonarqube/lib/common&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 해당 jar 파일을 SonarQube 컨테이너 내부의 opt/sonarqube/extensions/plugins 와 sonarqube/lib/common 경로에 cp 명령어로 넣어주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAfu1M/btrQY2HuTTs/QoLIqKajYV6W4cy2YeGAFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAfu1M/btrQY2HuTTs/QoLIqKajYV6W4cy2YeGAFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAfu1M/btrQY2HuTTs/QoLIqKajYV6W4cy2YeGAFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAfu1M%2FbtrQY2HuTTs%2FQoLIqKajYV6W4cy2YeGAFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;139&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPjOgA/btrQZg6vf9G/8zqhIQ95AjoSb7P8awZWok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPjOgA/btrQZg6vf9G/8zqhIQ95AjoSb7P8awZWok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPjOgA/btrQZg6vf9G/8zqhIQ95AjoSb7P8awZWok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPjOgA%2FbtrQZg6vf9G%2F8zqhIQ95AjoSb7P8awZWok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;154&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eeGfaI/btrQ1KZbeXk/DklxSPHivfc0EJDYqomuC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eeGfaI/btrQ1KZbeXk/DklxSPHivfc0EJDYqomuC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eeGfaI/btrQ1KZbeXk/DklxSPHivfc0EJDYqomuC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeeGfaI%2FbtrQ1KZbeXk%2FDklxSPHivfc0EJDYqomuC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;230&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위와 같이 파일이 정상적으로 컨테이너 내부에 들어갔는지 확인도 꼭 해주세요&lt;span&gt;! =)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668192655916&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=web
sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=ce&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 &lt;span&gt;Jenkins&lt;/span&gt;에서 관리하고 있는&lt;span&gt; SonarQube&lt;/span&gt;의 &lt;span&gt;properties 설정에서&lt;/span&gt;&amp;nbsp;&lt;span&gt;jar&lt;/span&gt;파일의 버전이 바뀌었으니&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 버전에 맞게 1.5.0으로 바꾸어 주었습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0geI/btrQ0wgiA3W/dtQ8tTGzMtDKt1Rq4jZye1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0geI/btrQ0wgiA3W/dtQ8tTGzMtDKt1Rq4jZye1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0geI/btrQ0wgiA3W/dtQ8tTGzMtDKt1Rq4jZye1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0geI%2FbtrQ0wgiA3W%2FdtQ8tTGzMtDKt1Rq4jZye1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;96&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668192844646&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker restart sonarqube&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 &lt;span&gt;SonarQube container&lt;/span&gt;를 다시 시작한 후 플러그인이 잘 설치되었는지 확인해주겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEd13y/btrQZtxRSZm/Ud3g0kCxXoyHNHNKvekLo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEd13y/btrQZtxRSZm/Ud3g0kCxXoyHNHNKvekLo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEd13y/btrQZtxRSZm/Ud3g0kCxXoyHNHNKvekLo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEd13y%2FbtrQZtxRSZm%2FUd3g0kCxXoyHNHNKvekLo1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;144&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 1.5.0 버전의 Community branch plugin이 설치가 되었습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 겪은 트러블 내용에서 &lt;b&gt;Sonar-bot&lt;/b&gt; 설치와 yml 파일 수정 및 sonar-bot에 대한 SonarQube &amp;amp; Gitea 의&amp;nbsp; Webhook 설정을 모두 하셨다면 대략적인 준비는 끝이 났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 추가적인 셋팅을 진행하도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자와 같이 로컬환경에 SonarQube를 구축하였다면 SonarQube 설정에 들어가 base url 을 포트포워딩한 공유기 공인 IP주소:9000 으로 명시를 해주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1539&quot; data-origin-height=&quot;915&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RhryO/btrQ0vPfDDs/6gRBwyJLILDUnjR85mER7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RhryO/btrQ0vPfDDs/6gRBwyJLILDUnjR85mER7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RhryO/btrQ0vPfDDs/6gRBwyJLILDUnjR85mER7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRhryO%2FbtrQ0vPfDDs%2F6gRBwyJLILDUnjR85mER7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;319&quot; data-origin-width=&quot;1539&quot; data-origin-height=&quot;915&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위와 같이 설정을 진행해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1479&quot; data-origin-height=&quot;573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DDRn9/btrQYYd4m4D/hPPSYjYNbCd9F7GMXXUNd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DDRn9/btrQYYd4m4D/hPPSYjYNbCd9F7GMXXUNd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DDRn9/btrQYYd4m4D/hPPSYjYNbCd9F7GMXXUNd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDDRn9%2FbtrQYYd4m4D%2FhPPSYjYNbCd9F7GMXXUNd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;248&quot; data-origin-width=&quot;1479&quot; data-origin-height=&quot;573&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 다음 PR comment를 위한 프로젝트를 하나 더 생성해주도록 합니다. 이때 프로젝트 생성시 token 생성은 따로 하지 않고 아래와 같이 기존에 사용하던 token 사용을 해줍니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CaCUC/btrQ0w1E0jG/DGzhRy3b8ImK4CdYVWLuq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CaCUC/btrQ0w1E0jG/DGzhRy3b8ImK4CdYVWLuq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CaCUC/btrQ0w1E0jG/DGzhRy3b8ImK4CdYVWLuq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCaCUC%2FbtrQ0w1E0jG%2FDGzhRy3b8ImK4CdYVWLuq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;624&quot; height=&quot;334&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1219&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baskeL/btrQ1gxg9gL/Ac87QVGkFvsTJ12xISqu91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baskeL/btrQ1gxg9gL/Ac87QVGkFvsTJ12xISqu91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baskeL/btrQ1gxg9gL/Ac87QVGkFvsTJ12xISqu91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaskeL%2FbtrQ1gxg9gL%2FAc87QVGkFvsTJ12xISqu91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;535&quot; height=&quot;301&quot; data-origin-width=&quot;1219&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Using existing token을 선택하고 해당 토큰의 이름을 입력해줍니다. 기존에 사용하던 토큰의 이름은 My Account - Security 에서 확인이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 프로젝트를 하나 더 생성한 이유는 sonar-bot 을 사용하여 SonarQube pull request 분석을 진행할 때 Jenkinsfile 내에서&amp;nbsp; SonarQube-Scanner 를 두 번 진행하여야 합니다. 하지만 하나의 프로젝트 내에서 해당 분석을 진행하면 pr-branch에 대한 분석이 정상적으로 이루어 지지 않고 다음과 같이 모두 0으로 표시 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0cVPB/btrQ1KkzYpb/dT9fvukpbfDORgPQDIkIi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0cVPB/btrQ1KkzYpb/dT9fvukpbfDORgPQDIkIi1/img.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;600&quot; data-is-animation=&quot;false&quot; width=&quot;445&quot; height=&quot;381&quot; style=&quot;width: 43.6274%; margin-right: 10px;&quot; data-widthpercent=&quot;44.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0cVPB/btrQ1KkzYpb/dT9fvukpbfDORgPQDIkIi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0cVPB%2FbtrQ1KkzYpb%2FdT9fvukpbfDORgPQDIkIi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nOb5b/btrQZgS0b6t/VLmb9kKSsTAYBjQfKtm6d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nOb5b/btrQZgS0b6t/VLmb9kKSsTAYBjQfKtm6d1/img.png&quot; data-origin-width=&quot;1689&quot; data-origin-height=&quot;1144&quot; data-is-animation=&quot;false&quot; width=&quot;403&quot; height=&quot;273&quot; style=&quot;width: 55.2098%;&quot; data-widthpercent=&quot;55.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nOb5b/btrQZgS0b6t/VLmb9kKSsTAYBjQfKtm6d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnOb5b%2FbtrQZgS0b6t%2FVLmb9kKSsTAYBjQfKtm6d1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1689&quot; height=&quot;1144&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1121&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mio3N/btrQZslshHi/bkWmbSYsEaF7T2JvkdJKfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mio3N/btrQZslshHi/bkWmbSYsEaF7T2JvkdJKfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mio3N/btrQZslshHi/bkWmbSYsEaF7T2JvkdJKfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMio3N%2FbtrQZslshHi%2FbkWmbSYsEaF7T2JvkdJKfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;568&quot; height=&quot;255&quot; data-origin-width=&quot;1121&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 생성을 완료 하였다면 이제 Jenkins 서버로 가서 새로운 SonarQube 프로젝트에 접근할 수 있도록 설정을 진행해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 SonarQube properties 설정인 sonar.projectKey= 와 sonar.projectName= 만 Jenkins 서버에서 관리를 하고 있기 때문에 SonarQube Server 설정을 하나 더 만들어 주었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1515&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zJNp8/btrQZd24V4M/7sdr1qmfyTwJ7ilgUqTobK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zJNp8/btrQZd24V4M/7sdr1qmfyTwJ7ilgUqTobK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zJNp8/btrQZd24V4M/7sdr1qmfyTwJ7ilgUqTobK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzJNp8%2FbtrQZd24V4M%2F7sdr1qmfyTwJ7ilgUqTobK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1515&quot; height=&quot;646&quot; data-origin-width=&quot;1515&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0DXQU/btrQZcb3JcU/CW4I3eTddt1O1Nk4fjZdv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0DXQU/btrQZcb3JcU/CW4I3eTddt1O1Nk4fjZdv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0DXQU/btrQZcb3JcU/CW4I3eTddt1O1Nk4fjZdv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0DXQU%2FbtrQZcb3JcU%2FCW4I3eTddt1O1Nk4fjZdv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1398&quot; height=&quot;299&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Name은 Jenkinsfile의 Sonar-Scanner Stage에서&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;withSonarQubeEnv(credentialsId:&quot;sonarqube-token&quot;,installationName:'SonarQube-DEV')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과&amp;nbsp; 같이 installtionName으로 사용할 ID 값 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Jenkinsfile에서 추가 구성을 해보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;-Dsonar.pullrequest.key='${PR_ID}'&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;-Dsonar.pullrequest.branch='${PR_BRANCH}'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pull request 프로젝트의 분석을 위해선 위의 sonar properties 설정이 필요한데 PR_number 는 지속적으로 값이 변경되는 부분이고 PR_branch 또한 어떤 feature branch에서 dev branch 로 merge 를 하는지 지속해서 변경되는 값이기에 해당 PR number 와 branch 값을 얻기 위해 필자는 Jenkinsfile의 첫 번째 Stage인 Set Variable 이라는 변수에 값을 할당하여 다른 Stage에서도 사용이 가능하도록 하는 곳에서 설정을 해주었습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;필자의 경우 해당 값을 얻기 위해 git에서 제공하는 환경 변수 값인 &lt;b&gt;${env.CHANGE_ID}&lt;/b&gt;와 &lt;b&gt;${env.CHANGE_BRANCH}&amp;nbsp;&lt;/b&gt;를 사용해보았지만 모두 null 값이 찍혔고 위의 환경변수는 Github를 사용시에 사용할 수 있는 환경 변수라는 것 같다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 방식을 시도해보았지만 기본적으로 제공되는 환경변수값을 통해서는 해당 PR_ID 와 PR_Branch 를 얻을 수 없다는 생각에 Stack Over Flow에 질문을 하였고 해답을 찾게 되었습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668195575652&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;How to get pr number of gitea at jenkins pipeline?&quot; data-og-description=&quot;I'm using gitea &amp;amp; jenkins &amp;amp; sonarqube combination now. I need pr number of gitea for sonarqube pr comment but i don't know how to get pr number at jenkins pipeline. I tried env variables like&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/74370687/how-to-get-pr-number-of-gitea-at-jenkins-pipeline&quot; data-og-url=&quot;https://stackoverflow.com/questions/74370687/how-to-get-pr-number-of-gitea-at-jenkins-pipeline&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bOhU1P/hyQxHuziBl/8tJdkMMmioze7GBGexNWRk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/74370687/how-to-get-pr-number-of-gitea-at-jenkins-pipeline&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/74370687/how-to-get-pr-number-of-gitea-at-jenkins-pipeline&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bOhU1P/hyQxHuziBl/8tJdkMMmioze7GBGexNWRk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How to get pr number of gitea at jenkins pipeline?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I'm using gitea &amp;amp; jenkins &amp;amp; sonarqube combination now. I need pr number of gitea for sonarqube pr comment but i don't know how to get pr number at jenkins pipeline. I tried env variables like&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자가 받은 답변의 내용으로 곰곰히 생각을 아이디어가 떠올랐고 해당 값이 포함되어 나오는 환경변수에서 subString과 split을 이용하여 해당 값만 추출하는 방식을 선택하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Slack 을 통해 Stage 별 알림을 받고 있는 상태였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알림 내용중 PR merge로 인해 발생된 Jenkins build의 경우 필자가 Set Variable Stage 에서 설정한 아래 환경변수에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 #109 라는 PR number 와 localtest 라는 feature branch의 값을 확인 할 수 있었습니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// Git Commit 메시지
GIT_COMMIT_MESSAGE = sh(script: &quot;git --no-pager show -s --format=%B ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s5WiG/btrQZzLv6dU/LOhTeLJB1Ra2RlZ6o5pjW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s5WiG/btrQZzLv6dU/LOhTeLJB1Ra2RlZ6o5pjW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s5WiG/btrQZzLv6dU/LOhTeLJB1Ra2RlZ6o5pjW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs5WiG%2FbtrQZzLv6dU%2FLOhTeLJB1Ra2RlZ6o5pjW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;124&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 &lt;b&gt;GIT_COMMIT_MESSAGE&lt;/b&gt; 라는 변수에 담기는 값을 이용하여 substing 과 split을 이용해 PR_number와 PR-branch를 얻을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 위 출력 내용을 보면 &lt;span&gt;PR_number는 고정적으로&lt;span&gt; (# ) 으로 감싸져 나오는 값이였고 feature branch 또한 from 과 into 라는 고정 출력 값에 감싸져 나오는 것을 확인하였습니다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;// Git Commit 메시지
GIT_COMMIT_MESSAGE = sh(script: &quot;git --no-pager show -s --format=%B ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
//PR_ID
PR_ID = &quot;${GIT_COMMIT_MESSAGE}&quot;.substring(&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf('#')+1,&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf(')')).trim();
//PR_BRANCH
PR_BRANCH = &quot;${GIT_COMMIT_MESSAGE}&quot;.split(&quot;from&quot;)[1].split(&quot;into&quot;)[0].trim();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드와 같이 PR_ID 와 PR_BRANCH 라는 변수에 해당 값만 추출이 되도록 해주었고 아래와 같이 기대하던 결과 값을 얻을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwJ2N7/btrQZciP4a1/VxzriDI0GSyflZMpKYlPG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwJ2N7/btrQZciP4a1/VxzriDI0GSyflZMpKYlPG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwJ2N7/btrQZciP4a1/VxzriDI0GSyflZMpKYlPG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwJ2N7%2FbtrQZciP4a1%2FVxzriDI0GSyflZMpKYlPG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;570&quot; height=&quot;274&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 필자가 설정한 Jenkinsfile 설정 값입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1668196392245&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;stage(&quot;Set Variable&quot;) {
            steps {
                script {
                    DOCKER_IMAGE = ''
                    //생성할 Docker Image 이름 지정
                    DOCKER_IMAGE_NAME = &quot;gunyoung/dev&quot;
                    //Container Registry 경로
                    IMAGE_STORAGE = &quot;https://registry.hub.docker.com/&quot;
                    //Container Registry 접근 Credential id
                    IMAGE_STORAGE_CREDENTIAL = &quot;Docker-id&quot;
                    //알림받을 채널
                    SLACK_CHANNEL = &quot;jenkins&quot;
                    SLACK_START_AND_FINISH_COLOR = &quot;#778899&quot;;
                    SLACK_SUCCESS_COLOR = &quot;#2C953C&quot;;
                    SLACK_FAIL_COLOR = &quot;#FF3232&quot;;
                    // Git Commit 계정
                    GIT_COMMIT_AUTHOR = sh(script: &quot;git --no-pager show -s --format=%an ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                    // Git Commit 메시지
                    GIT_COMMIT_MESSAGE = sh(script: &quot;git --no-pager show -s --format=%B ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                    //PR_ID
                    PR_ID = &quot;${GIT_COMMIT_MESSAGE}&quot;.substring(&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf('#')+1,&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf(')')).trim();
                    //PR_BRANCH
                    PR_BRANCH = &quot;${GIT_COMMIT_MESSAGE}&quot;.split(&quot;from&quot;)[1].split(&quot;into&quot;)[0].trim();
                }
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_START_AND_FINISH_COLOR,
                        message:
                        &quot;==================================================================\n&quot; +
                        &quot;\n&quot; +
                        &quot;배포 파이프라인이 시작되었습니다.\n&quot; +
                        &quot;${env.JOB_NAME}(${env.BUILD_NUMBER})\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_PR_ID-\n&quot; +
                        &quot;:  ${PR_ID}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_PR_BRANCH-\n&quot; +
                        &quot;:  ${PR_BRANCH}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_AUTHOR-\n&quot; +
                        &quot;:  ${GIT_COMMIT_AUTHOR}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_MESSAGE-\n&quot; +
                        &quot;:  ${GIT_COMMIT_MESSAGE}\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}&quot;
                    )
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 Set Variable Stage에서 두 값을 추출하기 위한 설정과 해당 값을 변수에 담아주도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668196502896&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Sonarqube Scanner - dev
        stage(&quot;sonarqube analysis-dev&quot;) {
            when {
                branch &quot;develop&quot;
            }
            steps{
                script{
                    def scannerHome = tool 'jenkins Global Tool Configuration에서 등록한 SonarQube Scanner 이름';
                    withSonarQubeEnv(credentialsId:&quot;jenkins에서 등록한 sonarqube credential&quot;,installationName:'jenkins 설정에서 등록한 sonarqube 이름') {
                    sh &quot;${scannerHome}/bin/sonar-scanner \
                        -Dsonar.branch.name=master \    &amp;lt;---- 이부분이 추가 되었는데 master는 SonarQube 프로젝트의 default branch 이름입니다.
                        -Dsonar.language=java \
                        -Dsonar.java.source=1.8 \
                        -Dsonar.sources=src/main/java \
                        -Dsonar.test=src/test/java \
                        -Dsonar.test.inclusion=**/*Test.java \
                        -Dsonar.issuesReport.console.enable=true \
                        -Dsonar.junit.reportPaths=build/test-results/test \
                        -Dsonar.java.binaries=build/classes \
                        -Dsonar.java.coveragePlugin=jacoco \
                        -Dsonar.coverage.jacoco.xmlReportPaths=build/jacoco/jacoco.xml \
                        -Dsonar.java.libraries.empty=true \
                        -Dsonar.sourceEncoding=UTF-8 \
                        -Dsonar.exclusions=**/dto/**,**/exception/**,**/constant/**,**/SpringInitProjectApplication.java,**/WebRestController.java,**/FileUploadYaml.java \
                        -Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \
                        -Dsonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=web \
                        -Dsonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=ce \
                        &quot;
                    }
                }
            }
            post{
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Dev branch SonarQube Scanning 을 성공하였습니다.&quot;
                    )
                    echo &quot;Success sonarqube analysis&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Dev branch SonarQube Scanning 을 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail sonarqube analysis&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SonarQube Scanner 를 이용한 분석을 두번 진행해주어야 하는데 먼저 기존에 생성했던 SonarQube 프로젝트로 진행을 해줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668196485074&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Sonarqube Scanner - feature(dev로 merge될 branch)
        stage(&quot;sonarqube analysis-feature&quot;) {
            when {
                branch &quot;develop&quot;
            }
            steps{
                script{
                    def scannerHome = tool 'SonarQube-Scanner-Feature';
                    withSonarQubeEnv(credentialsId:&quot;sonarqube-token&quot;,installationName:'SonarQube-PR') {
                    sh &quot;${scannerHome}/bin/sonar-scanner \
                        -Dsonar.pullrequest.key='${PR_ID}' \
                        -Dsonar.pullrequest.base=master \
                        -Dsonar.pullrequest.branch='${PR_BRANCH}' \
                        -Dsonar.language=java \
                        -Dsonar.java.source=1.8 \
                        -Dsonar.sources=src/main/java \
                        -Dsonar.test=src/test/java \
                        -Dsonar.test.inclusion=**/*Test.java \
                        -Dsonar.issuesReport.console.enable=true \
                        -Dsonar.junit.reportPaths=build/test-results/test \
                        -Dsonar.java.binaries=build/classes \
                        -Dsonar.java.coveragePlugin=jacoco \
                        -Dsonar.coverage.jacoco.xmlReportPaths=build/jacoco/jacoco.xml \
                        -Dsonar.java.libraries.empty=true \
                        -Dsonar.sourceEncoding=UTF-8 \
                        -Dsonar.exclusions=**/dto/**,**/exception/**,**/constant/**,**/SpringInitProjectApplication.java,**/WebRestController.java,**/FileUploadYaml.java \
                        -Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \
                        -Dsonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=web \
                        -Dsonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=ce \
                        &quot;
                    }
                }
            }
            post{
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Feature branch SonarQube Scanning 을 성공하였습니다.&quot;
                    )
                    echo &quot;Success sonarqube analysis&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Feature branch SonarQube Scanning 을 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail sonarqube analysis&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;-Dsonar.pullrequest.key='${PR_ID}' \
-Dsonar.pullrequest.base=master \
-Dsonar.pullrequest.branch='${PR_BRANCH}' \&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음은 PR branch에 대한 분석인데 위 3가지 설정값이 다르게 설정된다는 것을 확인해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Sonar-bot 컨테이너 내부의 설정파일과 -v 옵션으로 볼륨설정을 해둔 로컬환경의 yml 파일을 조금 수정해주도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkusTb/btrQ0vaDsMr/sAQKtwgrU8ZPXWkS3FGwgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkusTb/btrQ0vaDsMr/sAQKtwgrU8ZPXWkS3FGwgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkusTb/btrQ0vaDsMr/sAQKtwgrU8ZPXWkS3FGwgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkusTb%2FbtrQ0vaDsMr%2FsAQKtwgrU8ZPXWkS3FGwgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1452&quot; height=&quot;243&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Gitea의 PR comment 에 담길 분석 결과 값 중 new_security_hotspots 값을 추가하여 받도록 설정해줍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1551&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPjtkA/btrQZr07hfW/3zILdBhqC99KvK378czl7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPjtkA/btrQZr07hfW/3zILdBhqC99KvK378czl7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPjtkA/btrQZr07hfW/3zILdBhqC99KvK378czl7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPjtkA%2FbtrQZr07hfW%2F3zILdBhqC99KvK378czl7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1551&quot; height=&quot;526&quot; data-origin-width=&quot;1551&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 namingPattern 의 기존에 켜져있던 정규표현식 부분을 주석처리 해주시고 맨 아래의 정규표현식 주석을 해제해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daB9nL/btrQ0j2vY56/SizP7oTfExePMjLdHhzikK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daB9nL/btrQ0j2vY56/SizP7oTfExePMjLdHhzikK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daB9nL/btrQ0j2vY56/SizP7oTfExePMjLdHhzikK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaB9nL%2FbtrQ0j2vY56%2FSizP7oTfExePMjLdHhzikK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;527&quot; height=&quot;221&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 설정파일이 반영되도록 sonar-bot 컨테이너를 재시작해줍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 정말 끝이 난 것 같지만 아직 한가지 작업을 더 진행해주어야 합니다....! =(&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blgPSu/btrQ1lrKeaM/1h4Xk0MXlakpV3haFVQkL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blgPSu/btrQ1lrKeaM/1h4Xk0MXlakpV3haFVQkL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blgPSu/btrQ1lrKeaM/1h4Xk0MXlakpV3haFVQkL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblgPSu%2FbtrQ1lrKeaM%2F1h4Xk0MXlakpV3haFVQkL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;393&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SonarQube에서 PR branch 분석은 Main branch인 Master 에서 이루어지지 않고 계속해서 branch 가 생성되며 분석결과가 담깁니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그렇기 때문에 새로 생성한&amp;nbsp; FeatuePR 이라는 프로젝트에는 Master branch에 아무런 결과 값이 없어 sonar-bot이 정상적으로 작동하지 않습니다. =(&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQWhBa/btrQ2d1jmAK/2bkICtMSchBqaDCtz1hnf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQWhBa/btrQ2d1jmAK/2bkICtMSchBqaDCtz1hnf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQWhBa/btrQ2d1jmAK/2bkICtMSchBqaDCtz1hnf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQWhBa%2FbtrQ2d1jmAK%2F2bkICtMSchBqaDCtz1hnf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;319&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;조금 번거롭지만 Jenkinsfile 내에서 위 3개 설정을 잠시 지우고&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;-Dsonar.branch.name=master \&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;를 추가하여 Jenkins build를 한 번 진행해주도록 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1809&quot; data-origin-height=&quot;1033&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ylO7Z/btrQYXe8kyS/lBA7E7DxiFenkMyTh1nlC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ylO7Z/btrQYXe8kyS/lBA7E7DxiFenkMyTh1nlC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ylO7Z/btrQYXe8kyS/lBA7E7DxiFenkMyTh1nlC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FylO7Z%2FbtrQYXe8kyS%2FlBA7E7DxiFenkMyTh1nlC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;337&quot; data-origin-width=&quot;1809&quot; data-origin-height=&quot;1033&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그럼 다음과 같이 새로 생성한 프로젝트의&amp;nbsp; master branch에도 결과 값이 담기게 됩니다 !&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 다시 Jenkinsfile의 featurePR 의 Sonnar-Scanner 설정에서&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;-Dsonar.branch.name=master \&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위 값을 지워주고&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;-Dsonar.pullrequest.key='${PR_ID}' \
-Dsonar.pullrequest.base=master \
-Dsonar.pullrequest.branch='${PR_BRANCH}' \&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;pullrequest 설정값 3가지를 다시 넣어줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 모든 작업이 끝났습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Gitea에서 dev branch로 PR을 날린 후 merge 를 하게 되면 아래와 같이 Jenkins build의 SonarQube Quality Gate가 끝난 후 PR comment 가 달리는 것을 확인 할 수 있습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkQuE5/btrQ1gD28K9/JKmDtOsjksJuewZKBBWAxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkQuE5/btrQ1gD28K9/JKmDtOsjksJuewZKBBWAxK/img.png&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;418&quot; data-is-animation=&quot;false&quot; width=&quot;577&quot; height=&quot;263&quot; style=&quot;width: 40.3927%; margin-right: 10px;&quot; data-widthpercent=&quot;40.87&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkQuE5/btrQ1gD28K9/JKmDtOsjksJuewZKBBWAxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkQuE5%2FbtrQ1gD28K9%2FJKmDtOsjksJuewZKBBWAxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;917&quot; height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9wgO7/btrQZWGtUA3/31w0PgNmZP3z4T39C47Dm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9wgO7/btrQZWGtUA3/31w0PgNmZP3z4T39C47Dm0/img.png&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;155&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.4445%;&quot; data-widthpercent=&quot;59.13&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9wgO7/btrQZWGtUA3/31w0PgNmZP3z4T39C47Dm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9wgO7%2FbtrQZWGtUA3%2F31w0PgNmZP3z4T39C47Dm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;492&quot; height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HbxSB/btrQ0Xq8w4T/8M6IcwcK9krzrIKBHBzwik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HbxSB/btrQ0Xq8w4T/8M6IcwcK9krzrIKBHBzwik/img.png&quot; data-origin-width=&quot;1632&quot; data-origin-height=&quot;864&quot; data-is-animation=&quot;false&quot; width=&quot;576&quot; height=&quot;305&quot; style=&quot;width: 51.6849%; margin-right: 10px;&quot; data-widthpercent=&quot;52.29&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HbxSB/btrQ0Xq8w4T/8M6IcwcK9krzrIKBHBzwik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHbxSB%2FbtrQ0Xq8w4T%2F8M6IcwcK9krzrIKBHBzwik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1632&quot; height=&quot;864&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v2rRV/btrQZtdBhu9/s7lpk1Zjr6N3kZTyCtlAH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2rRV/btrQZtdBhu9/s7lpk1Zjr6N3kZTyCtlAH1/img.png&quot; data-origin-width=&quot;1127&quot; data-origin-height=&quot;654&quot; data-is-animation=&quot;false&quot; width=&quot;576&quot; height=&quot;334&quot; style=&quot;width: 47.1523%;&quot; data-widthpercent=&quot;47.71&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2rRV/btrQZtdBhu9/s7lpk1Zjr6N3kZTyCtlAH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2rRV%2FbtrQZtdBhu9%2Fs7lpk1Zjr6N3kZTyCtlAH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1127&quot; height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZVsbn/btrQ0YQ8lLR/3khvl10pN7vCTIwt6VZtw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZVsbn/btrQ0YQ8lLR/3khvl10pN7vCTIwt6VZtw0/img.png&quot; data-alt=&quot;sonar-bot 컨테이너 log를 확인하여 web-hook 이 정상적으로 작동하는지 확인 할 수 있습니다. =)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZVsbn/btrQ0YQ8lLR/3khvl10pN7vCTIwt6VZtw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZVsbn%2FbtrQ0YQ8lLR%2F3khvl10pN7vCTIwt6VZtw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;907&quot; height=&quot;186&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;sonar-bot 컨테이너 log를 확인하여 web-hook 이 정상적으로 작동하는지 확인 할 수 있습니다. =)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkinsfile 전체 소스코드는 필자의 깃헙을 확인해주시기 바랍니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668199046180&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&quot; data-og-description=&quot;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이상으로 Sonar-bot을 이용한 SonarQube PR comment 까지 마무리하며 &lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins&amp;amp;Springboot CI/CD 정리 시리즈를 마치도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;혹여나 Sonar-bot을 이용하여 SonarQube &amp;amp; Gitea PR comment 작업을 하시는데 있어 &lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어려운 부분이 있으시면 댓글을 남겨주시기 바랍니다 !&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;긴 글 읽어주셔서 감사합니다 !&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy/CI CD</category>
      <category>Gitea</category>
      <category>Jenkins CI/CD</category>
      <category>PR comment</category>
      <category>Sonar-bot</category>
      <category>sonarqube</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/38</guid>
      <comments>https://0andwild.tistory.com/38#entry38comment</comments>
      <pubDate>Sat, 12 Nov 2022 05:32:18 +0900</pubDate>
    </item>
    <item>
      <title>Jenkins&amp;amp;Springboot CI/CD 정리(3)</title>
      <link>https://0andwild.tistory.com/37</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnTPl6/btrQWmeyVK6/zqCEnxum48OXE9hwEE8qS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnTPl6/btrQWmeyVK6/zqCEnxum48OXE9hwEE8qS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnTPl6/btrQWmeyVK6/zqCEnxum48OXE9hwEE8qS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnTPl6%2FbtrQWmeyVK6%2FzqCEnxum48OXE9hwEE8qS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span&gt;Jenkins&amp;amp;Springboot CI/CD 정리(3)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnyqBG/btrQ0v10NrQ/VF8DGQkvlmZHDBgOwPvkM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnyqBG/btrQ0v10NrQ/VF8DGQkvlmZHDBgOwPvkM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnyqBG/btrQ0v10NrQ/VF8DGQkvlmZHDBgOwPvkM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnyqBG%2FbtrQ0v10NrQ%2FVF8DGQkvlmZHDBgOwPvkM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;477&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지난 2편에 이어 &lt;b&gt;3편에서는&lt;/b&gt; SonarQube Quality Gate &lt;b&gt;가 통과되었다는 가정하에 그 이후의 Stage들에 대한 설명을 해볼까 합니다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;QualityGate까지의 Stage가 끝나게 되면 분석 결과를 Sonar-bot을 통해 Gitea의 PR comment에 남기게 되지만 이부분은 4편에서 설명드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Jenkins Server에 Docker 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Jenkins server가 돌고 있는 EC2 인스턴스에 docker를 설치해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 이전에 작성된 글이 있으므로 해당 글을 참고해주세요. =)&lt;/p&gt;
&lt;figure id=&quot;og_1668166484917&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;도커(Docker) 설치 &amp;amp; 도커(Docker) 명령어 사용방법 총정리&quot; data-og-description=&quot;지난 글에 이어 도커의 명령어와 사용방법을 정리해볼까 합니다 =) 우선 도커를 사용하려면 설치를 해주어야 겠죠? 필자의 경우 AWS EC2 인스턴스로 Ubuntu 환경에서 Docker를 설치하였습니다. (Ubuntu &quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/31&quot; data-og-url=&quot;https://0andwild.tistory.com/31&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5Ixsi/hyQxDlezPX/pwtxnAhKmKQYIFkAhUyF0k/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/ogT0t/hyQwLkQ5gz/0ufPDJ5tLKTG0uz4kQsAI1/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/vcDRY/hyQwFdSfcR/b3cbfuLpidJ2UvLsPLKK30/img.png?width=992&amp;amp;height=532&amp;amp;face=0_0_992_532&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/31&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/31&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5Ixsi/hyQxDlezPX/pwtxnAhKmKQYIFkAhUyF0k/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/ogT0t/hyQwLkQ5gz/0ufPDJ5tLKTG0uz4kQsAI1/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/vcDRY/hyQwFdSfcR/b3cbfuLpidJ2UvLsPLKK30/img.png?width=992&amp;amp;height=532&amp;amp;face=0_0_992_532');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;도커(Docker) 설치 &amp;amp; 도커(Docker) 명령어 사용방법 총정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;지난 글에 이어 도커의 명령어와 사용방법을 정리해볼까 합니다 =) 우선 도커를 사용하려면 설치를 해주어야 겠죠? 필자의 경우 AWS EC2 인스턴스로 Ubuntu 환경에서 Docker를 설치하였습니다. (Ubuntu&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Dockerfile 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SonarQube Quality Gate&lt;/b&gt;가 끝난 직후 &lt;b&gt;Docker image build&lt;/b&gt; 를 통해 &lt;b&gt;Docker image&lt;/b&gt;를 생성한 후 &lt;b&gt;Docker hub&lt;/b&gt;로 &lt;b&gt;push&lt;/b&gt;를 진행하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자의 경우 Docker hub를 사용해보고자 하는 목적으로 Docker hub를 사용하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(Flow)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) Jenkins 서버에서 프로젝트 image 생성 &amp;amp; Docker hub로 image push&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) Nginx 서버에서 Docker image pull&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker hub는 Github과 같은 개념으로 생각을 하시면 쉽게 이해하실 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Docker hub를 사용하면 이미지 버전관리를 할 수 있다는 장점이 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;(이번 연습에서는 따로 Docker image 생성 시 버전을 명시하지 않았습니다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Docker hub를 사용하지 않을 시에는 gradle build 를 통해 생성된 jar 파일을 Publish over SSH 라는 Jenkins에서 설치가능한 플러그인을 이용해 Nginx 서버로 보낸 후 여기에서 image build를 하는 방법도 있습니다. =)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자와 같은 방식을 사용한다면 다음과 같이 진행해주시면 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;217&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKXZnb/btrQYHpiGKR/COwe6OC3By26r5aiukNzHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKXZnb/btrQYHpiGKR/COwe6OC3By26r5aiukNzHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKXZnb/btrQYHpiGKR/COwe6OC3By26r5aiukNzHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKXZnb%2FbtrQYHpiGKR%2FCOwe6OC3By26r5aiukNzHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;217&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;217&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 프로젝트의&lt;b&gt; root 디렉토리에 dockerfile&lt;/b&gt; 을 하나 만들어주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVJ2Lr%2FbtrQYt5VxrQ%2FudHkwZhwMPM5PhRV3kdo3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;411&quot; height=&quot;216&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668156378892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM openjdk:11
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT [&quot;java&quot;,&quot;-jar&quot;,&quot;/app.jar&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FROM&lt;/b&gt; 명령문은 base 이미지를 지정해주는 것이며 Dockerfile에서 최상단에 위치시켜줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;base 이미지는 일반적으로 Docker hub 같은 공식 Docker repository에 있는 공개 이미지를 주로 사용합니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 openjdk11 을 명시해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ARG&lt;/b&gt; 명령문은&amp;nbsp; docker build 시 --build-arg 옵션으로 인자값을 넘길 수 있습니다. &lt;b&gt;ex)&amp;nbsp; --build-arg -port=8080&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 설정된 인자 값은&amp;nbsp; ${설정된 인자값} 으로 사용될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;COPY&lt;/b&gt; 명령문은 로컬환경 또는 프로젝트내에 파일경로를 입력하고 Docker 이미지 파일 시스템으로 복사를 할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 COPY 명령문을 해석해보면 필자는 현재 Spirngboot &amp;amp; Gradle을 사용하고 있고 프로젝트 내에서 build를 하게되면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 프로젝트의 root 경로의 build/libs/ 에 .jar 파일이 생성되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZY5Pi/btrQYEsURsr/WZfW2rLEkO7Ti934f0zrLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZY5Pi/btrQYEsURsr/WZfW2rLEkO7Ti934f0zrLK/img.png&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;418&quot; data-is-animation=&quot;false&quot; width=&quot;692&quot; height=&quot;218&quot; style=&quot;width: 61.7963%; margin-right: 10px;&quot; data-widthpercent=&quot;62.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZY5Pi/btrQYEsURsr/WZfW2rLEkO7Ti934f0zrLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZY5Pi%2FbtrQYEsURsr%2FWZfW2rLEkO7Ti934f0zrLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1326&quot; height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot; width=&quot;411&quot; height=&quot;216&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;274&quot; data-is-animation=&quot;false&quot; style=&quot;width: 37.0409%;&quot; data-widthpercent=&quot;37.48&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VJ2Lr/btrQYt5VxrQ/udHkwZhwMPM5PhRV3kdo3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVJ2Lr%2FbtrQYt5VxrQ%2FudHkwZhwMPM5PhRV3kdo3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;521&quot; height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는&lt;b&gt; ARG&lt;/b&gt; 에서 &lt;b&gt;JAR_FILE&lt;/b&gt; 이라는 변수안에&lt;b&gt; .jar 파일의 위치&lt;/b&gt;를 지정해주었고 다음과 같이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;COPY {JAR_FILE=.jar 파일 경로} app.jar&lt;/b&gt; 를 지정해주면 &lt;b&gt;Docker build 시&lt;/b&gt; 필자가 지정해준 경로의&lt;b&gt; .jar파일을&lt;/b&gt; &lt;b&gt;이미지 시스템의 app.jar 파일에 복사 &lt;/b&gt;해줍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 &lt;b&gt;ENTRYPOINT&lt;/b&gt; 명령문은 이미지를 컨테이너로 띄울 때 항상 실행되어야 하는 커맨드를 지정해줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너가 뜰 때 &lt;b&gt;ENTRYPOINT&lt;/b&gt; 명령문으로 지정되어진 커맨드가 실행되고, 해당 커맨드로 실해된 프로세스가 죽을 때 컨테이너도 함께 종료되어 집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668159066939&quot; class=&quot;mipsasm&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;java -jar {파일명.jar}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 ENTRYPOINT 안에 지정된 명령문은 우리가 일반적으로 spring project를 터미널 또는 powerShell 등을 이용해 서버를 띄울 때 입력하는 명령어라고 생각하시면 됩니다. 맨뒤에 app.jar 에는 COPY 명령어를 통해 복사된 프로젝트의 jar 파일이 담겨 있기 때문에 app.jar 파일을 실행하라 라고 명령을 하게 되면 프로젝트에서 build 되어진 .jar 파일이 실행되는 것이죠. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Jenkins 서버에서 Docker Plugin을 설치와 Docker hub 가입을 해주도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Jenkins Docker Plugin 설치 및 Docker hub 가입 및 셋팅.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1393&quot; data-origin-height=&quot;1059&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wSjxh/btrQYujLczv/2EAGzIliEgFvfjEvZxDlM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wSjxh/btrQYujLczv/2EAGzIliEgFvfjEvZxDlM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wSjxh/btrQYujLczv/2EAGzIliEgFvfjEvZxDlM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwSjxh%2FbtrQYujLczv%2F2EAGzIliEgFvfjEvZxDlM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;385&quot; data-origin-width=&quot;1393&quot; data-origin-height=&quot;1059&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins 관리 - Plugin Manager &lt;/b&gt;로 들어가 설치가능에서 Docker 를 검색하신 후 &lt;b&gt;Docker Pipeline&lt;/b&gt; 과 &lt;b&gt;Docker plugin&lt;/b&gt; 두 가지를 설치해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 진행되는 동안 Docker hub 가입을 진행해보도록 하죠. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;882&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OW2jM/btrQYP8U2x6/1N3vC6c5fhi1m7kzgSVdM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OW2jM/btrQYP8U2x6/1N3vC6c5fhi1m7kzgSVdM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OW2jM/btrQYP8U2x6/1N3vC6c5fhi1m7kzgSVdM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOW2jM%2FbtrQYP8U2x6%2F1N3vC6c5fhi1m7kzgSVdM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;626&quot; height=&quot;339&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;882&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker hub 홈페이지에 들어가 가입을 진행해주고 로그인을 해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1467&quot; data-origin-height=&quot;591&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/citCHw/btrQZzK9Cue/DePgn3mKPrg8DhV7MKhwm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/citCHw/btrQZzK9Cue/DePgn3mKPrg8DhV7MKhwm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/citCHw/btrQZzK9Cue/DePgn3mKPrg8DhV7MKhwm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcitCHw%2FbtrQZzK9Cue%2FDePgn3mKPrg8DhV7MKhwm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;594&quot; height=&quot;239&quot; data-origin-width=&quot;1467&quot; data-origin-height=&quot;591&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/53urH/btrQZRx7guV/RkdOAxnkCdFkkfmmY0uUx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/53urH/btrQZRx7guV/RkdOAxnkCdFkkfmmY0uUx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/53urH/btrQZRx7guV/RkdOAxnkCdFkkfmmY0uUx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F53urH%2FbtrQZRx7guV%2FRkdOAxnkCdFkkfmmY0uUx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1068&quot; height=&quot;150&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 다음과 같이 image를 관리할 private repository를 하나 생성해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker hub의 셋팅은 끝났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Jenkins에 Docker hub에 접근할 수 있게 Credential 을 등록해주도록 하죠. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1507&quot; data-origin-height=&quot;1132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn95p5/btrQY2fYydM/qV699YnhJvSJ6rJl4EChhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn95p5/btrQY2fYydM/qV699YnhJvSJ6rJl4EChhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn95p5/btrQY2fYydM/qV699YnhJvSJ6rJl4EChhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn95p5%2FbtrQY2fYydM%2FqV699YnhJvSJ6rJl4EChhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;430&quot; data-origin-width=&quot;1507&quot; data-origin-height=&quot;1132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 Username with password를 이용해 등록해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Username&lt;/b&gt; = Docker hub 아이디&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Password&lt;/b&gt; = Docker hub 비밀번호&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ID&lt;/b&gt; = Jenkinsfile에서 사용할 ID 값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Description&lt;/b&gt; = 해당 credential 에 대한 설명&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Jenkins Server 에서 docker hub에 로그인을 해보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qezAc/btrQ0vBpRtB/RB9BSnp6BNK7Y92ZhL0RsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qezAc/btrQ0vBpRtB/RB9BSnp6BNK7Y92ZhL0RsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qezAc/btrQ0vBpRtB/RB9BSnp6BNK7Y92ZhL0RsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqezAc%2FbtrQ0vBpRtB%2FRB9BSnp6BNK7Y92ZhL0RsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;125&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;분명 올바른 아이디와 비밀번호를 입력했는데 &lt;span&gt;permission denied&lt;/span&gt;가 떴네요&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 문제는 사용자가 &lt;span&gt;/var/run/docker.sock &lt;/span&gt;을 접근하려 했지만 권한이 없어 발생하는 문제입니다&lt;span&gt;. &lt;/span&gt;사용자가&lt;span&gt; root:docker &lt;/span&gt;권한을 가지고 있어야 합니다&lt;span&gt;.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZc6kT/btrQ1eTtLVh/bWM59ldPa2KKMKeIf2SY80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZc6kT/btrQ1eTtLVh/bWM59ldPa2KKMKeIf2SY80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZc6kT/btrQ1eTtLVh/bWM59ldPa2KKMKeIf2SY80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZc6kT%2FbtrQ1eTtLVh%2FbWM59ldPa2KKMKeIf2SY80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;56&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인을 해보면 &lt;span&gt;docker&lt;/span&gt;에 대한 권한이 부여되어 있지 않으므로 권한을 부여해주도록 하겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2TUkk/btrQ0HhsuNm/oEh0n6AJSSKkYZ7audQWAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2TUkk/btrQ0HhsuNm/oEh0n6AJSSKkYZ7audQWAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2TUkk/btrQ0HhsuNm/oEh0n6AJSSKkYZ7audQWAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2TUkk%2FbtrQ0HhsuNm%2FoEh0n6AJSSKkYZ7audQWAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;61&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668166653116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo usermod -a -G docker $USER&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자를 &lt;span&gt;docker group&lt;/span&gt;에 포함시켜주도록 하겠습니다&lt;span&gt;. $USER &lt;/span&gt;환경 변수는 로그인한 사용자 아이디를 나타내므로 그대로 입력해줍시다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6z8ju/btrQ0HIzrgY/KHYsboJayYfj2uhyuaErh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6z8ju/btrQ0HIzrgY/KHYsboJayYfj2uhyuaErh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6z8ju/btrQ0HIzrgY/KHYsboJayYfj2uhyuaErh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6z8ju%2FbtrQ0HIzrgY%2FKHYsboJayYfj2uhyuaErh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;55&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668166680412&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo chmod 666 /var/run/docker.sock&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;/var/run/docker.sock &lt;/span&gt;파일의 권한을 &lt;span&gt;666&lt;/span&gt;으로 변경하여 그룹 내 다른 사용자도 접근가능하게 진행해주었습니다&lt;span&gt;.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SWk4l/btrQ1mxaar9/FL2Qos0abrYCte5SjUMyOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SWk4l/btrQ1mxaar9/FL2Qos0abrYCte5SjUMyOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SWk4l/btrQ1mxaar9/FL2Qos0abrYCte5SjUMyOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSWk4l%2FbtrQ1mxaar9%2FFL2Qos0abrYCte5SjUMyOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;50&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 해당 권한 변경사항을 적용시켜주기 위해 Docker 를 재시작 해주도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. Jenkins 파일 작성 (Docker Image build)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작성을 하다 플로우가 이해가 가지 않는 부분은 풀 소스코드를 필자의 깃헙에서 확인해주시기 바랍니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668164739490&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&quot; data-og-description=&quot;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668164547835&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;stages {
        //공통사용 항목 변수 지정 및 build 유발자와 commit 내역을 함께 Slack 알림으로 전송
        stage(&quot;Set Variable&quot;) {
            steps {
                script {
                    DOCKER_IMAGE = ''
                    //생성할 Docker Image 이름 지정
                    DOCKER_IMAGE_NAME = &quot;gunyoung/dev&quot;
                    //Container Registry 경로
                    IMAGE_STORAGE = &quot;https://registry.hub.docker.com/&quot;
                    //Container Registry 접근 Credential id
                    IMAGE_STORAGE_CREDENTIAL = &quot;Docker-id&quot;
                    //알림받을 채널
                    SLACK_CHANNEL = &quot;jenkins&quot;
                    SLACK_START_AND_FINISH_COLOR = &quot;#778899&quot;;
                    SLACK_SUCCESS_COLOR = &quot;#2C953C&quot;;
                    SLACK_FAIL_COLOR = &quot;#FF3232&quot;;
                    // Git Commit 계정
                    GIT_COMMIT_AUTHOR = sh(script: &quot;git --no-pager show -s --format=%an ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                    // Git Commit 메시지
                    GIT_COMMIT_MESSAGE = sh(script: &quot;git --no-pager show -s --format=%B ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                    //PR_ID
                    PR_ID = &quot;${GIT_COMMIT_MESSAGE}&quot;.substring(&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf('#')+1,&quot;${GIT_COMMIT_MESSAGE}&quot;.indexOf(')')).trim();
                    //PR_BRANCH
                    PR_BRANCH = &quot;${GIT_COMMIT_MESSAGE}&quot;.split(&quot;from&quot;)[1].split(&quot;into&quot;)[0].trim();
                }
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_START_AND_FINISH_COLOR,
                        message:
                        &quot;==================================================================\n&quot; +
                        &quot;\n&quot; +
                        &quot;배포 파이프라인이 시작되었습니다.\n&quot; +
                        &quot;${env.JOB_NAME}(${env.BUILD_NUMBER})\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_PR_ID-\n&quot; +
                        &quot;:  ${PR_ID}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_PR_BRANCH-\n&quot; +
                        &quot;:  ${PR_BRANCH}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_AUTHOR-\n&quot; +
                        &quot;:  ${GIT_COMMIT_AUTHOR}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_MESSAGE-\n&quot; +
                        &quot;:  ${GIT_COMMIT_MESSAGE}\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}&quot;
                    )
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자는 Stages{} 안의 첫번째 Stage{}로 Set Variable 이라는 자주 사용되는 값 또는 Jenkins에 등록한 credential 등을 이 Stage에서 모두 변수 값에 담아두었습니다. 이렇게 설정을 해두면 다른 Stage들에서도 ${설정한 변수} 로 그 값을 가져올 수 있기 때문에 편리합니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DOCKER IMAGE = ' '&lt;/b&gt;&amp;nbsp; 는&amp;nbsp; docker image 빌드를 한 값을 담아주는 변수이기에 빈 String 으로 지정해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DOCKER_IMAGE_NAME = &quot;gunyoung/dev&quot;&lt;/b&gt;&amp;nbsp; 이부분은 Docker hub에서 생성한 registry의 이름과 동일하게 지정해주었습니다.&lt;br /&gt;//Container Registry 경로 &lt;br /&gt;&lt;b&gt;IMAGE_STORAGE =&lt;/b&gt; &lt;b&gt;&quot;&lt;a href=&quot;https://registry.hub.docker.com/&amp;quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://registry.hub.docker.com/&quot;&lt;/a&gt;&lt;/b&gt; &lt;br /&gt;//Container Registry 접근 Credential id로 Jenkins에서 등록한 Docker hub의 credentail ID 값 입니다.&lt;br /&gt;&lt;b&gt;IMAGE_STORAGE_CREDENTIAL = &quot;Docker-id&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668148613178&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Docker Image 생성
        stage('Build Docker') {
            when {
                branch &quot;develop&quot;
            }
            steps {
                sh 'echo &quot;Image Build Start&quot;'
                script {
                    DOCKER_IMAGE = docker.build DOCKER_IMAGE_NAME
                }
            }
            post {
                success {
                    sh 'echo &quot;Successfully Build Docker&quot;'
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Docker Image Build 를 성공하였습니다.&quot;
                    )
                }
                failure {
                    sh 'echo &quot;Build Docker Fail&quot;'
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Docker Image Build 를 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 SonarQube Quality Gate Stage 밑에 Docker Image build Stage를 추가 해주도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DOCKER_IMAGE&amp;nbsp;=&amp;nbsp;docker.build&amp;nbsp;DOCKER_IMAGE_NAME&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 처음 Stage에서 Docker_IMAGE 라는 변수에&amp;nbsp; ' ' 을 지정해주었는데 이번 Stage에서 Docker Image build 를 한 값이 담기게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker_IMAGE_NAME 에는 gunyoung/dev 로 지정해주었기 때문에 해당 이름으로 Image가 빌드 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668165430086&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Docker Image를 Docker-hub 에 push
        stage('Push Docker') {
            when {
                branch &quot;develop&quot;
            }
            steps {
                sh 'echo &quot;Docker Image Push Start&quot;'
                script {
                    docker.withRegistry(IMAGE_STORAGE, IMAGE_STORAGE_CREDENTIAL){
                    DOCKER_IMAGE.push(&quot;latest&quot;)
                    }
                }
            }
            post {
                success {
                    sh 'docker rmi $(docker images -q -f dangling=true)'
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Docker registry 에 Image 를 성공적으로 push 하였습니다.&quot;
                    )
                    echo &quot;Push Docker Success&quot;
                }
                failure {
                    error 'This Image Push Fail'
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Docker registry 에 Image push 를 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Push Docker Fail&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker.withRegistry(IMAGE_STORAGE,&amp;nbsp;IMAGE_STORAGE_CREDENTIAL){ &lt;/b&gt;&lt;br /&gt;&lt;b&gt;DOCKER_IMAGE.push(&quot;latest&quot;)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;}&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드를 통해 build 한 Docker Image를 Docker hub 에 Push 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;withRegistry()&lt;/b&gt; 안에 담겨있는&lt;b&gt; IMAGE_STORAGE&lt;/b&gt; 와&lt;b&gt; IMAGE_STORAGE_CREDENTIAL&lt;/b&gt; 은 맨 첫 번째 Stage인 Set Variable 에서 설정한 값이 담기게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 살펴봐야 할 것은 steps 가 끝나고 Post{} 에서 해당 Step이 성공하였을 때 에 대한 실행 명령인데 이부분에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;sh 'docker rmi $(docker images -q -f dangling=true)'&amp;nbsp;&lt;/b&gt;는 Jenkins Server 에서 프로젝트의 Docker Image를 생성하기 때문에 계속해서 이미지가 쌓이는 것을 방지 하기 위해 &lt;b&gt;dangling=true &lt;/b&gt;명령어를 이용해 image tag가 없는 이미지를 삭제하도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 코드에서 Jenkins build를 실행하고 맨처음 Image 빌드를 하였다면 아마 Post의 Success에서&amp;nbsp; error가 날 것 입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 현재 이미지를 처음 생성하였기 때문에 docker image 중 tag가 없는 image가 없으므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;sh 'docker rmi $(docker images -q -f dangling=true)'&amp;nbsp;&amp;nbsp;&lt;/b&gt;명령어 에서 삭제할 이미지가 없기 때문에 에러가 납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkins 빌드를 다시 한 번 돌리게 된다면 정상적으로 docker hub로 생성한 Imgae를 Push 하는 Stage까지 성공을 하실 수 있을 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이부분은 안에 조건문을 감싸 tag가 없는 이미지가 존재할 때만 위 명령어를 실행하도록 하는 방법을 추가하면 될 것 같다는 생각이 드네요...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조만간 수정을 하여 다시 Github에 올리도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;만약 해당 Stage에서 빌드시 docker permission denied 나 docker.sock과 관련된 에러가 난다면 Jenkins 가 있는 EC2 인스턴스에 SSH 접속을 하여 docker login을 다시 해보시고,&amp;nbsp; 위에서 진행하였던 docker 에대한 사용자 권한을 다시 확인해보시길 바랍니다. =)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Docker image를 생성하고 Docker hub로 image를 Push 하는 것 까지 모두 완료하였습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 스텝은 Nginx와 spring project 가 띄워질 서버를 만들고 설정을 해보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. Nginx와 &lt;b&gt;spring project 컨테이너가 띄워질&lt;/b&gt; EC2 인스턴스 생성 및 Docker 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx와 Spring project 컨테이너가 띄워질 서버가 필요하기 때문에 AWS EC2 인스턴스를 하나 더 생성해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;만약 EC2 인스턴스 생성 방법이 헷갈리시는 분들은 해당 시리즈 1편의 글을 확인해주세요.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668167220067&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Jenkins&amp;amp;Springboot CI/CD 정리(1)&quot; data-og-description=&quot;Jenkins&amp;amp;Springboot CI/CD 정리(1) 필자가 경험한 Springboot 프로젝트와 Jenkins CI 를 활용한 CI/CD 구축에 대해 정리를 해보고자 합니다. =) 이 시리즈에서는 이미 작성된 내용에 대해선 해당 글로 대체 할 예&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/35&quot; data-og-url=&quot;https://0andwild.tistory.com/35&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qio2H/hyQxAPz7O1/EAxjtgfk9WA95d5VcgfAhk/img.png?width=225&amp;amp;height=225&amp;amp;face=96_39_139_86,https://scrap.kakaocdn.net/dn/bvqFxy/hyQxExGbzE/1amtJN1Hc5sbOViGNUd1B0/img.png?width=225&amp;amp;height=225&amp;amp;face=96_39_139_86,https://scrap.kakaocdn.net/dn/bWwucS/hyQwy0aVci/ot4r8xLEBFqxEe0AYy2xJK/img.png?width=1813&amp;amp;height=1111&amp;amp;face=0_0_1813_1111&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/35&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/35&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qio2H/hyQxAPz7O1/EAxjtgfk9WA95d5VcgfAhk/img.png?width=225&amp;amp;height=225&amp;amp;face=96_39_139_86,https://scrap.kakaocdn.net/dn/bvqFxy/hyQxExGbzE/1amtJN1Hc5sbOViGNUd1B0/img.png?width=225&amp;amp;height=225&amp;amp;face=96_39_139_86,https://scrap.kakaocdn.net/dn/bWwucS/hyQwy0aVci/ot4r8xLEBFqxEe0AYy2xJK/img.png?width=1813&amp;amp;height=1111&amp;amp;face=0_0_1813_1111');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins&amp;amp;Springboot CI/CD 정리(1)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins&amp;amp;Springboot CI/CD 정리(1) 필자가 경험한 Springboot 프로젝트와 Jenkins CI 를 활용한 CI/CD 구축에 대해 정리를 해보고자 합니다. =) 이 시리즈에서는 이미 작성된 내용에 대해선 해당 글로 대체 할 예&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 750 시간으로 제한된 EC2 freetier를 효율적으로 사용하기 위해 AWS 계정을 하나 더 만들어 작업을 진행하였습니다. =)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인스턴스 생성을 완료하였다면 해당 서버에도&amp;nbsp; Docker를 설치해주도록 합시다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 설치의 경우 1번에서 필자가 작성한 글의 링크를 걸어두었으니 참고를하여 설치를 진행해주세요.=)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되었다면 Jenkins 서버에서 했던것과 동일하게 Docker 에대한 사용자 권한을 설정해주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;

&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6. Docker Compose 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번의 작업이 모두 끝났다는 가정하에 Blue &amp;amp; Green 방식으로 띄워질 Spring project에 대한 Docker-compose 파일 작성과 Nginx 설정파일 작성을 진행해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5JTsh/btrQY1uJBpL/RFGZOlWPoDz11uxVBxKbG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5JTsh/btrQY1uJBpL/RFGZOlWPoDz11uxVBxKbG1/img.png&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;402&quot; data-is-animation=&quot;false&quot; width=&quot;491&quot; height=&quot;213&quot; style=&quot;width: 49.9924%; margin-right: 10px;&quot; data-widthpercent=&quot;50.58&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5JTsh/btrQY1uJBpL/RFGZOlWPoDz11uxVBxKbG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5JTsh%2FbtrQY1uJBpL%2FRFGZOlWPoDz11uxVBxKbG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;926&quot; height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TVCOH/btrQ0Gv8xiS/j7ZucMmk0BSNCNijN7MF41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TVCOH/btrQ0Gv8xiS/j7ZucMmk0BSNCNijN7MF41/img.png&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;411&quot; data-is-animation=&quot;false&quot; width=&quot;538&quot; height=&quot;239&quot; style=&quot;width: 48.8448%;&quot; data-widthpercent=&quot;49.42&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TVCOH/btrQ0Gv8xiS/j7ZucMmk0BSNCNijN7MF41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTVCOH%2FbtrQ0Gv8xiS%2Fj7ZucMmk0BSNCNijN7MF41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;925&quot; height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668167963160&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;version: '3.1'

services:

  api:
    image: gunyoung/dev:latest

    container_name: springboot-blue-a

    environment:
      - &quot;SPRING_PROFILES_ACTIVE=dev1&quot;
      - LANG=ko_KR.UTF-8

    ports:
      - '8080:8081'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 dev환경과&amp;nbsp; prod 환경을 분리하여 서버를 띄우기 위해 docker-dev 라는 패키지와 docker-operation(=prod) 라는 패키지를 생성해주고 그안에 deploy.sh(실행 명령어 파일)과 docker compose 파일을 담아주었습니다. 해당 패키지들은 Jenkinsfile에서 작성한데로 when{develop} 또는 when{main} 이라는 branch 에 따라 파일이 해당 서버로 &lt;b&gt;Publish Over SSH plugin&lt;/b&gt;을 통해 전송이 될 것 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker-compose.yml&lt;/b&gt; 파일은 컨테이너를 compose 파일로 띄울 때 Compose 파일에 명시된 대로 컨테이너가 띄워지므로 내가 이 컨테이너에 어떠한 것들을 담을 것인가라는 장바구니 개념으로 생각하시면 될 것 같습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compose 파일 내에 &lt;b&gt;image&lt;/b&gt;는 실행할 이미지이고 필자의 경우 gunyoung/dev 라는 이미지를 Jenkins 서버에서 생성하고 nginx가 있는 서버에서 해당 이미지를 필자의 docker hub로 부터 pull 하여 컨테이너를 띄울 것이기 때문에 생성한 이미지 이름을 명시해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;container_name&lt;/b&gt;은 해당 Compose 파일로 컨테이너를 띄울 때 컨테이너 이름을 무엇으로 할 지 정하는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여기서 조금 주의깊게 봐야할 것은 environment 설정에서 필자의 경우 application.yml 파일에서 local, dev, operation(=prod) 로 환경 분리를 해두었기 때문에 여기에서 dev1 이라는 프로필 설정을 가져오겠다고 명시를 하면 해당 컨테이너는 dev1이라는 프로필 설정값으로 컨테이너가 띄워지게 됩니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ports &lt;/b&gt;의 경우 좌측은 외부 포트 번호로 즉, 해당 url 과 포트번호를 입력하여 서버로 붙을 port 번호 입니다. 우측의 포트 번호는 필자의 경우 application.yml 파일에서 spring profile을 local = 8080, dev1= 8081, operation(=prod)=8180 으로 주었기 때문에 해당 Compose의 environment에서 지정해준 dev1 프로필에 맞추어 8081포트를 입력해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 profile을 operation(=pord) 환경으로 맞추어 놓고 우측 포트번호를&amp;nbsp; 8080 또는 8081 등 내부 프로필 포트번호와 다르게 맞추게되면 정상적으로 서버가 띄워지지 않으니 주의깊게 살펴보시길 바랍니다. =)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 깃헙에 들어가 docker compose 파일을 보시면 아시겠지만 필자는 blue compose 2개 green compose 2개 를 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 이유는 우선 Blue &amp;amp; Green 방식은 Blue 가 띄워져 있다면 Green 컨테이너에 새로운 버전을 띄운 후 스위칭하고 구버전 컨테이너인 Blue 컨테이너를 종료하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 이번 연습에서 Nginx를 이용하여 로드밸런싱 설정을 함께 해보고 싶어 각 컨테이너를 2개 씩 띄워지도록 작업을 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(docker compose -dev)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCC2WL/btrQZWsJE9z/kg8S5quPrzR1dTa7Zu7UP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCC2WL/btrQZWsJE9z/kg8S5quPrzR1dTa7Zu7UP1/img.png&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;472&quot; data-is-animation=&quot;false&quot; width=&quot;286&quot; height=&quot;242&quot; data-widthpercent=&quot;50.64&quot; style=&quot;width: 50.0493%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCC2WL/btrQZWsJE9z/kg8S5quPrzR1dTa7Zu7UP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCC2WL%2FbtrQZWsJE9z%2Fkg8S5quPrzR1dTa7Zu7UP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;557&quot; height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wnioL/btrQ0YQTvEP/42lkeT49CqEHrKKt0u77Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wnioL/btrQ0YQTvEP/42lkeT49CqEHrKKt0u77Uk/img.png&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;439&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.7879%;&quot; data-widthpercent=&quot;49.36&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wnioL/btrQ0YQTvEP/42lkeT49CqEHrKKt0u77Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwnioL%2FbtrQ0YQTvEP%2F42lkeT49CqEHrKKt0u77Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;439&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGS0hW/btrQZiiKEe1/Rw7Jbu3dObeBNSX7J0oYjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGS0hW/btrQZiiKEe1/Rw7Jbu3dObeBNSX7J0oYjK/img.png&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;433&quot; data-is-animation=&quot;false&quot; width=&quot;343&quot; height=&quot;307&quot; style=&quot;width: 48.9212%; margin-right: 10px;&quot; data-widthpercent=&quot;49.5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGS0hW/btrQZiiKEe1/Rw7Jbu3dObeBNSX7J0oYjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGS0hW%2FbtrQZiiKEe1%2FRw7Jbu3dObeBNSX7J0oYjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;484&quot; height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0Xpch/btrQ0GbSBCk/GIMctGewGazyvba0NlLD30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0Xpch/btrQ0GbSBCk/GIMctGewGazyvba0NlLD30/img.png&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;427&quot; data-is-animation=&quot;false&quot; width=&quot;320&quot; height=&quot;281&quot; style=&quot;width: 49.9161%;&quot; data-widthpercent=&quot;50.5&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0Xpch/btrQ0GbSBCk/GIMctGewGazyvba0NlLD30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0Xpch%2FbtrQ0GbSBCk%2FGIMctGewGazyvba0NlLD30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Operation(=prod) 환경의 경우 스프링 프로필 설정과 포트번호만 다르게 설정을 해주었기 때문에 따로 코드를 올리지 않도록 하곘습니다. 만약 헷갈리시거나 해당 코드를 확인해보고 싶으시다면 필자의 깃헙 코드를 참고해주세요.&lt;/p&gt;
&lt;figure id=&quot;og_1668169471312&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&quot; data-og-description=&quot;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dkSV1Q/hyQwxNGh83/6b2imHL5AX3hDK2kHED9Yk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - 0AndWild/Jenkins-CICD: Jenkins Ci tool을 활용한 CI/CD 구축&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins Ci tool을 활용한 CI/CD 구축. Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;7. Nginx config 파일 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dt8xh7/btrQ1gw3VnN/tFzbjddKDnCt8CrK1DtQP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dt8xh7/btrQ1gw3VnN/tFzbjddKDnCt8CrK1DtQP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dt8xh7/btrQ1gw3VnN/tFzbjddKDnCt8CrK1DtQP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdt8xh7%2FbtrQ1gw3VnN%2FtFzbjddKDnCt8CrK1DtQP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;290&quot; height=&quot;284&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 프로젝트의 root 디렉토리에 nginx/conf.d 라는 패키지를 생성해주었고 이 안에 nginx 컨테이너를 띄울 compose 파일과 nginx의 blue &amp;amp; green 설정파일들을 넣어주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668169654502&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;version: '3.3'
services:
  nginx:
    image: nginx
    ports:
      - '80:80'
    extra_hosts:
      - &quot;host.docker.internal:host-gateway&quot;
    volumes:
      - /home/ec2-user/nginx/conf.d/nginx.conf:/etc/nginx/nginx.conf
    container_name: nginx-webserver&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(docker-compose-nginx.yml)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668169775755&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    upstream backend {
        server {spring project가 띄워질 서버의 ip}:8080; # blue
        server {spring project가 띄워질 서버의 ip}:8081; # blue
    }

    access_log /var/log/nginx/access.log;

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(nginx.blue.conf)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668169823151&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    upstream backend {
        server {spring project가 띄워질 서버의 ip}:8082; # green
        server {spring project가 띄워질 서버의 ip}:8083; # green
    }

    access_log /var/log/nginx/access.log;

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(nginx.green.conf)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668169888335&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    upstream backend {
        server {spring project가 띄워질 서버의 ip}:8080; # blue
        server {spring project가 띄워질 서버의 ip}:8081; # blue
    }

    access_log /var/log/nginx/access.log;

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(nginx.conf) - 필자의 경우 초기 nginx.conf의 설정값을 blue로 지정해주었습니다. 이후 deploy.sh에 명시된 docker cp 명령어에 따라 새로 띄워지는 컨테이너의 color의 설정값으로 변경이 됩니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 location 의&amp;nbsp; proxy pass 를 통해 nginx 서버로 접속을 하면 http upstream backend 에서 설정해준 ip:port 로 프록시가 이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 필자의 경우 같은 색상의 컨테이너를 두개씩 띄워주었고 upstream에도 해당 컨테이너들이 띄워지는 ip와 외부 포트번호를 명시해주었는데 이렇게 따로 설정없이 두개를 모두 입력하면 라운드로빈 방식(요청 순서대로: 기본값) 으로 로드밸런싱이 적용이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nginx를 활용한 무중단 배포 방식은 Blue &amp;amp; Green 방식 외에도 롤링, 카나리 등의 방식이 존재합니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로드밸런싱 또한 라운드로빈 방식 외에 least_connection, ip_hash, least_time 등 의 방식이 존재하지만 이 부분에 대해서는 따로 글을 정리하여 업로드 하도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Deploy.sh 파일을 작성해보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8. Deploy.sh 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deploy.sh 파일은 배포를 하는데 있어 필요한 sh 스크립트 명령어의 집합이라고 생각하시면 됩니다. =)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3yRbW/btrQ0XxHTTK/e5kXSNk1CI2FcxscPm3cEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3yRbW/btrQ0XxHTTK/e5kXSNk1CI2FcxscPm3cEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3yRbW/btrQ0XxHTTK/e5kXSNk1CI2FcxscPm3cEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3yRbW%2FbtrQ0XxHTTK%2Fe5kXSNk1CI2FcxscPm3cEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;345&quot; height=&quot;186&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 docker compose들이 담겨 있는 패키지 안에 deploy.sh 을 위치 시켜주었고 해당 패키지를 한 번에 jenkins 서버에서 nginx 서버로 전송해주었습니다. 이 부분은 다음 스텝에서 Jenkinsfile을 작성하면서 설명드리도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;deploy.sh 파일은 주석을 통해 설명 하도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668171070545&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash    &amp;lt;- 해당 파일을 bash 쉘로 실행시키겠다는 의미

#필자의 경우 nginx와 spring project 컨테이너가 띄워지는 두번째 인스턴스를 ubuntu가 아닌
#AWS Linux를 사용해보았고 초기 사용자 이름이 ec2-user 로 잡혀 있습니다. 이부분은 ubuntu 로 생성하였을 경우
#ubuntu로 바꾸어주시길 바랍니다.=)
#아래의 변수에 담긴 파일 경로는 Jenkins에서 publish Over SSH 로 Nginx 서버로 보낸 파일들의 경로 입니다.
#이 경로도 Jenkins 설정에서 경로를 다르게 지정해주면 해당 경로로 파일들을 보낼 수 있습니다. 

#Nginx.conf 파일경로
NGINX_DIR=/home/ec2-user/nginx/conf.d
#Docker-compose 파일경로
DOCKER_DIR=/home/ec2-user/docker-dev
#docker 컨테이너 이름
DOCKER_APP_NAME=springboot

#nginx 컨테이너가 떠있는지 확인
EXIST_NGINX=$(docker ps | grep nginx-webserver)
#떠있지 않으면 nginx 서버를 구동한다 이미 구동중이라면 skip
if [ -z &quot;$EXIST_NGINX&quot; ]; then
    echo &quot;nginx container start&quot;
    docker-compose -p nginx-webserver -f ${NGINX_DIR}/docker-compose.nginx.yml up -d
else
    echo &quot;nginx is already running&quot;
fi

sleep 5

# Blue 를 기준으로 현재 떠있는 컨테이너를 체크한다.
EXIST_BLUE_A=$(docker-compose -p ${DOCKER_APP_NAME}-blue-a -f ${DOCKER_DIR}/docker-compose.blue1.yml ps --status=running | grep ${DOCKER_APP_NAME}-blue-a)
EXIST_BLUE_B=$(docker-compose -p ${DOCKER_APP_NAME}-blue-b -f ${DOCKER_DIR}/docker-compose.blue2.yml ps --status=running | grep ${DOCKER_APP_NAME}-blue-b)

# 컨테이너 스위칭
if [ -z &quot;$EXIST_BLUE_A&quot; ] &amp;amp;&amp;amp; [ -z &quot;$EXIST_BLUE_B&quot; ]; then
    echo &quot;blue up&quot;
    docker-compose -p ${DOCKER_APP_NAME}-blue-a -f ${DOCKER_DIR}/docker-compose.blue1.yml up -d
    docker-compose -p ${DOCKER_APP_NAME}-blue-b -f ${DOCKER_DIR}/docker-compose.blue2.yml up -d
    IDLE_PORT=8080
    BEFORE_COMPOSE_COLOR=&quot;green&quot;
    AFTER_COMPOSE_COLOR=&quot;blue&quot;
else
    echo &quot;green up&quot;
    docker-compose -p ${DOCKER_APP_NAME}-green-a -f ${DOCKER_DIR}/docker-compose.green1.yml up -d
    docker-compose -p ${DOCKER_APP_NAME}-green-b -f ${DOCKER_DIR}/docker-compose.green2.yml up -d
    IDLE_PORT=8082
    BEFORE_COMPOSE_COLOR=&quot;blue&quot;
    AFTER_COMPOSE_COLOR=&quot;green&quot;
fi

sleep 5

# 새로운 컨테이너가 제대로 떴는지 확인
EXIST_AFTER_A=$(docker-compose -p ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR}-a -f ${DOCKER_DIR}/docker-compose.${AFTER_COMPOSE_COLOR}&quot;1&quot;.yml ps --status=running | grep ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR}-a)
EXIST_AFTER_B=$(docker-compose -p ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR}-b -f ${DOCKER_DIR}/docker-compose.${AFTER_COMPOSE_COLOR}&quot;2&quot;.yml ps --status=running | grep ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR}-b)
if [ -n &quot;$EXIST_AFTER_A&quot; ] &amp;amp;&amp;amp; [ -n &quot;$EXIST_AFTER_B&quot; ]; then
  #새로운 컨테이너가 뜬 것을 확인 후 Health Check를 통해 해당 spring poject 컨테이너가 잘 실행 되었는지 체크를 진행합니다.
  # health check
  echo &quot;&amp;gt; Health Check Start!&quot;
  echo &quot;&amp;gt; IDLE_PORT: $IDLE_PORT&quot;
  echo &quot;&amp;gt; curl -s http://{Spring project 컨테이너가 띄어지는 서버 ip}:$IDLE_PORT &quot;
  sleep 5

  for RETRY_COUNT in {1..10}
  do
    RESPONSE=$(curl -s http://3.36.66.225:${IDLE_PORT})
    UP_COUNT=$(echo ${RESPONSE} | grep &quot;timestamp&quot; | wc -l)

    if [ ${UP_COUNT} -ge 1 ]
    then # $up_count &amp;gt;= 1
        echo &quot;&amp;gt; Health check 성공&quot;
        #Health check가 정상적으로 성공 된 후 nginx 설정값을 변경해주어야 서버가 다운타임 없이 배포가 진행됩니다.
        # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다
        cp ${NGINX_DIR}/nginx.${AFTER_COMPOSE_COLOR}.conf ${NGINX_DIR}/nginx.conf
        #서버를중단하지 않고 변경된 사항을 적용시켜줌
        docker exec nginx-webserver nginx -s reload

        sleep 5

        # 이전 컨테이너 종료
        docker-compose -p ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR}-a -f ${DOCKER_DIR}/docker-compose.${BEFORE_COMPOSE_COLOR}&quot;1&quot;.yml down
        docker-compose -p ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR}-b -f ${DOCKER_DIR}/docker-compose.${BEFORE_COMPOSE_COLOR}&quot;2&quot;.yml down
        echo &quot;$BEFORE_COMPOSE_COLOR down&quot;
    break

    else
          echo &quot;&amp;gt; Health check의 응답을 알 수 없거나 혹은 실행 상태가 아닙니다.&quot;
          echo &quot;&amp;gt; Health check: ${RESPONSE}&quot;
    fi

    if [ ${RETRY_COUNT} -eq 10 ]
      then
        echo &quot;&amp;gt; Health check 실패. &quot;
        echo &quot;&amp;gt; 엔진엑스에 연결하지 않고 배포를 종료합니다.&quot;
        exit 1
      fi

      echo &quot;&amp;gt; Health check 연결 실패. 재시도...&quot;
      sleep 7
    done

else
  echo &quot;&amp;gt; 새로운 ${AFTER_COMPOSE_COLOR} 컨테이너가 정상적으로 띄워지지 않았습니다.&quot;
fi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로젝트 내에서의 모든 설정은 끝이 났습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Jenkins 서버로 돌아가 Publish Over SSH plugin 을 설치해주도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;9. Jenkins 서버 Publish Over SSH plugin 설치 및 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1403&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNyz2W/btrQZWzvtle/zg91t5jpxJUWUrQKen7hw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNyz2W/btrQZWzvtle/zg91t5jpxJUWUrQKen7hw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNyz2W/btrQZWzvtle/zg91t5jpxJUWUrQKen7hw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNyz2W%2FbtrQZWzvtle%2Fzg91t5jpxJUWUrQKen7hw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;314&quot; data-origin-width=&quot;1403&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins 관리 - Plugin Manager에 들어가 Publish Over SSH 라는 플러그인을 설치해주도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMiBd/btrQ1K5NUSe/mtceYAcFbU6wtd0cUc2Qik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMiBd/btrQ1K5NUSe/mtceYAcFbU6wtd0cUc2Qik/img.png&quot; data-alt=&quot;해당 이미지는 필자가 이전에 ssh-keygen 명령어를 사용할 때 캡쳐한 이미지 이므로 ubuntu로 되어 있습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMiBd/btrQ1K5NUSe/mtceYAcFbU6wtd0cUc2Qik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMiBd%2FbtrQ1K5NUSe%2FmtceYAcFbU6wtd0cUc2Qik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;457&quot; height=&quot;309&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;해당 이미지는 필자가 이전에 ssh-keygen 명령어를 사용할 때 캡쳐한 이미지 이므로 ubuntu로 되어 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668173174666&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ssh-keygen -t rsa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 Jenkins Server 에서 위 명령어를 통해 RSA 방식으로 개인키와 공개키 한 쌍을 생성하도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgkUk9/btrQ0QSYaM9/aKsfD9M52rAKKGODyKeNuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgkUk9/btrQ0QSYaM9/aKsfD9M52rAKKGODyKeNuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgkUk9/btrQ0QSYaM9/aKsfD9M52rAKKGODyKeNuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgkUk9%2FbtrQ0QSYaM9%2FaKsfD9M52rAKKGODyKeNuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1251&quot; height=&quot;241&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668173402336&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/.ssh&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1668173719662&quot; class=&quot;css&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo cat id_rsa.pub&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 경로로 들어가서 ls 를 통해 파일을 확인해보면 개인키와 .pub이 붙은 공개키가 생성된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 해당 공개키를 복사하여 nginx 서버에 등록해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EHYXG/btrQZQ7gyqo/cGC05NySILqlqstkeamSV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EHYXG/btrQZQ7gyqo/cGC05NySILqlqstkeamSV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EHYXG/btrQZQ7gyqo/cGC05NySILqlqstkeamSV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEHYXG%2FbtrQZQ7gyqo%2FcGC05NySILqlqstkeamSV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;108&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N0Z8Q/btrQZg6nmbY/1E5EupuXARVkQWKv8K0FZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N0Z8Q/btrQZg6nmbY/1E5EupuXARVkQWKv8K0FZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N0Z8Q/btrQZg6nmbY/1E5EupuXARVkQWKv8K0FZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN0Z8Q%2FbtrQZg6nmbY%2F1E5EupuXARVkQWKv8K0FZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;235&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668173809951&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo vim authorized_keys&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 vim 편집기를 사용하여 Nginx 서버의 authoraized_key 파일의 기존 공개키 아래에 Jenkins에서 생성한 공개키를 추가해주었습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vim 편집기 사용시 알파벳 O 를 누르면 텍스트가 끝난 지점 다음 줄에서 입력을 시작할 수 있습니다. 복사한 공개키를 붙여넣어 주시고 esc 를 누른 후 :w 를 입력하여 저장한 후 :q 를 입력하여 빠져나와 주도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;1090&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SDEXW/btrQZr0XG2Q/c1gL99K1w6Sdc5QsR2t6dK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SDEXW/btrQZr0XG2Q/c1gL99K1w6Sdc5QsR2t6dK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SDEXW/btrQZr0XG2Q/c1gL99K1w6Sdc5QsR2t6dK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSDEXW%2FbtrQZr0XG2Q%2Fc1gL99K1w6Sdc5QsR2t6dK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;434&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;1090&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Jenkins 서버 설정에 들어와 Publish Over SSH 설정에서 Jenkins 서버에서 생성한 RSA 키 중 개인키를 복사하여 붙여넣어주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1363&quot; data-origin-height=&quot;951&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dM4WE6/btrQZhYs4mO/xe8AciBUBhXKZc9vNkIFR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dM4WE6/btrQZhYs4mO/xe8AciBUBhXKZc9vNkIFR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dM4WE6/btrQZhYs4mO/xe8AciBUBhXKZc9vNkIFR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdM4WE6%2FbtrQZhYs4mO%2Fxe8AciBUBhXKZc9vNkIFR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;690&quot; height=&quot;481&quot; data-origin-width=&quot;1363&quot; data-origin-height=&quot;951&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 아래 &lt;b&gt;Name&lt;/b&gt; 은 Jenkins file에서 사용할 ID 값을 입력한 후 &lt;b&gt;HostName&lt;/b&gt;은 Nginx 서버의 IP 주소를 넣어주도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Username 은 Nginx 서버의 Username을 입력하면 되는데 Ubuntu 인스턴스의 경우는 ubuntu를 입력하여 주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(만약 이름을 변경하셨다면 변경하신 이름을 입력해주세요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Remote Directory는 이제 Jenkins서버에서 보낼 파일을 Nginx 서버의 어느 경로에 위치시킬거냐 라고 생각하시면 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 설정이 끝났다면 이제 Test Configuration 을 진행해주시고 Success가 뜨는지 꼭 확인해 주세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;10. Jenkinsfile 작성 (Publish Over SSH 를 이용한 Nginx 서버의 Docker pull &amp;amp; deploy.sh 실행)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668174533687&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//nginx 패키지와 docker 패키지를 배포할서버로 보낸 후 deploy.sh을 실행
        stage('Remote Server Docker Pull') {
            steps([$class: 'BapSshPromotionPublisherPlugin']) {
                sh 'echo &quot;Remote Server Docker Pull Start&quot;'
                 sshPublisher(
                    continueOnError: false, failOnError: true,
                    publishers: [
                        sshPublisherDesc(
                            configName: &quot;springboot-remote-server&quot;,
                            verbose: true,
                            transfers: [
                                sshTransfer(
                                    execCommand: &quot;docker pull gunyoung/dev:latest&quot;
                                )
                            ]
                        )
                    ]
                 )
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Docker pull 을 성공하였습니다.&quot;
                    )
                    echo &quot;Completed Remote Server Docker pull&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Docker pull 을 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail Remote Server Docker Pull&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;sshPublisherDesc( &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;configName:&amp;nbsp;&quot;springboot-remote-server&quot;, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verbose:&amp;nbsp;true, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transfers:&amp;nbsp;[ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sshTransfer( &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;execCommand:&amp;nbsp;&quot;docker&amp;nbsp;pull&amp;nbsp;gunyoung/dev:latest&quot; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dweFyk/btrQZh5iqfc/Mku73gA1NiuiP5qoHjPXrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dweFyk/btrQZh5iqfc/Mku73gA1NiuiP5qoHjPXrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dweFyk/btrQZh5iqfc/Mku73gA1NiuiP5qoHjPXrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdweFyk%2FbtrQZh5iqfc%2FMku73gA1NiuiP5qoHjPXrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;151&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 configName은 Jenkins 서버에서 설정해준 Publish Over SSH의 Name입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;execCommand 에서는 원격 접속한 서버에서 실행할 명령어를 입력해주는 곳입니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker pull&amp;nbsp; 명령어를 통해 docker hub의 개인 repositopry로부터 push 해준 이미지를 받아오도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668174764305&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//(dev 환경)nginx 패키지와 docker 패키지를 배포할서버로 보낸 후 deploy.sh을 실행
        stage('Dev-Remote Server Exec deploy.sh') {
            when {
                branch &quot;develop&quot;
            }
            steps([$class: 'BapSshPromotionPublisherPlugin']) {
                sh 'echo &quot;Remote Server Deploy start&quot;'
                 sshPublisher(
                    continueOnError: false, failOnError: true,
                    publishers: [
                        sshPublisherDesc(
                            configName: &quot;springboot-remote-server&quot;,
                            verbose: true,
                            transfers: [
                                sshTransfer(
                                    sourceFiles:&quot;nginx/**&quot;,
                                ),
                                sshTransfer(
                                    sourceFiles:&quot;docker-dev/**&quot;,
                                    execCommand: &quot;chmod +x /home/ec2-user/docker-dev/deploy.sh&quot;
                                ),
                                sshTransfer(
                                    execCommand: &quot;/home/ec2-user/docker-dev/deploy.sh&quot;
                                ),
                                sshTransfer(
                                    execCommand: 'docker image prune -f --filter=&quot;dangling=true&quot;'
                                )
                            ]
                        )
                    ]
                 )
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;dev 환경 배포를를 성공하였습니다.&quot;
                    )
                    echo &quot;Completed Remote Server Deploy&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;dev 환경 배포를 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail Remote Server Deploy&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음&amp;nbsp; Stage는 nginx 설정파일이 담긴 nginx 패키지와 deploy.sh과 docker compose 파일이 담긴 docker 패키지를 원격 서버로 보내줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;execCommand:&amp;nbsp;&quot;chmod&amp;nbsp;+x&amp;nbsp;/home/ec2-user/docker-dev/deploy.sh&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 위 명령어를 수행하여 deploy.sh파일을 실행시킬 수 있게 x권한(실행권한)을 위임해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;execCommand:&amp;nbsp;&quot;/home/ec2-user/docker-dev/deploy.sh&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행권한을 위임한 후 deploy.sh을 실행합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;execCommand: 'docker image prune -f --filter=&quot;dangling=true&quot;'&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 Nginx 서버에서도 tag가 사라진 불필요한 이미지가 메모리 공간을 차지하지 않도록 제거해줍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이렇게 모든 Jenkins CI/CD 작업이 모두 완료 되었습니다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 git push 또는 merge를 통해 Jenkins job을 trigger 하면 다음과 같이 정상적으로 빌드가 되고 Slack으로 Stage별 알림이 오는 것을 확인 할 수 있습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;947&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evZlrw/btrQZWGlgsm/jERI9pkTZzINkhGjkrJMXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evZlrw/btrQZWGlgsm/jERI9pkTZzINkhGjkrJMXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evZlrw/btrQZWGlgsm/jERI9pkTZzINkhGjkrJMXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FevZlrw%2FbtrQZWGlgsm%2FjERI9pkTZzINkhGjkrJMXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;323&quot; height=&quot;434&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;947&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oRlDU/btrQYW1toHo/QNO5JV8T0H6TfAXKDumUgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oRlDU/btrQYW1toHo/QNO5JV8T0H6TfAXKDumUgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oRlDU/btrQYW1toHo/QNO5JV8T0H6TfAXKDumUgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoRlDU%2FbtrQYW1toHo%2FQNO5JV8T0H6TfAXKDumUgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;776&quot; height=&quot;193&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정상적으로 Container 가 뜨는 것을 확인할 수 있습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 마지막 4편에서는 오픈소스인 Sonar-bot을 활용하여 Gitea의 PR comment에 자동으로 SonarQube 분석 결과를 남기는 작업을 진행해보도록 하겠습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4편의 내용은 Gitea를 사용할 경우에만 해당이 되니 만약 Github을 사용할 경우에는 아래 참고 블로그 링크를 통해 작업을 진행해보시길 바랍니다! =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668175509089&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Server] 소나큐브(SonarQube) 커뮤니티 무료 버전에서 PR 데코레이션(Pull Request Decoration) 설정 적용하&quot; data-og-description=&quot;SonarQube 유료 버전의 기능으로 Pull Request에 대해 정적 분석 코멘트를 남겨주는 Pull Request Decoration이 있습니다. 하지만 무료 플러그인을 사용하면 유료 버전이 아니여도 해당 기능을 사용할 수 있&quot; data-og-host=&quot;mangkyu.tistory.com&quot; data-og-source-url=&quot;https://mangkyu.tistory.com/229&quot; data-og-url=&quot;https://mangkyu.tistory.com/229&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/JNo3f/hyQxIGU8r5/SJdeFF3KNmqKa6MkO3RyFk/img.png?width=800&amp;amp;height=352&amp;amp;face=493_15_521_46,https://scrap.kakaocdn.net/dn/cjqqbf/hyQxD6FHjm/UJxwjpuoNBEKEywhEUnHJK/img.png?width=800&amp;amp;height=352&amp;amp;face=493_15_521_46,https://scrap.kakaocdn.net/dn/mRWy4/hyQxF4uO9u/BNgcjtSdbTLEQKEkBfmuEk/img.png?width=1270&amp;amp;height=560&amp;amp;face=781_21_832_76&quot;&gt;&lt;a href=&quot;https://mangkyu.tistory.com/229&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mangkyu.tistory.com/229&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/JNo3f/hyQxIGU8r5/SJdeFF3KNmqKa6MkO3RyFk/img.png?width=800&amp;amp;height=352&amp;amp;face=493_15_521_46,https://scrap.kakaocdn.net/dn/cjqqbf/hyQxD6FHjm/UJxwjpuoNBEKEywhEUnHJK/img.png?width=800&amp;amp;height=352&amp;amp;face=493_15_521_46,https://scrap.kakaocdn.net/dn/mRWy4/hyQxF4uO9u/BNgcjtSdbTLEQKEkBfmuEk/img.png?width=1270&amp;amp;height=560&amp;amp;face=781_21_832_76');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Server] 소나큐브(SonarQube) 커뮤니티 무료 버전에서 PR 데코레이션(Pull Request Decoration) 설정 적용하&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SonarQube 유료 버전의 기능으로 Pull Request에 대해 정적 분석 코멘트를 남겨주는 Pull Request Decoration이 있습니다. 하지만 무료 플러그인을 사용하면 유료 버전이 아니여도 해당 기능을 사용할 수 있&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mangkyu.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy/CI CD</category>
      <category>CI/CD</category>
      <category>docker</category>
      <category>Docker hub</category>
      <category>jenkins</category>
      <category>nginx</category>
      <category>sonarqube</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/37</guid>
      <comments>https://0andwild.tistory.com/37#entry37comment</comments>
      <pubDate>Fri, 11 Nov 2022 16:25:27 +0900</pubDate>
    </item>
    <item>
      <title>Jenkins&amp;amp;Springboot CI/CD 정리(2)</title>
      <link>https://0andwild.tistory.com/36</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ct0wEK/btrQTk89QEL/kapgvG0Ek1KYvVr7JGBn7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ct0wEK/btrQTk89QEL/kapgvG0Ek1KYvVr7JGBn7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ct0wEK/btrQTk89QEL/kapgvG0Ek1KYvVr7JGBn7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fct0wEK%2FbtrQTk89QEL%2FkapgvG0Ek1KYvVr7JGBn7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span&gt;Jenkins&amp;amp;Springboot CI/CD 정리(2)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QtOcI/btrQYucLYTb/oDomjsgMOa7HoYRlZuRp30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QtOcI/btrQYucLYTb/oDomjsgMOa7HoYRlZuRp30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QtOcI/btrQYucLYTb/oDomjsgMOa7HoYRlZuRp30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQtOcI%2FbtrQYucLYTb%2FoDomjsgMOa7HoYRlZuRp30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;477&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선 지난 1편에서는 위의 서비스 아키텍쳐의 gradle build와 함께 Jacoco, CheckStyle 설정 및 report 파일 생성 까지 모두 마무리 하였습니다. 이제는 Jacoco와 CheckStyle report를 Sonarqube로 넘겨준 후 Quality Gate를 진행하도록 하겠습니다.=)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 SonarQube의 분석결과를 오픈소스인 Sonar-Bot을 통해 간단하게 Gitea의 PR comment로 남겨주는 방식이 추가 되었는데 이부분은 설정할 부분이 생각보다 많아 다음편에서 소개를 해드리도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. SonarQube 설치 및 셋팅&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Sonarqube를 AWS EC2 프리티어에서 실행시키기에는 버거운 Tool 이라는 것을 알게되어 로컬환경에 도커 컨테이너로 띄우는 방식을 채택하였습니다. 단점은 실제 서버로 사용하려면 필자의 노트북 또는 데스크톱을 계속해서 켜놔야 한다는 점이지만 필자의 경우 연습을 위한 환경이였기에 로컬환경에서 구축을 하기로 하였습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자는 노트북으로 윈도우 운영체제를 사용하고 있기에 Docker Desktop을 설치하여 SonarQube 이미지를 Docker hub로 부터 다운받은 후 Docker Container 로 띄우는 방식을 사용하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 공유기 포트포워딩을 통해 필자의 공인 IP 주소의 9000포트를 열어주어 다른 공인 IP에서도 접속이 가능하도록 하였고, 이를 통해 jenkins와 연동을 할 수 있게 하였습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Docker를 로컬 환경에 설치해주어야 하는데 이 부분은 필자가 정리한 글을 통해 대체를 하도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668099180864&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;도커(Docker) 설치 &amp;amp; 도커(Docker) 명령어 사용방법 총정리&quot; data-og-description=&quot;지난 글에 이어 도커의 명령어와 사용방법을 정리해볼까 합니다 =) 우선 도커를 사용하려면 설치를 해주어야 겠죠? 필자의 경우 AWS EC2 인스턴스로 Ubuntu 환경에서 Docker를 설치하였습니다. (Ubuntu &quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/31&quot; data-og-url=&quot;https://0andwild.tistory.com/31&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/byxETx/hyQxQ5uxHZ/edeaFqZ3eLH99qA01nCek1/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/bxe2II/hyQwHh2Dtm/tXJTOLsdMWYCVnaKtvyoT0/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/PZbhh/hyQxIM9Jyv/04xv2BknBjYizbQdmmsQa1/img.png?width=992&amp;amp;height=532&amp;amp;face=0_0_992_532&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/31&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/31&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/byxETx/hyQxQ5uxHZ/edeaFqZ3eLH99qA01nCek1/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/bxe2II/hyQwHh2Dtm/tXJTOLsdMWYCVnaKtvyoT0/img.png?width=800&amp;amp;height=429&amp;amp;face=0_0_800_429,https://scrap.kakaocdn.net/dn/PZbhh/hyQxIM9Jyv/04xv2BknBjYizbQdmmsQa1/img.png?width=992&amp;amp;height=532&amp;amp;face=0_0_992_532');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;도커(Docker) 설치 &amp;amp; 도커(Docker) 명령어 사용방법 총정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;지난 글에 이어 도커의 명령어와 사용방법을 정리해볼까 합니다 =) 우선 도커를 사용하려면 설치를 해주어야 겠죠? 필자의 경우 AWS EC2 인스턴스로 Ubuntu 환경에서 Docker를 설치하였습니다. (Ubuntu&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 설치가 완료 되었다면 이제 docker pull을 통해 SonarQube 이미지를 다운받아 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nhxBz/btrQTEfcX0v/8uXdrzardzWkJOIY0NebE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nhxBz/btrQTEfcX0v/8uXdrzardzWkJOIY0NebE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nhxBz/btrQTEfcX0v/8uXdrzardzWkJOIY0NebE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnhxBz%2FbtrQTEfcX0v%2F8uXdrzardzWkJOIY0NebE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;246&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker hub의 홈페이지에 들어와 SonarQube를 검색하면 공식 이미지를 확인 할 수 있습니다. Tags를 누르면 버전별 이미지를 확인할 수 있습니다.=)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gitabash, Terminal, PowerShell을 이용해 $ docker pull sonarqube를 하면 최신 버전의 SonarQube 이미지를 받을 수 있으나 필자의 경우 다음편에서 설명 할 Sonar-bot을 사용하는데&amp;nbsp; 필요한 Plugin 설치 및 셋팅에 최신버전이 호환이 되지 않는 문제가 발생하여 8.4 버전을 채택하였고 해당 이미지를 받았습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DbQ3n/btrQUAbYznK/CeRs44gyP5KeHFZJjFcx0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DbQ3n/btrQUAbYznK/CeRs44gyP5KeHFZJjFcx0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DbQ3n/btrQUAbYznK/CeRs44gyP5KeHFZJjFcx0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDbQ3n%2FbtrQUAbYznK%2FCeRs44gyP5KeHFZJjFcx0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1438&quot; height=&quot;215&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;215&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668100181571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker pull sonarqube:8.4.2-community&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 해당 이미지를 다운 받았으며 우측의 복사 버튼을 클릭하면 이미지를 받기위한 명령어가 복사되어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dioV0c/btrQWniD3Te/94FdBi4pXQetEnmOs4boQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dioV0c/btrQWniD3Te/94FdBi4pXQetEnmOs4boQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dioV0c/btrQWniD3Te/94FdBi4pXQetEnmOs4boQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdioV0c%2FbtrQWniD3Te%2F94FdBi4pXQetEnmOs4boQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;97&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668100302674&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되었으면 다음과 같이 명령어를 입력하여 다운받은 이미지를 확인해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0bjnG/btrQTjCtqB8/OMVYFOW1tSjB9uIedqKVQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0bjnG/btrQTjCtqB8/OMVYFOW1tSjB9uIedqKVQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0bjnG/btrQTjCtqB8/OMVYFOW1tSjB9uIedqKVQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0bjnG%2FbtrQTjCtqB8%2FOMVYFOW1tSjB9uIedqKVQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;556&quot; height=&quot;258&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;669&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Docker desktop을 사용하고 있어 다음처럼 확인을 할 수 도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 해당 이미지를 실행시켜 Docker Container로 띄워 보도록 하겠습니다.=)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;69&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AaZkO/btrQTQT3V9S/tbemnKwqkljIxZvMkcXG8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AaZkO/btrQTQT3V9S/tbemnKwqkljIxZvMkcXG8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AaZkO/btrQTQT3V9S/tbemnKwqkljIxZvMkcXG8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAaZkO%2FbtrQTQT3V9S%2FtbemnKwqkljIxZvMkcXG8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;69&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668100997769&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run -d -it --name sonarqube -p 9000:9000 sonarqube&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 -d 옵션은 백그라운드 실행합니다. -it 옵션은 -i 와 -t 옵션을 분리해서 사용할 수 도 있지만 대게 함께 사용합니다. -it 옵션은 컨테이너를 종료하지 않고 컨테이너로 명령어를 전달할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--name 옵션을 통해 사용자가 해당 컨테이너의 이름을 지정해줄 수 있으며 컨테이너 ID 값이 아닌 해당 이름으로 컨테이너 제어 명령어를 사용할 수 있게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-p는 포트번호이며 좌측은 사용자가 url에 입력하여 붙을 수 있는 포트번호이고, 우측은 컨테이너의 내부 포트 번호를 뜻합니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCmdHl/btrQUB2011F/fgVVHqXM4qjEfKAvthXTa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCmdHl/btrQUB2011F/fgVVHqXM4qjEfKAvthXTa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCmdHl/btrQUB2011F/fgVVHqXM4qjEfKAvthXTa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCmdHl%2FbtrQUB2011F%2FfgVVHqXM4qjEfKAvthXTa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1463&quot; height=&quot;109&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668101728037&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 컨테이너를 실행시키고 docker ps 명령어를 통해 띄워진 컨테이너를 확인해주도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SonarQube 컨테이너가 잘 띄워진 것 같군요 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 실행을 시켜봐야 겠죠 ?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2137&quot; data-origin-height=&quot;1178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTaNY3/btrQTE7nlJz/wgJRiXDfNX9kpu2c2nLv70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTaNY3/btrQTE7nlJz/wgJRiXDfNX9kpu2c2nLv70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTaNY3/btrQTE7nlJz/wgJRiXDfNX9kpu2c2nLv70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTaNY3%2FbtrQTE7nlJz%2FwgJRiXDfNX9kpu2c2nLv70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;290&quot; data-origin-width=&quot;2137&quot; data-origin-height=&quot;1178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1668101899448&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;localhost:9000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 로컬 환경에 구축을 하였으므로 localhost:9000 으로 접속을 하였습니다. 버전마다 로그인 화면이 조금씩 다르나 해당 8.4.2 버전의 경우 좌측과 우측 상단에 로그인 버튼이 존재하고 로그인을 해보도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;659&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/edRkC0/btrQVAvNPSW/yE6NroqZJPRYk9pUffl2o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/edRkC0/btrQVAvNPSW/yE6NroqZJPRYk9pUffl2o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/edRkC0/btrQVAvNPSW/yE6NroqZJPRYk9pUffl2o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FedRkC0%2FbtrQVAvNPSW%2FyE6NroqZJPRYk9pUffl2o1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;348&quot; data-origin-width=&quot;659&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SonarQube의 경우 초기 로그인 아이디와 비밀번호는 모두 admin 입니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;1052&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rPDVG/btrQUUH9je6/X7amjixQi9foduepEYdgP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rPDVG/btrQUUH9je6/X7amjixQi9foduepEYdgP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rPDVG/btrQUUH9je6/X7amjixQi9foduepEYdgP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrPDVG%2FbtrQUUH9je6%2FX7amjixQi9foduepEYdgP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;760&quot; height=&quot;359&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;1052&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인을 하면 다음과 같은 창이 나올텐데 필자의 경우 이미 프로젝트 생성과 셋팅이 모두 끝난 상태라 프로젝트가 3개 있는 것을 확인 할 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 셋팅에 앞서 공유기 포트포워딩을 진행하여 9000 포트를 열어주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;만약 로컬환경이 아닌 AWS EC2 환경에 SonarQube 컨테이너를 띄웠다면 아래 내용은 넘어가셔도 무방합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 로컬환경에 구축을 하였기 때문에 다른 IP에서 필자의 로컬 환경에 접속을 할 수 없는 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해선 필자가 사용하고 있는 공유기의 설정에서 9000 포트를 개방하여 다른 IP에서도 필자가 사용하고 있는 공유기의 공인 IP 9000포트로 접속을 할 수 있게 하면 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이부분은 사설망과 공인망에 대한 이해가 필요한 부분인데 필자가 공부를 하며 작성을 해둔 글이 있으니 궁금하신 분은 아래 글을 확인해주시기 바랍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668102696782&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;사설IP/공인IP? 사설망/공중망? VPN?&quot; data-og-description=&quot;사설망 공중망? 어디선가 들어는 보았지만 개념은 잘 몰랐기에 정리를 해보고자 합니다. 위 그림을 처음보면 잉? 하겠지만 글을 모두 읽고나면 아! 하면서 어느정도 이해를 하실 수 있을겁니다 .&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/27&quot; data-og-url=&quot;https://0andwild.tistory.com/27&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cJw4HR/hyQwJUtjRo/vmlryvJDHu71CkPw4T6hpK/img.png?width=288&amp;amp;height=175&amp;amp;face=0_0_288_175,https://scrap.kakaocdn.net/dn/CqiT9/hyQxMvgpmt/xaBzBS7vVbzA1xTtq3xaok/img.png?width=288&amp;amp;height=175&amp;amp;face=0_0_288_175,https://scrap.kakaocdn.net/dn/0YJOi/hyQwBPGpLT/sTKHjJ08JPFKj6Pg7hS9YK/img.png?width=1193&amp;amp;height=889&amp;amp;face=0_0_1193_889&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/27&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/27&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cJw4HR/hyQwJUtjRo/vmlryvJDHu71CkPw4T6hpK/img.png?width=288&amp;amp;height=175&amp;amp;face=0_0_288_175,https://scrap.kakaocdn.net/dn/CqiT9/hyQxMvgpmt/xaBzBS7vVbzA1xTtq3xaok/img.png?width=288&amp;amp;height=175&amp;amp;face=0_0_288_175,https://scrap.kakaocdn.net/dn/0YJOi/hyQwBPGpLT/sTKHjJ08JPFKj6Pg7hS9YK/img.png?width=1193&amp;amp;height=889&amp;amp;face=0_0_1193_889');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;사설IP/공인IP? 사설망/공중망? VPN?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;사설망 공중망? 어디선가 들어는 보았지만 개념은 잘 몰랐기에 정리를 해보고자 합니다. 위 그림을 처음보면 잉? 하겠지만 글을 모두 읽고나면 아! 하면서 어느정도 이해를 하실 수 있을겁니다 .&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필자의 경우 kt 공유기를 사용하고 있어 kt 공유기 주소로 접근해주도록 하겠습니다. 만약 다른 공유기를 사용하고 있으시다면 &lt;b&gt;ex) Iptime 공유기 포트워딩 하는법 &lt;/b&gt;을 검색하시면 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nI0MM/btrQUbXPa4Q/IyikzRkd9o8J3Aut93nkKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nI0MM/btrQUbXPa4Q/IyikzRkd9o8J3Aut93nkKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nI0MM/btrQUbXPa4Q/IyikzRkd9o8J3Aut93nkKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnI0MM%2FbtrQUbXPa4Q%2FIyikzRkd9o8J3Aut93nkKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;539&quot; height=&quot;301&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KT의 경우 &lt;span style=&quot;color: #000000;&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color: #a77f71;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a77f71;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #a77f71;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;homehub&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;olleh&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;com 을 주소창에 입력하면 쉽게 접속하실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처음 초기 아이디와 비밀번호는 다음과 같습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ID: ktuser&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PW: homehub&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDMwaw/btrQUVG3xrU/HaqYgQjNBvTPkxm16kF5eK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDMwaw/btrQUVG3xrU/HaqYgQjNBvTPkxm16kF5eK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDMwaw/btrQUVG3xrU/HaqYgQjNBvTPkxm16kF5eK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDMwaw%2FbtrQUVG3xrU%2FHaqYgQjNBvTPkxm16kF5eK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;743&quot; height=&quot;402&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인을 진행한 후 &lt;b&gt;장치설정 - 트래픽 관리&amp;nbsp;&lt;/b&gt;로 이동을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 이미 9000포트와 추가적으로 9001 포트를 열어 주었는데 9001 포트는 Sonar-bot 컨테이너가 사용중인 포트입니다. 만약 필자와 같이 Gitea를 사용하고 PR comment를 Sonar-bot이 달아주는 것을 원하신다면 미리 9001번 포트도 개방하여 주세요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCPptG/btrQT5QUKIk/0OfpcniFqyFiK7NqON9TM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCPptG/btrQT5QUKIk/0OfpcniFqyFiK7NqON9TM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCPptG/btrQT5QUKIk/0OfpcniFqyFiK7NqON9TM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCPptG%2FbtrQT5QUKIk%2F0OfpcniFqyFiK7NqON9TM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;275&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 입력을 한 후 추가를 해주면 되는데 내부 IP 주소의 경우 cmd 또는 gitbash 등 자신이 사용하는 CLI 툴을 이용해 ipconfig 명령어를 입력하여 아래와 같이 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2sF0X/btrQWXD7Y3F/3p28od57Sj93fM1p66Z5u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2sF0X/btrQWXD7Y3F/3p28od57Sj93fM1p66Z5u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2sF0X/btrQWXD7Y3F/3p28od57Sj93fM1p66Z5u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2sF0X%2FbtrQWXD7Y3F%2F3p28od57Sj93fM1p66Z5u0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;332&quot; height=&quot;89&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DkT1s/btrQVzp6FML/QkukJGCX3W2sKkuVwHNXk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DkT1s/btrQVzp6FML/QkukJGCX3W2sKkuVwHNXk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DkT1s/btrQVzp6FML/QkukJGCX3W2sKkuVwHNXk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDkT1s%2FbtrQVzp6FML%2FQkukJGCX3W2sKkuVwHNXk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;509&quot; height=&quot;96&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 내부 IP주소를 위와 같이 입력을 해준 후 추가를 해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYxIhk/btrQTkg2vR3/Dgf7G4JelvlVjSA6J4FgzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYxIhk/btrQTkg2vR3/Dgf7G4JelvlVjSA6J4FgzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYxIhk/btrQTkg2vR3/Dgf7G4JelvlVjSA6J4FgzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYxIhk%2FbtrQTkg2vR3%2FDgf7G4JelvlVjSA6J4FgzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;96&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k48oK/btrQTDADLdm/y5aju680TxIgNK1ErcbiRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k48oK/btrQTDADLdm/y5aju680TxIgNK1ErcbiRK/img.png&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;348&quot; data-is-animation=&quot;false&quot; width=&quot;165&quot; height=&quot;240&quot; style=&quot;width: 10.1513%; margin-right: 10px;&quot; data-widthpercent=&quot;10.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k48oK/btrQTDADLdm/y5aju680TxIgNK1ErcbiRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk48oK%2FbtrQTDADLdm%2Fy5aju680TxIgNK1ErcbiRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;239&quot; height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEIops/btrQVBapsRE/Zjyk7qMSRmaUfXlUS6DH4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEIops/btrQVBapsRE/Zjyk7qMSRmaUfXlUS6DH4k/img.png&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;163&quot; data-is-animation=&quot;false&quot; width=&quot;559&quot; height=&quot;93&quot; style=&quot;width: 88.6859%;&quot; data-widthpercent=&quot;89.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEIops/btrQVBapsRE/Zjyk7qMSRmaUfXlUS6DH4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEIops%2FbtrQVBapsRE%2FZjyk7qMSRmaUfXlUS6DH4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;978&quot; height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 추가된 목록을 확인 하신 후 시스템정보의 인터넷 연결정보에서 자신이 사용하는 공유기의 공인 IP 주소를 확인할 수 있습니다.=)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 정말 다른 공인 IP에서도 자신이 개방한 9000포트로 접속을 할 수 있는지 확인해 봐야 겠죠?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 필자의 휴대폰으로 {내 공인IP}:9000 으로 접속하여 로컬환경에서 띄운 SonarQube 사이트로 접속이 되는지 확인을 해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;1304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4usyT/btrQTSqLykX/DBpBwSY8HZNhwFj0lYvZv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4usyT/btrQTSqLykX/DBpBwSY8HZNhwFj0lYvZv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4usyT/btrQTSqLykX/DBpBwSY8HZNhwFj0lYvZv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4usyT%2FbtrQTSqLykX%2FDBpBwSY8HZNhwFj0lYvZv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;217&quot; height=&quot;489&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;1304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속이 정상적으로 잘 이루어졌습니다 ! 이제 포트포워딩 작업은 끝이 났고 Jenkins와 연결을 해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/37OcQ/btrQT7uq4EM/fIHcdHa9u59Vg3Zw5whDPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/37OcQ/btrQT7uq4EM/fIHcdHa9u59Vg3Zw5whDPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/37OcQ/btrQT7uq4EM/fIHcdHa9u59Vg3Zw5whDPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F37OcQ%2FbtrQT7uq4EM%2FfIHcdHa9u59Vg3Zw5whDPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;498&quot; height=&quot;212&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6L1sa/btrQTjCt3Am/B90n2qtzZgQPRZfwSPELck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6L1sa/btrQTjCt3Am/B90n2qtzZgQPRZfwSPELck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6L1sa/btrQTjCt3Am/B90n2qtzZgQPRZfwSPELck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6L1sa%2FbtrQTjCt3Am%2FB90n2qtzZgQPRZfwSPELck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;398&quot; height=&quot;335&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;523&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Sonarqube에서 프로젝트를 하나 생성하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름은 자신이 사용하고 싶은 이름을 사용하시면 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Project Key와 Display이름은 동일하게 맞추어지는데 key 값을 다르게 하셔도 상관없습니다. 다만 jenkins와 연동 시 SonarQube properties 설정에서 해당 key값과 name을 입력해주어야 하는데 헷갈리지 않으려면 함께 사용하는게 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX0yZV/btrQUVfXJCF/bmjQOTkTc3RI6KmIsRV9Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX0yZV/btrQUVfXJCF/bmjQOTkTc3RI6KmIsRV9Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX0yZV/btrQUVfXJCF/bmjQOTkTc3RI6KmIsRV9Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX0yZV%2FbtrQUVfXJCF%2FbmjQOTkTc3RI6KmIsRV9Gk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;300&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 token을 생성해주어야 하는데 처음 사용을 하였더라면 설정된 token 값이 없을 겁니다. 그러므로 원하는 이름을 입력한 후 token 생성을 해주도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJU2PD/btrQWWrHaWd/fdFMW9p74rU6M4CmCTZTy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJU2PD/btrQWWrHaWd/fdFMW9p74rU6M4CmCTZTy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJU2PD/btrQWWrHaWd/fdFMW9p74rU6M4CmCTZTy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJU2PD%2FbtrQWWrHaWd%2FfdFMW9p74rU6M4CmCTZTy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;180&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;393&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;generate 버튼을 누르면 token이 생성되는데 해당 토큰은 Jenkins credential에 등록해주어야 하니 꼭 메모장이나 어딘가에 token 값을 저장해 주세요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;789&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xIk15/btrQUBvaIox/tPvP8YZ5DNjdES88wEpMQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xIk15/btrQUBvaIox/tPvP8YZ5DNjdES88wEpMQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xIk15/btrQUBvaIox/tPvP8YZ5DNjdES88wEpMQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxIk15%2FbtrQUBvaIox%2FtPvP8YZ5DNjdES88wEpMQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;507&quot; height=&quot;286&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;789&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 Sonarqube의 home으로 돌아오면 방금 생성한 프로젝트를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;782&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbzeDI/btrQTSdhr3H/wqr8ysX5kBukmMljlYyqQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbzeDI/btrQTSdhr3H/wqr8ysX5kBukmMljlYyqQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbzeDI/btrQTSdhr3H/wqr8ysX5kBukmMljlYyqQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbzeDI%2FbtrQTSdhr3H%2Fwqr8ysX5kBukmMljlYyqQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;392&quot; height=&quot;302&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;782&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Jenkins에 대한 webhook을 설정해주어야 하는데 &lt;b&gt;Administration - Configuration - Webhook&lt;/b&gt; 으로 들어와주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1877&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brkHtI/btrQWYbYobS/f2dkzg6SiOPTT9YJmRkxyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brkHtI/btrQWYbYobS/f2dkzg6SiOPTT9YJmRkxyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brkHtI/btrQWYbYobS/f2dkzg6SiOPTT9YJmRkxyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrkHtI%2FbtrQWYbYobS%2Ff2dkzg6SiOPTT9YJmRkxyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;85&quot; data-origin-width=&quot;1877&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmVISx/btrQTRk46tF/u802vBcKA7dBKeTgPLb4m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmVISx/btrQTRk46tF/u802vBcKA7dBKeTgPLb4m1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmVISx/btrQTRk46tF/u802vBcKA7dBKeTgPLb4m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmVISx%2FbtrQTRk46tF%2Fu802vBcKA7dBKeTgPLb4m1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;333&quot; height=&quot;345&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;609&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668105554179&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://{자신의 젠킨스서버 public IP}:{젠킨스포트번호}/sonarqube-webhook/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;create를 눌러준 후 다음과 같이 입력을하고 생성을 해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 설정을 하면 글로벌 설정이 되어 Sonarqube의 모든 프로젝트에 해당 webhook이 적용되어 지는데 필자는 dev환경 분석과 PR 분석을 위한 프로젝트 모두 같은 Jenkins를 바라보기 때문에 해당 웹훅은 글로벌로 설정을 해두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 프로젝트 별 웹훅 설정을 원하는 경우 아래와 같이 프로젝트 내에서 &lt;b&gt;Project Setting - Webhook&amp;nbsp;&lt;/b&gt;에 들어가 프로젝트별로 webhook 설정을 다르게 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cK8yiq/btrQTE7n2yf/gPOfVEMvxBzIbKWC3tBYk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cK8yiq/btrQTE7n2yf/gPOfVEMvxBzIbKWC3tBYk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cK8yiq/btrQTE7n2yf/gPOfVEMvxBzIbKWC3tBYk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcK8yiq%2FbtrQTE7n2yf%2FgPOfVEMvxBzIbKWC3tBYk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;594&quot; height=&quot;170&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Jenkins에 들어가 SonarQube 설정을 해주도록 하겠습니다. =)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bct6oo/btrQSENA2Aw/xteGYOgjTXw7MIFKLv2Pj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bct6oo/btrQSENA2Aw/xteGYOgjTXw7MIFKLv2Pj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bct6oo/btrQSENA2Aw/xteGYOgjTXw7MIFKLv2Pj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbct6oo%2FbtrQSENA2Aw%2FxteGYOgjTXw7MIFKLv2Pj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;577&quot; height=&quot;296&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TXgsh/btrQWlLUXOJ/mdvykL6k3D8GfpuP3ASjdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TXgsh/btrQWlLUXOJ/mdvykL6k3D8GfpuP3ASjdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TXgsh/btrQWlLUXOJ/mdvykL6k3D8GfpuP3ASjdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTXgsh%2FbtrQWlLUXOJ%2FmdvykL6k3D8GfpuP3ASjdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;557&quot; height=&quot;224&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;507&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/quJoK/btrQSX7kWUA/w5DKVYNddW69x4zl1tqvs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/quJoK/btrQSX7kWUA/w5DKVYNddW69x4zl1tqvs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/quJoK/btrQSX7kWUA/w5DKVYNddW69x4zl1tqvs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FquJoK%2FbtrQSX7kWUA%2Fw5DKVYNddW69x4zl1tqvs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;75&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins관리 - 플러그인 관리&amp;nbsp;&lt;/b&gt;에 들어와 &lt;b&gt;Sonar Quality Gates Plugin&lt;/b&gt;과 &lt;b&gt;SonarQube Scanner for Jenkins&amp;nbsp;&lt;/b&gt;플러그인을 설치해주도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1311&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUWmg6/btrQVaqAqd6/pfQKHKfU7TNzMuktRdTg90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUWmg6/btrQVaqAqd6/pfQKHKfU7TNzMuktRdTg90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUWmg6/btrQVaqAqd6/pfQKHKfU7TNzMuktRdTg90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUWmg6%2FbtrQVaqAqd6%2FpfQKHKfU7TNzMuktRdTg90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;379&quot; height=&quot;161&quot; data-origin-width=&quot;1311&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blNMdh/btrQT6bgjRl/ekIQAAcEnD9bbpEP3HvOSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blNMdh/btrQT6bgjRl/ekIQAAcEnD9bbpEP3HvOSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blNMdh/btrQT6bgjRl/ekIQAAcEnD9bbpEP3HvOSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblNMdh%2FbtrQT6bgjRl%2FekIQAAcEnD9bbpEP3HvOSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;570&quot; height=&quot;102&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;169&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;879&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxyOaE/btrQUu32u2c/b4yYKQUcst3X5Cp51rHgXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxyOaE/btrQUu32u2c/b4yYKQUcst3X5Cp51rHgXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxyOaE/btrQUu32u2c/b4yYKQUcst3X5Cp51rHgXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxyOaE%2FbtrQUu32u2c%2Fb4yYKQUcst3X5Cp51rHgXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;231&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;879&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 SonarQube에 대한 credential 을 등록해주도록 하겠습니다. &lt;b&gt;Manage Credentials&lt;/b&gt;로 들어와&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;grobal의 add credentials&lt;/b&gt;를 눌러주고 &lt;b&gt;kind는 Secret text&lt;/b&gt;로 설정해주겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Secret&lt;/b&gt; = Sonarqube 프로젝트 생성시 발급한 토큰 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ID&lt;/b&gt; = Jenkins 파이프라인에서 사용할 ID &lt;b&gt;(해당 ID로 Jenkinsfile에서 Sonarqube token값을 전달 받습니다.)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Description&lt;/b&gt; = 해당 키에 대한 설명&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;1167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buwoqT/btrQUuQvdL5/Op8iv8FO6jNFMUUXoJeY11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buwoqT/btrQUuQvdL5/Op8iv8FO6jNFMUUXoJeY11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buwoqT/btrQUuQvdL5/Op8iv8FO6jNFMUUXoJeY11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuwoqT%2FbtrQUuQvdL5%2FOp8iv8FO6jNFMUUXoJeY11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;372&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;1167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYW21I/btrQUAQAOPA/gllqXUkjiTPxDZwkKqBS21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYW21I/btrQUAQAOPA/gllqXUkjiTPxDZwkKqBS21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYW21I/btrQUAQAOPA/gllqXUkjiTPxDZwkKqBS21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdYW21I%2FbtrQUAQAOPA%2FgllqXUkjiTPxDZwkKqBS21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;504&quot; height=&quot;143&quot; data-origin-width=&quot;1313&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLF01D/btrQWmqw6WS/qxJNDuKu9VxODcT1G1kFkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLF01D/btrQWmqw6WS/qxJNDuKu9VxODcT1G1kFkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLF01D/btrQWmqw6WS/qxJNDuKu9VxODcT1G1kFkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLF01D%2FbtrQWmqw6WS%2FqxJNDuKu9VxODcT1G1kFkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1294&quot; height=&quot;227&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 SonarQube관련 플러그인이 모두 설치 되었다는 가정하에 설정을 진행해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkins관리 - Configure System&lt;/b&gt;에 들어오면 &lt;b&gt;SonarQube Server&lt;/b&gt; 라는 부분이 생성된 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Name&lt;/b&gt; = Jenkinsfile 에서 installtionName으로 사용될 값입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Server URL&lt;/b&gt;= 필자의 경우 공유기 포트포워딩을 해두었기 때문에 http://필자의 공유기 IP:9000 으로 지정해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Server authentication token&lt;/b&gt; = 위에서 생성한 sonarqube&amp;nbsp; crendential 을 등록해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고급 버튼을 누르면 위처럼 Sonarqube의 properties를 설정할 수 있는 부분이 있는데 필자는 projectKey와 projectName만 여기에서 등록을 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자처럼 위 값을 jenkins에서 관리를 하여도 되고, 모든 sonarQube 설정을 springboot 프로젝트의 루트 디렉토리에 sonar.properties를 생성하여 관리를 하여도 무방합니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Sonar-Scanner 설정을 진행해보도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhdwXp/btrQVZWvysb/aOUvKiDMSV5xO5NNKNSwW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhdwXp/btrQVZWvysb/aOUvKiDMSV5xO5NNKNSwW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhdwXp/btrQVZWvysb/aOUvKiDMSV5xO5NNKNSwW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhdwXp%2FbtrQVZWvysb%2FaOUvKiDMSV5xO5NNKNSwW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;227&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bW8aMH/btrQVsxRvQT/8iZHFnXtlHmztjoZewQ5qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bW8aMH/btrQVsxRvQT/8iZHFnXtlHmztjoZewQ5qK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bW8aMH/btrQVsxRvQT/8iZHFnXtlHmztjoZewQ5qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbW8aMH%2FbtrQVsxRvQT%2F8iZHFnXtlHmztjoZewQ5qK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;204&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Sonar-Scanner &lt;/b&gt;플러그인이 정상적으로 설치 되었다면 &lt;b&gt;Global Tool Configuration&lt;/b&gt; 에 위와 같은 설정 항목이 생겼을 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;827&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qSQRr/btrQVA3Ds9v/hJGIsvsAfD7sKue7Gnlehk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qSQRr/btrQVA3Ds9v/hJGIsvsAfD7sKue7Gnlehk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qSQRr/btrQVA3Ds9v/hJGIsvsAfD7sKue7Gnlehk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqSQRr%2FbtrQVA3Ds9v%2FhJGIsvsAfD7sKue7Gnlehk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;365&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpd5Ij/btrQT5QVA0P/nldcAFbf7JMfUd7zuUGjG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpd5Ij/btrQT5QVA0P/nldcAFbf7JMfUd7zuUGjG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpd5Ij/btrQT5QVA0P/nldcAFbf7JMfUd7zuUGjG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdpd5Ij%2FbtrQT5QVA0P%2FnldcAFbf7JMfUd7zuUGjG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;348&quot; data-origin-width=&quot;1317&quot; data-origin-height=&quot;843&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정을 진행해주는데 SonarQube Scanner 의 Name 부분은 자신이 사용하고자 하는 이름을 사용해주면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFaLdr/btrQSYLWKLk/2zV7cMGHCZsesBM7l2Ean0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFaLdr/btrQSYLWKLk/2zV7cMGHCZsesBM7l2Ean0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFaLdr/btrQSYLWKLk/2zV7cMGHCZsesBM7l2Ean0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFaLdr%2FbtrQSYLWKLk%2F2zV7cMGHCZsesBM7l2Ean0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;163&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 마찬가지로 Jenkinsfile에서 Sonnar-analysis Stage의 Sonnar-Scanner tool 에 명시해줄 이름입니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jenkinsfile에서 위 이름으로 sh 을 실행하면 Jenkins에서 등록한 Sonar-Scanner 를 사용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Jenkins와 SonarQube에서의 작업은 모두 끝났습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkinsfile에 pipeline을 작성해보도록 하죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;

&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Jenkinsfile 작성 (SonarQube)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 1편 에서는 gradle build 단계까지 작성을 하였고 이어서 SonarQube Stage를 작성하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkinsfile 풀 소스코드는 필자의 깃헙에서 확인하실 수 있으니 아래 링크를 통해 확인해주세요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1668109045051&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - 0AndWild/Jenkins-CICD&quot; data-og-description=&quot;Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oI4xn/hyQwEeydkZ/mcAe2GoGWAiyAUlbzo7Prk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oI4xn/hyQwEeydkZ/mcAe2GoGWAiyAUlbzo7Prk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - 0AndWild/Jenkins-CICD&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668109287855&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Sonarqube Scanner - dev
        stage(&quot;sonarqube analysis-dev&quot;) {
            when {
                branch &quot;develop&quot;
            }
            steps{
                script{
                    def scannerHome = tool 'jenkins에서 등록한 Sonnar-Scanner Name';
                    withSonarQubeEnv(credentialsId:&quot;Jenkins에서 등록한 SonarQube Crendential ID&quot;,installationName:'Jenkins SonarQube Server설정의 Name') {
                    sh &quot;${scannerHome}/bin/sonar-scanner \
                        -Dsonar.branch.name=master \
                        -Dsonar.language=java \
                        -Dsonar.java.source=1.8 \
                        -Dsonar.sources=src/main/java \
                        -Dsonar.test=src/test/java \
                        -Dsonar.test.inclusion=**/*Test.java \
                        -Dsonar.issuesReport.console.enable=true \
                        -Dsonar.junit.reportPaths=build/test-results/test \
                        -Dsonar.java.binaries=build/classes \
                        -Dsonar.java.coveragePlugin=jacoco \
                        -Dsonar.coverage.jacoco.xmlReportPaths=build/jacoco/jacoco.xml \
                        -Dsonar.java.libraries.empty=true \
                        -Dsonar.sourceEncoding=UTF-8 \
                        -Dsonar.exclusions=**/dto/**,**/exception/**,**/constant/**,**/SpringInitProjectApplication.java,**/WebRestController.java,**/FileUploadYaml.java \
                        -Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \
                        -Dsonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=web \
                        -Dsonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.5.0.jar=ce \
                        &quot;
                    }
                }
            }
            post{
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Dev branch SonarQube Scanning 을 성공하였습니다.&quot;
                    )
                    echo &quot;Success sonarqube analysis&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Dev branch SonarQube Scanning 을 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail sonarqube analysis&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에 대한 설명을 드리자면 해당 Stage는 SonarQube-Scanner 를 이용하여 설정된 파일을 읽고 분석을 하는 과정입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stage안의 when{develop} 은 Jenkins build가 develop branch로의 merge 또는 push가 일어났을 때만 해당 Stage가 작동하도록 해줍니다. prod 환경이 배포될 main branch의 경우 이미 develop branch에서 모든 분석과 수정 및 테스트가 끝나고 배포되는 환경이기에 SonarQube Stage를 Skip 하게 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stage 안의 sh ' ' 부분을 보시면 -Dsonar. 으로 시작하는 설정들이 존재하는데 이 설정들은 SonarQube 분석 시 사용될 설정들을 말합니다. 분석을 할 패키지의 위치를 명시해주고 inclusion 과&amp;nbsp; exclusion 설정을 통해 분석 시 포함할 항목과 배제할 항목을 지정해줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar.branch.name=master 는 SonarQube에서 생성한 프로젝트에 분석결과를 등록할 branch name인데 SonarQube설정을 통해 default branch 이름을 변경하지 않는 한 master로 잡혀 있습니다. 또한 이 설정은 sonar-bot의 pr commnet 를 사용하지 않을 것 이라면 지워주셔도 무방합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jacoco를 사용하고 있다면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar.java.coveragePlugin=jacoco \&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar.coverage.jacoco.xmlReportPaths=build/jacoco/jacoco.xml \ 여기에서 jacoco.xml report가 생성되는 위치를&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 명시해주어야 SonarQube에서 해당 report를 읽어들일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CheckStyle을 통해 코드 컨벤션 분석 결과를 SonarQube로 보내기 위해 생성된 xml 파일의 위치를 명시해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar. 으로 시작하는 설정들은 필자가 Jenkins에서 SonarQube 설정 시 말한 것 처럼 프로젝트 root경로에 sonar.properties를 만들어 따로 관리하여도 상관이 없습니다. 위 코드가 지져분해 보인다면 입맛에 맞추어 관리하여도 문제가 되지 않을 것 같습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Dsonar의 맨 밑 2줄을 보시면 -Dsonar.web&amp;nbsp; 과&amp;nbsp; -Dsonar.ce 부분은 다음번에 설명할 Sonar-bot 을 사용할 때 Community-branch-plugin 을 직접 설치하여 설정하는 부분인데 Sonar-bot을 사용하지 않을 것 이라면&amp;nbsp; 위 두 줄은 지워도 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668110641480&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//SonarQube Quality Gate
        stage('SonarQube Quality Gate'){
            when {
                branch &quot;develop&quot;
            }
            steps{
                timeout(time: 1, unit: 'MINUTES') {
                    script{
                        echo &quot;Start~~~~&quot;
                        def qg = waitForQualityGate()
                        echo &quot;Status: ${qg.status}&quot;
                        if(qg.status != 'OK') {
                            echo &quot;NOT OK Status: ${qg.status}&quot;
                            error &quot;Pipeline aborted due to quality gate failure: ${qg.status}&quot;
                        } else{
                            echo &quot;OK Status: ${qg.status}&quot;
                        }
                        echo &quot;End~~~~&quot;
                    }
                }
            }
            post{
                success {
                    echo &quot;Success sonarqube analysis&quot;
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;SonarQube Quality Gate 를 통과하였습니다.&quot;
                    )
                }
                failure {
                    echo &quot;Fail sonarqube analysis&quot;
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;SonarQube Quality Gate 를 통과하지 못하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; +
                        &quot;==================================================================&quot;
                    )
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SonarQube의 마지막 Stage는 SonarQube Quality Gate 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;qg 라는 변수에 waitForQualityGate() 라는 설정을 담아주었는데 이는 SonarQube analysis가 끝날 때 까지 기다린 후 결과 값을 반환하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3ndM5/btrQUBaVovP/LiK8gMBTnlQV4QgqRK0h51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3ndM5/btrQUBaVovP/LiK8gMBTnlQV4QgqRK0h51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3ndM5/btrQUBaVovP/LiK8gMBTnlQV4QgqRK0h51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3ndM5%2FbtrQUBaVovP%2FLiK8gMBTnlQV4QgqRK0h51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;661&quot; height=&quot;201&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;qg.status 가 ok 즉, 모든 분석 결과가 SonarQube Quality Gate를 통과하게 된다면 ok 를 반환하게 되고 해당 Stage를 통과 하게 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1781&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7O3YB/btrQUVNPWll/Y3DnsZRdklI4sUrNkGT5f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7O3YB/btrQUVNPWll/Y3DnsZRdklI4sUrNkGT5f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7O3YB/btrQUVNPWll/Y3DnsZRdklI4sUrNkGT5f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7O3YB%2FbtrQUVNPWll%2FY3DnsZRdklI4sUrNkGT5f1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;277&quot; data-origin-width=&quot;1781&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SonarQube Quality Gate 는 default로 잡혀 있는 설정이 있지만 만약 이 설정 값이 자신이 진행하고자 하는 프로젝트에 너무 높은 기준치라 판단되거나 좀 더 수정이 필요하다면 Quality Gates 설정에서 커스텀이 가능합니다. 위는 default로 잡혀 잇는 SonarWay 라는 이름의 Quality Gate 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQyOhE/btrQTEl3zPd/Ynb6sE9XmdD7bNc1kG7Ub1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQyOhE/btrQTEl3zPd/Ynb6sE9XmdD7bNc1kG7Ub1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQyOhE/btrQTEl3zPd/Ynb6sE9XmdD7bNc1kG7Ub1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQyOhE%2FbtrQTEl3zPd%2FYnb6sE9XmdD7bNc1kG7Ub1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;274&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Quality Gate 설정에서 좌측의 create 버튼을 누른 후 사요할 Quality Gate의 이름을 입력해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ0vbc/btrQTQ7AtgA/pmLBIkdqZgiMBockb2lbcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ0vbc/btrQTQ7AtgA/pmLBIkdqZgiMBockb2lbcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ0vbc/btrQTQ7AtgA/pmLBIkdqZgiMBockb2lbcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ0vbc%2FbtrQTQ7AtgA%2FpmLBIkdqZgiMBockb2lbcK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;351&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;781&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Add Condition을 누르면 다음과 같은 창이 뜨는데 여기에서 자신이 Quality Gate에서 사용할 항목들을 하나하나 추가하고 수치들을 설정할 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pb4gH/btrQTQNgyEH/zDjEwO2CndC57Kcshihyqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pb4gH/btrQTQNgyEH/zDjEwO2CndC57Kcshihyqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pb4gH/btrQTQNgyEH/zDjEwO2CndC57Kcshihyqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPb4gH%2FbtrQTQNgyEH%2FzDjEwO2CndC57Kcshihyqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;174&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsV2bC/btrQSX7lPvy/bbV8D1ct7Fo63cdmTnKXAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsV2bC/btrQSX7lPvy/bbV8D1ct7Fo63cdmTnKXAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsV2bC/btrQSX7lPvy/bbV8D1ct7Fo63cdmTnKXAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsV2bC%2FbtrQSX7lPvy%2FbbV8D1ct7Fo63cdmTnKXAk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;429&quot; height=&quot;319&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신이 사용할 항목들을 모두 추가한 Quality Gates 를 만들었다면 이제 프로젝트 내의 &lt;b&gt;Project Setting&lt;/b&gt;의 &lt;b&gt;Quality Gate&amp;nbsp;&lt;/b&gt;설정에서 생성한 Quality Gate를 지정할 수 있습니다. 이렇게 하면 SonarQube의 해당 프로젝트는 지정된 Quality Gate를 통해 분석결과를 실패시키거나 성공시키게 됩니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 SonarQube 설정과 setting 설명이 길어져 여기서 끊고 다음 Stage인 docker image build 와 Docker hub 연동, nginx 를 이용한 blue &amp;amp; green 배포는 3편에서 이어 가도록 하겠습니다. =(&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy/CI CD</category>
      <category>checkstyle</category>
      <category>docker</category>
      <category>jacoco</category>
      <category>jenkins</category>
      <category>Jenkins CI/CD</category>
      <category>Sonar Quality Gate</category>
      <category>sonarqube</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/36</guid>
      <comments>https://0andwild.tistory.com/36#entry36comment</comments>
      <pubDate>Fri, 11 Nov 2022 05:33:55 +0900</pubDate>
    </item>
    <item>
      <title>Jenkins&amp;amp;Springboot CI/CD 정리(1)</title>
      <link>https://0andwild.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu5nFN/btrQqMYM6nl/Lk0xweCPWMzZaz3dnqJUvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu5nFN/btrQqMYM6nl/Lk0xweCPWMzZaz3dnqJUvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu5nFN/btrQqMYM6nl/Lk0xweCPWMzZaz3dnqJUvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu5nFN%2FbtrQqMYM6nl%2FLk0xweCPWMzZaz3dnqJUvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Jenkins&amp;amp;Springboot&amp;nbsp;CI/CD&amp;nbsp;정리(1)&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자가 경험한 Springboot 프로젝트와 Jenkins CI 를 활용한 CI/CD 구축에 대해 정리를 해보고자 합니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 시리즈에서는 이미 작성된 내용에 대해선 해당 글로 대체 할 예정이니 참고바랍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자의 경우 Springboot&amp;amp;Gradle 을 이용하였고, SonarQube의 경우 Ec2 프리티어에서 돌리기 버거워 로컬에서 설치 후 공유기 포트포워딩을 통해 Ec2 인스턴스와 연결하였습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Nginx 배포 방식은 Blue&amp;amp;Green 배포 방식을 사용하였습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 JenkinsPipeline의 jenkinsfile은 필자의 Github에 공유되어 있으니 아래 링크를 참고하여 주세요. =)&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667596097829&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - 0AndWild/Jenkins-CICD&quot; data-og-description=&quot;Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cxtcd7/hyQtyw0lip/9qKbBNeHII3l9I49b7NOPk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/0AndWild/Jenkins-CICD&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/0AndWild/Jenkins-CICD&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cxtcd7/hyQtyw0lip/9qKbBNeHII3l9I49b7NOPk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - 0AndWild/Jenkins-CICD&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to 0AndWild/Jenkins-CICD development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byLX6A/btrQYEl1m34/T7DpEChurJRFX3KRMA2eH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byLX6A/btrQYEl1m34/T7DpEChurJRFX3KRMA2eH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byLX6A/btrQYEl1m34/T7DpEChurJRFX3KRMA2eH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyLX6A%2FbtrQYEl1m34%2FT7DpEChurJRFX3KRMA2eH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;477&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;먼저 대략적인 서비스 아키텍쳐입니다. (2022.11.11 수정됨)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(Flow)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 스프링프로젝트에서 feature branch 단위로 작업 후 해당 branch로 푸시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. dev branch로 풀리퀘스트 발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 풀리퀘스트에 대한 Merge 발생(Gitea&amp;amp;Jenkins webhook 발동)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Gitea에서 Sonar-bot으로 웹훅 발동(pending)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. Jenkins Multibranch Pipeline 프로젝트 build가 trigger됨&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. Jenkinsfile의 파이프라인 수행 시작&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7. Gitea Repository 체크아웃&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8. Gradle build 수행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;9. Gradle 빌드시 unit test를 통해 Jacoco 코드커버리지 report 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10. Gradle 빌드시 CheckStyle을 통해 코드컨벤션 리포트 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;11. SonarQube Scanner를 통해 Sonar analysis 시작&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12. jacoco xml 리포트와 CheckStyle 리포트를 통해 SonarQuality Gate 충족 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;13. SonarQube Quality Gate를 충족하면 통과 아니면 Jenkins 빌드 실패&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;14. SonarQube에서 Sonar-bot 으로 webhook 웹훅 발동&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;15. SonarQube 결과를 Gitea PR comment에 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;16. SonarQube Quality Gate가 통과된 jar 파일 Docker Image 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;17. Jenkins Plugin인 Publish Over SSH 를 통해 2번째 Ec2인스턴스에 Docker Compose.yml, Nginx파일, Deploy.sh 파일 전송&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;18. Deploy.sh 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;19. Nginx 컨테이너 띄워져있지 않으면 Docker Compose 파일로 Nginx 컨테이너 실행, 실행중이면 skip&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;20. Blue 컨테이너 띄워져 있는지 확인 없으면 Blue up&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;21. 만약 이미 Blue 컨테이너가 띄어져 있으면 Green up 후 Green 컨테이너에 배포 후 컨테이너 스위칭&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;22. Green 컨테이너로 스위칭후 컨테이너가 잘 떠있는지 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;23. Green이 정상적으로 띄워졌으면 Nginx conf 파일을 Green 컨테이너에 맞추어 변경후 reload&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;24. 이전 컨테이너인 Blue 컨테이너 down&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 AWS Ec2 인스턴스가 2개가 필요한데 필자의 경우 프리티어를 사용하기 위해 AWS 계정 2개를 가입하여 사용하였습니다. 하나의 계정으로 프리티어 인스턴스를 여러개 많들 수 있지만 이럴경우 한달에 750시간의 프리티어 시간이 빠르게 소모되어 과금이 될 수 있으므로 계정을 분리하여 사용하는 것이 좋습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS가입은 생략을 하고 EC2인스턴스를 생성해보도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(깨알지식)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2는 Elastic Compute Cloud의 약자로 단어의 앞글자인 C가 2개 들어가 EC2라고 합니다.=)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. EC2인스턴스 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBMFEx/btrQrEez87X/GiH7rJGr1IlnAznZ8jDUK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBMFEx/btrQrEez87X/GiH7rJGr1IlnAznZ8jDUK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBMFEx/btrQrEez87X/GiH7rJGr1IlnAznZ8jDUK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBMFEx%2FbtrQrEez87X%2FGiH7rJGr1IlnAznZ8jDUK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;493&quot; height=&quot;267&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS가입 후 좌측 서비스 카테고리를 살펴 보시면 EC2라는 카테고리가 보입니다. 클릭 후 이동을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wZiJU/btrQqLFzKwK/ZoMfMWAFPxwGwVaCO0AKW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wZiJU/btrQqLFzKwK/ZoMfMWAFPxwGwVaCO0AKW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wZiJU/btrQqLFzKwK/ZoMfMWAFPxwGwVaCO0AKW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwZiJU%2FbtrQqLFzKwK%2FZoMfMWAFPxwGwVaCO0AKW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1844&quot; height=&quot;673&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이동을 하였다면 우측 상단에 나라를 서울로 바꾸어 주도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1790&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czWe7x/btrQp6pVzuX/1MHkm78CjkNsBqJbrHk7UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czWe7x/btrQp6pVzuX/1MHkm78CjkNsBqJbrHk7UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czWe7x/btrQp6pVzuX/1MHkm78CjkNsBqJbrHk7UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczWe7x%2FbtrQp6pVzuX%2F1MHkm78CjkNsBqJbrHk7UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1790&quot; height=&quot;380&quot; data-origin-width=&quot;1790&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 이미 인스턴스가 생성이 되어 있는 상태지만 인스턴스 시작 버튼을 통해 인스턴스를 생성해보도록 하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;1168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OVCqa/btrQqJAVUBo/FCWETaqrGd1weL6Q7NY3ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OVCqa/btrQqJAVUBo/FCWETaqrGd1weL6Q7NY3ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OVCqa/btrQqJAVUBo/FCWETaqrGd1weL6Q7NY3ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOVCqa%2FbtrQqJAVUBo%2FFCWETaqrGd1weL6Q7NY3ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;392&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;1168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 시작버튼을 누르면 다음과 같은 화면이 나올겁니다. 여기에서 먼저 애플리케이션 및 OS 이미지 부분을 확인해보도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보시면 여러가지 OS이미지들이 보이실텐데 여기에서 자신이 사용하고자 하는 AWS EC2 OS를 선택해주면 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Ubuntu를 사용해본 경험이 있어 첫번째 인스턴스는 Ubuntu를 선택하였고 두번째 인스턴스는 Amazon Linux를 선택하였습니다. 각 OS마다 사용하는 명령어가 다르니 자신이 편한 것을 선택해주면 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 많은 AMI를 누르시면 다음과 같이 더 많은 정보를 다음과 같이 확인할 수 있습니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1813&quot; data-origin-height=&quot;1111&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxCg5C/btrQq6imXqM/E4awwpRLCKi0klIUfk1mlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxCg5C/btrQq6imXqM/E4awwpRLCKi0klIUfk1mlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxCg5C/btrQq6imXqM/E4awwpRLCKi0klIUfk1mlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxCg5C%2FbtrQq6imXqM%2FE4awwpRLCKi0klIUfk1mlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;444&quot; data-origin-width=&quot;1813&quot; data-origin-height=&quot;1111&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 첫번째 인스턴스로 Ubuntu Server 20.04 LTS 를 선택하였습니다. 선택하실 때 꼭 프리티어 사용 가능을 확인해주세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;1069&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wMpJH/btrQr6aPz9D/v6h9xfyvc3wv7mOw50NZx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wMpJH/btrQr6aPz9D/v6h9xfyvc3wv7mOw50NZx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wMpJH/btrQr6aPz9D/v6h9xfyvc3wv7mOw50NZx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwMpJH%2FbtrQr6aPz9D%2Fv6h9xfyvc3wv7mOw50NZx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;560&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;1069&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 선택을 완료해주었고 아래를 보시면 인스턴스 유형으로 초기에 프리티어 유형인 t2.micro로 잡혀 있는 것을 확인할 수 있습니다. 꼭 이부분이 t2.micro로 잡혀 있고 우측의 free tier eligible을 확인하여 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;1046&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCGtTZ/btrQsErEfQ9/9pISYToA7tZSCs8iSnvYH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCGtTZ/btrQsErEfQ9/9pISYToA7tZSCs8iSnvYH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCGtTZ/btrQsErEfQ9/9pISYToA7tZSCs8iSnvYH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCGtTZ%2FbtrQsErEfQ9%2F9pISYToA7tZSCs8iSnvYH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;443&quot; height=&quot;500&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;1046&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 해당 인스턴스에 접속하기위한 키페어를 생성해야 하는데 기존에 사용하고 있으신 키페어가 있다면 해당 키페어를 선택해주시면 공용으로 사용할 수 있습니다. 만약 없다면 새 키 페어 생성을 눌러주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boUC94/btrQpTdfK4Y/bVOVsBFLk0JHYXyHKDXrFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boUC94/btrQpTdfK4Y/bVOVsBFLk0JHYXyHKDXrFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boUC94/btrQpTdfK4Y/bVOVsBFLk0JHYXyHKDXrFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboUC94%2FbtrQpTdfK4Y%2FbVOVsBFLk0JHYXyHKDXrFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;379&quot; height=&quot;398&quot; data-origin-width=&quot;675&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 키 페어 이름을 자신이 원하는 이름으로 입력한 후 아래에 RSA, .pem을 선택해주고 키 페어 생성 버튼을 눌러주세요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;395&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSHEH4/btrQpSFnFUf/xGDKSEJ4YnmfRVIcZXptlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSHEH4/btrQpSFnFUf/xGDKSEJ4YnmfRVIcZXptlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSHEH4/btrQpSFnFUf/xGDKSEJ4YnmfRVIcZXptlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSHEH4%2FbtrQpSFnFUf%2FxGDKSEJ4YnmfRVIcZXptlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;309&quot; height=&quot;279&quot; data-origin-width=&quot;437&quot; data-origin-height=&quot;395&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다음과 같이 생성한 키 페어 가 다운받아지는데 인스턴스로 ssh 접속을 할 때 꼭 필요한 파일이니 잘 저장해두시고 관리해두시길 바랍니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k3zAr/btrQq4LEmXP/F7x4VzkPFFpmKbjLjszdy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k3zAr/btrQq4LEmXP/F7x4VzkPFFpmKbjLjszdy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k3zAr/btrQq4LEmXP/F7x4VzkPFFpmKbjLjszdy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk3zAr%2FbtrQq4LEmXP%2FF7x4VzkPFFpmKbjLjszdy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;493&quot; height=&quot;441&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 과정은 인스턴스를 처음만든다는 가정하에 진행을 하므로 초기 상태 그대로 넘어가도록 하겠습니다. 기존 보안 그룹선택을 하고 자신이 사용하고자하는 규칙을 선택하면 자신이 기존에 사용하고 있던 인바운드 규칙등을 다시 설정하지 않고 그대로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl8aSx/btrQp4r5EtN/0LZ6VhYDbvJqv7ZGD3RUB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl8aSx/btrQp4r5EtN/0LZ6VhYDbvJqv7ZGD3RUB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl8aSx/btrQp4r5EtN/0LZ6VhYDbvJqv7ZGD3RUB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl8aSx%2FbtrQp4r5EtN%2F0LZ6VhYDbvJqv7ZGD3RUB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;273&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 스토리지 구성은 default로 8gib 로 잡혀 있을거지만 프리티어에선 30gib까지 스토리지볼륨을 무료로 제공하니 꼭 30gib로 해줍시다. ㅎㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 그리고 만약 하나의 AWS계정에서 프리티어 인스턴스를 하나 이상 사용할 때 나머지 인스턴스도 스토리지 볼륨을 30gib로 늘리게 되면 나머지 인스턴스의 스토리지 볼륨은 무료로 측정이 되지 않는 것 같으니 꼭 하나만 30gib로 설정해 주세요. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CE1GU/btrQql1qyd8/FGcuSVPJtr6vJLj3NKZoJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CE1GU/btrQql1qyd8/FGcuSVPJtr6vJLj3NKZoJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CE1GU/btrQql1qyd8/FGcuSVPJtr6vJLj3NKZoJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCE1GU%2FbtrQql1qyd8%2FFGcuSVPJtr6vJLj3NKZoJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;287&quot; height=&quot;508&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 설정이 완료 되었다면 인스턴스 시작버튼을 눌러주도록 합시다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 설명을 위해 만드는 과정만 보여드렸고 따로 인스턴스를 생성하진 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYEmqT/btrQqmMLBkS/TzAPJGOwNJQJ8aghbR9O91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYEmqT/btrQqmMLBkS/TzAPJGOwNJQJ8aghbR9O91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYEmqT/btrQqmMLBkS/TzAPJGOwNJQJ8aghbR9O91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdYEmqT%2FbtrQqmMLBkS%2FTzAPJGOwNJQJ8aghbR9O91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;701&quot; height=&quot;181&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 생성 후 잠시 대기시간을 가지게 되면 인스턴스 상태가 실해중으로 바뀌게 될겁니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행중으로 바뀌게 되면 이제 해당 인스턴스를 사용할 수 있게 되는거죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Jenkins 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방금 생성한 Ubuntu 인스턴스에 접속하기 전 미리 Jenkins서버가 띄워질 8080포트를 인바운드 규칙에서 열어주도록 하겠습니다. 설치를 하는데 있어선 문제가 되지 않지만 설치후 Jenkins 서버에 &lt;b&gt;http://퍼블릭아이피주소:포트&lt;/b&gt; 로 접속하기 위해서 입니다. =)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xjivK/btrQqkIbxDO/lpnvCoeMRG2IzEpusir42k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xjivK/btrQqkIbxDO/lpnvCoeMRG2IzEpusir42k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xjivK/btrQqkIbxDO/lpnvCoeMRG2IzEpusir42k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxjivK%2FbtrQqkIbxDO%2FlpnvCoeMRG2IzEpusir42k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;318&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 인스턴스를 선택 후 하단의 보안을 눌러주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 보안그룹을 클릭해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1661&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/79oUU/btrQqk9iyiU/RrodIM8U2yjrqPQJ61sF5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/79oUU/btrQqk9iyiU/RrodIM8U2yjrqPQJ61sF5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/79oUU/btrQqk9iyiU/RrodIM8U2yjrqPQJ61sF5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F79oUU%2FbtrQqk9iyiU%2FRrodIM8U2yjrqPQJ61sF5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;638&quot; height=&quot;233&quot; data-origin-width=&quot;1661&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 창이 보일텐데 여기에서 인바운드 규칙 편집을 눌러주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsp0ri/btrQrtxCjkA/KMd8va0dVAQ830zagwEEJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsp0ri/btrQrtxCjkA/KMd8va0dVAQ830zagwEEJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsp0ri/btrQrtxCjkA/KMd8va0dVAQ830zagwEEJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsp0ri%2FbtrQrtxCjkA%2FKMd8va0dVAQ830zagwEEJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;218&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 이미 많은 인바운드 규칙이 설정되어 있는데 다음과 같이 규칙추가를 눌러 주고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자지정TCP, 8080, Anywhere-IPv4를 선택해주도록 합니다. 사실 실제 운영을 할 서버라면 사용자 지정으로 허용해야할 특정 IP만 허용하여 해당 IP에서만 열어준 포트로 접속을 할 수 있게 해주는게 좋습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 모든 셋팅이 끝났으니 ssh 접속을 해보도록 하겠습니다. 필자의 경우 여러개의 인스턴스에 접속을 쉽게 하기 위해 ssh-client tool을 사용하고 있습니다. 이 방법은 필자가 정리해둔 아래 링크를 참고하여 주세요.&lt;/p&gt;
&lt;figure id=&quot;og_1667593671155&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;편리한 EC2 인스턴스 접속(SSH Client Tool)&quot; data-og-description=&quot;편리한게 AWS EC2 인스턴스에 접속을 하기 위해 SSH Client Tool 을 사용해보자! 필자는 Windows 환경에서 EC2 인스턴스에 접속을 하기 위해 gitbash를 사용하는 편이지만 좀 더 편리하게 접속을 하기위해 Te&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/23&quot; data-og-url=&quot;https://0andwild.tistory.com/23&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gHX6y/hyQse1doeY/QVymx9HkJX0GUIsnRi6Ci1/img.png?width=800&amp;amp;height=380&amp;amp;face=0_0_800_380,https://scrap.kakaocdn.net/dn/fuIqb/hyQsfsihNk/5cJLzNKpkzmnUAB5yEQDj1/img.png?width=800&amp;amp;height=380&amp;amp;face=0_0_800_380,https://scrap.kakaocdn.net/dn/mUbR5/hyQr3ZF8VB/4lBcNgsOfTBdOml270NDkK/img.png?width=827&amp;amp;height=481&amp;amp;face=0_0_827_481&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/23&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gHX6y/hyQse1doeY/QVymx9HkJX0GUIsnRi6Ci1/img.png?width=800&amp;amp;height=380&amp;amp;face=0_0_800_380,https://scrap.kakaocdn.net/dn/fuIqb/hyQsfsihNk/5cJLzNKpkzmnUAB5yEQDj1/img.png?width=800&amp;amp;height=380&amp;amp;face=0_0_800_380,https://scrap.kakaocdn.net/dn/mUbR5/hyQr3ZF8VB/4lBcNgsOfTBdOml270NDkK/img.png?width=827&amp;amp;height=481&amp;amp;face=0_0_827_481');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;편리한 EC2 인스턴스 접속(SSH Client Tool)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;편리한게 AWS EC2 인스턴스에 접속을 하기 위해 SSH Client Tool 을 사용해보자! 필자는 Windows 환경에서 EC2 인스턴스에 접속을 하기 위해 gitbash를 사용하는 편이지만 좀 더 편리하게 접속을 하기위해 Te&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 자신이 터미널 또는 gitbash를 통해 접속을 원한다면 다음과 같이 진행을 해주시면 됩니다. =)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxRd4v/btrQrGXMX6e/459eb4i4dmP3m87Re6PVx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxRd4v/btrQrGXMX6e/459eb4i4dmP3m87Re6PVx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxRd4v/btrQrGXMX6e/459eb4i4dmP3m87Re6PVx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxRd4v%2FbtrQrGXMX6e%2F459eb4i4dmP3m87Re6PVx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;225&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh&amp;nbsp;-i&amp;nbsp;(키페어&amp;nbsp;넣어줌)&amp;nbsp;ubuntu@(실행중인&amp;nbsp;ec2의&amp;nbsp;퍼블릭&amp;nbsp;IPv4&amp;nbsp;주소&amp;nbsp;넣어줌)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh -i 입력후 인스턴스 생성시 새로 만든 키페어를 드래그해주시면 키페어가 입력됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 ubuntu를 입력해주었는데 이부분은 자신이 선택한 인스턴스 유형에 따라 즉, OS에 따라 초기 이름이 다르게 잡혀 있기 때문에 이부분은 찾아보시는게 좋을 것 같습니다. =) 추가적으로 AWS Linux의 경우는 초기 이름이 ec2-user 로 잡혀 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼블릭 아이피의 경우 해당 인스턴스를 클릭 후 네트워킹을 선택하시면 퍼블릭 IP주소를 확인할 수 있고 좌측의 네모난 모양의 버튼을 클릭하면 쉽게 복사가 되어 붙여넣기를 진행해 주시면 됩니다. =)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjFGZX/btrQp5LiCw5/KuYVazXq7zmR4LadPYLIjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjFGZX/btrQp5LiCw5/KuYVazXq7zmR4LadPYLIjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjFGZX/btrQp5LiCw5/KuYVazXq7zmR4LadPYLIjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjFGZX%2FbtrQp5LiCw5%2FKuYVazXq7zmR4LadPYLIjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;296&quot; height=&quot;320&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sX2vR/btrQrrmf9m9/7H2feUbZstGm5RuenHxYj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sX2vR/btrQrrmf9m9/7H2feUbZstGm5RuenHxYj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sX2vR/btrQrrmf9m9/7H2feUbZstGm5RuenHxYj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsX2vR%2FbtrQrrmf9m9%2F7H2feUbZstGm5RuenHxYj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;478&quot; height=&quot;286&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 입력을 다하셨다면 엔터를 줄러주시고 다음과 같이 정상적으로 접속이 된 화면을 확인하실 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 접속을 한다면 fingerprint(yes/no)가 나올 수 있는데 yes를 입력하시고 엔터를 눌러주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Jenkins를 설치해보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqTZje/btrQrFq1zgK/oTM2Ka5uEIQrncK5sizgsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqTZje/btrQrFq1zgK/oTM2Ka5uEIQrncK5sizgsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqTZje/btrQrFq1zgK/oTM2Ka5uEIQrncK5sizgsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqTZje%2FbtrQrFq1zgK%2FoTM2Ka5uEIQrncK5sizgsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;897&quot; height=&quot;38&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667594928320&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install open-jdk-11&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkins는 Java8버전부터 호환이 가능합니다. 아마 EC2 인스턴스에는 기본적으로 jdk 8이 설치되어 있는것으로 알지만 필자는 jdk 11로 설치를 해주었습니다. =)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7mo8T/btrQr11GAhJ/id9b6IjokRx1AMGVRHc0jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7mo8T/btrQr11GAhJ/id9b6IjokRx1AMGVRHc0jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7mo8T/btrQr11GAhJ/id9b6IjokRx1AMGVRHc0jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7mo8T%2FbtrQr11GAhJ%2Fid9b6IjokRx1AMGVRHc0jk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;150&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667595009303&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;java -version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;jenkins 설치의 경우 이미 필자가 정리해둔 글이 있기에 해당 글로 대체를 하도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 아쉬운 점은 필자는 초반 Jenkins를 해당 인스턴스내에 직접 설치를 하였지만 Docker conatiner로 젠킨스를 띄워 사용해보는 것도 좋은 방법일거라 생각이듭니다.=)&lt;/p&gt;
&lt;figure id=&quot;og_1667595100823&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Jenkins를 이용한 CI/CD Pipeline 구축해보기(2)&quot; data-og-description=&quot;1편에서 만들어둔 EC2 인스턴스를 중지시키고 이미지(AMI)를 생성해줄 겁니다. 아직 인스턴스 생성과 초기 작업이 수행되지 않았다면 아래 링크를 참고하여주세요. Jenkins를 이용한 CI/CD Pipeline 구&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/24&quot; data-og-url=&quot;https://0andwild.tistory.com/24&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/nPPfu/hyQsfluLEt/pdiP1BlRdydgXlSvZ4cwY1/img.png?width=225&amp;amp;height=225&amp;amp;face=109_62_132_87,https://scrap.kakaocdn.net/dn/c5WS7T/hyQsgShCIF/7tWfoRUH3OaHBN6zznlvNK/img.png?width=225&amp;amp;height=225&amp;amp;face=109_62_132_87,https://scrap.kakaocdn.net/dn/FzCa7/hyQtrYWEwX/YxDv9nXme7GBLfeRdo4Qg0/img.png?width=960&amp;amp;height=425&amp;amp;face=0_0_960_425&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/24&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/24&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/nPPfu/hyQsfluLEt/pdiP1BlRdydgXlSvZ4cwY1/img.png?width=225&amp;amp;height=225&amp;amp;face=109_62_132_87,https://scrap.kakaocdn.net/dn/c5WS7T/hyQsgShCIF/7tWfoRUH3OaHBN6zznlvNK/img.png?width=225&amp;amp;height=225&amp;amp;face=109_62_132_87,https://scrap.kakaocdn.net/dn/FzCa7/hyQtrYWEwX/YxDv9nXme7GBLfeRdo4Qg0/img.png?width=960&amp;amp;height=425&amp;amp;face=0_0_960_425');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins를 이용한 CI/CD Pipeline 구축해보기(2)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1편에서 만들어둔 EC2 인스턴스를 중지시키고 이미지(AMI)를 생성해줄 겁니다. 아직 인스턴스 생성과 초기 작업이 수행되지 않았다면 아래 링크를 참고하여주세요. Jenkins를 이용한 CI/CD Pipeline 구&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 Jenkins가 생각보다 자원을 많이먹는 녀석이다보니 AWE EC2 프리티어 인스턴스에서는 Swap 메모리를 구축하여 사용하는 것이 좋습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(Swap 메모리 구축)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SWAP메모리는 OS에서 메모리를 full로 사용하고 있으면 사용하지 않는 메모리 안의 페이지를 하드드라이브에 저장하게 되는데, 이게 SWAP메모리의 기본 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYLs6S/btrQqMkQyzk/bRm4YF9pgAadKnnMCO9tV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYLs6S/btrQqMkQyzk/bRm4YF9pgAadKnnMCO9tV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYLs6S/btrQqMkQyzk/bRm4YF9pgAadKnnMCO9tV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYLs6S%2FbtrQqMkQyzk%2FbRm4YF9pgAadKnnMCO9tV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;190&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LbSaF/btrQqI3PiWa/glMh0SZacGMbjf8nnwRbeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LbSaF/btrQqI3PiWa/glMh0SZacGMbjf8nnwRbeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LbSaF/btrQqI3PiWa/glMh0SZacGMbjf8nnwRbeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLbSaF%2FbtrQqI3PiWa%2FglMh0SZacGMbjf8nnwRbeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;503&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6ARJX/btrQvYwNQgH/6f3ijNLmnyhiZ88oUjDvtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6ARJX/btrQvYwNQgH/6f3ijNLmnyhiZ88oUjDvtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6ARJX/btrQvYwNQgH/6f3ijNLmnyhiZ88oUjDvtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6ARJX%2FbtrQvYwNQgH%2F6f3ijNLmnyhiZ88oUjDvtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;712&quot; height=&quot;119&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667668337986&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Swap space의 기본 용량 단위는 128MB라고 한다.
AWS 프리티어는 RAM이 1GB이기 때문에 2GB의 SWAP Space를 할당하기 위해
count=16으로 설정해준다.
$ sudo dd if=/dev/zero of=/swapfile bs=128M count=16

스왑 파일 Read/ Write 권한을 변경한다.
$ sudo chmod 600 /swapfile

Linux SWAP File을 사용해서 영역을 설정한다.
$ sudo mkswap /swapfile

SWAP SPACE에 SWAP File을 추가해준다.
$ sudo swapon /swapfile

추가된 SWAP 영역을 확인한다.
$ sudo swapon -s

서버를 Reboot(재실행) 할 경우 SWAP을 자동으로 활성화 하기 위해
vim 에디터를 이용해 /etc/fstab 파일을 열어서 해당 내용을 추가해준다.
$ sudo vim /etc/fstab
/swapfile swap swap default 0 0      &amp;lt;--이부분을 추가해줌&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Jenkins Multibranch Pipeline 프로젝트 생성 및 Gitea 연결&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이부분도 이전 작성해둔 글로 대체를 하도록 하겠습니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 수정된 부분이 있어 그 부분에 대해서만 설명을 드리도록 하겠습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1667595406649&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Gitea Webhook Jenkins(Gitea 와 jenkins 연동하기)&quot; data-og-description=&quot;최근 5일동안 Gitea와 Jenkins Webhook 연결 문제로 삽질을 엄청 많이 했습니다..... =( 혹여나 필자와 같은 상황에 있는 분들을 위해 정리를 해보고자 합니다. 만약 Gitea Jenkins Webhook 관련 연결 실패 때문&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/28&quot; data-og-url=&quot;https://0andwild.tistory.com/28&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ODWPo/hyQsjg9v2U/uDeBjkfU3BFOcQv4pgZMrK/img.png?width=308&amp;amp;height=163&amp;amp;face=67_24_119_81,https://scrap.kakaocdn.net/dn/bfGGvC/hyQr4qMzGe/1ku66JDAvwMRq92hEkmhLK/img.png?width=308&amp;amp;height=163&amp;amp;face=67_24_119_81,https://scrap.kakaocdn.net/dn/cKJMHB/hyQtrYWHtH/a4efOjszmdfzosjCLaPH2K/img.png?width=2088&amp;amp;height=856&amp;amp;face=0_0_2088_856&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/28&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ODWPo/hyQsjg9v2U/uDeBjkfU3BFOcQv4pgZMrK/img.png?width=308&amp;amp;height=163&amp;amp;face=67_24_119_81,https://scrap.kakaocdn.net/dn/bfGGvC/hyQr4qMzGe/1ku66JDAvwMRq92hEkmhLK/img.png?width=308&amp;amp;height=163&amp;amp;face=67_24_119_81,https://scrap.kakaocdn.net/dn/cKJMHB/hyQtrYWHtH/a4efOjszmdfzosjCLaPH2K/img.png?width=2088&amp;amp;height=856&amp;amp;face=0_0_2088_856');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Gitea Webhook Jenkins(Gitea 와 jenkins 연동하기)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최근 5일동안 Gitea와 Jenkins Webhook 연결 문제로 삽질을 엄청 많이 했습니다..... =( 혹여나 필자와 같은 상황에 있는 분들을 위해 정리를 해보고자 합니다. 만약 Gitea Jenkins Webhook 관련 연결 실패 때문&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YOATL/btrQrGjcQHa/AkA1zQkejObCPTI1EVoVHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YOATL/btrQrGjcQHa/AkA1zQkejObCPTI1EVoVHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YOATL/btrQrGjcQHa/AkA1zQkejObCPTI1EVoVHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYOATL%2FbtrQrGjcQHa%2FAkA1zQkejObCPTI1EVoVHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1366&quot; height=&quot;413&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 Multibranch Pipeline 프로젝트의 Gitea 설정 부분에서 Filter by name을 prod 환경을 배포할 main branch와 dev환경을 배포항 develop 브랜치로 설정해두어 해당 브랜치에서 push또는 Pull request 발생 시 Jenkins build가 trigger 되도록 하였습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Jenkins file 작성(1)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 Jenkins Pipeline의 핵심인 Jenkins file을 작성해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Jenkinsfile 작성법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;젠킨스파일을 작성하는 방법은 두 가지 방식이 존재하는데 선언형(Declarative)과 스크립트형(Scripted)이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크립트형 문법의 경우 Groovy를 사용보시지 않았거나 Java 문법에 익숙지 않으며 쉽지 않다는 단점이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 장점으로는 더 많은 절차적인 코드작성, 보다 복잡한 워크 플로우 및 파이프라인 작성 가능을 꼽을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언형의 경우 보다 쉽게 작성이 가능하고 Groovy 문법을 잘 몰라도 작성이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 선언형을 선택하였고 그 기반으로 설명을 드리도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkinsfile의 시작은 pipeline{} 명시함으로써 시작이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;agent 는 pipeline 내의 최상단에 위치해야 하며 any로 명시할 경우 어떠한 agent로도 실행해도 된다는 걸 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 파이프라인 전체에서 사용할 수 있게 되는 것이다. 반면 none으로 설정할 경우 각 stage마다 agent를 설정해주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 아래의 예제 에서는 존재 하지 않지만 pipeline은 stages로 stage들을 감쌀 수 있으며, stage는 어떠한 job의 단계를 말합니다. stage안에는 steps가 존재하는데 이 부분에는 실행해야할 명령어를 입력해주는 부분이라 생각하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래의 post 부분은 steps가 끝난이후 어떠한 행동을 할 건지에대해 명시를 할 수 있습니다. 가장 대표적인 문법은 success와 failure로 steps안의 행동을 성공했을 때와 실패했을 때를 구분하여 다음 행동을 명시 할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1667596003546&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Git Checkout
pipeline {
    agent any
    
        stage('gitea clone') {
            steps {
                echo&quot;Cloning Repository&quot;
                git branch: '{main or dev 등 checkout을 할 branch}',
                    credentialsId: '{jenkins 에서 등록한 github or gitea or gitlab 등의 credential}',
                    url: '{github or gitea or gitlab 등 URL}'
            }
            post{
                success {
                    echo &quot;Successfully Cloned Repository&quot;
                }
                failure {
                    echo &quot;Fail Cloned Repository&quot;
                }
            }
        }
 
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 gitea의 해당 branch 여기서는 develop branch를 가져오는 파이프라인입니다. 간단하게 클론을 성공하였을 때와 실패를 하였을 때 echo를 통해 해당 job을 성공했다 또는 실패했다를 남기도록 하였습다. 이부분은 jenkins 빌드기록의 log에 남게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 파이프라인에 대한 설명을 이어나가기전 젠킨스 빌드시 편의를 위해 Slack 알림 연동을 미리 설정해두도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이부분 또한 필자가 작성해둔 글이 있어 해당 글로 대체를 하도록 하겠습니다.=)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667598286636&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Jenkins &amp;amp; Slack 연동하기(Slack Notification) 및 파이프라인 작성&quot; data-og-description=&quot;Jenkins &amp;amp; Slack Notification 연동 Slack에서 Jenkins CI 앱을 추가해주면 다음과 같은 웹 사이트로 이동이 되며 설정 지침에 따라 Jenkins 설정을 진행해 주도록 합시다. =) 먼저 Jenkins Server로 들어와 Slack Notifi&quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/33&quot; data-og-url=&quot;https://0andwild.tistory.com/33&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cxb9vw/hyQsgxXIzn/LK3KUyA1mrSsicNns19bMK/img.png?width=375&amp;amp;height=135&amp;amp;face=52_22_93_67,https://scrap.kakaocdn.net/dn/1Xje3/hyQtBUNBM1/jGjKgU8sNJ4Z7mugKQIFs1/img.png?width=375&amp;amp;height=135&amp;amp;face=52_22_93_67,https://scrap.kakaocdn.net/dn/bdnZHh/hyQtyRiZbz/Yj6suiQNiJypuI1WOlYEF1/img.png?width=940&amp;amp;height=705&amp;amp;face=0_0_940_705&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/33&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/33&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cxb9vw/hyQsgxXIzn/LK3KUyA1mrSsicNns19bMK/img.png?width=375&amp;amp;height=135&amp;amp;face=52_22_93_67,https://scrap.kakaocdn.net/dn/1Xje3/hyQtBUNBM1/jGjKgU8sNJ4Z7mugKQIFs1/img.png?width=375&amp;amp;height=135&amp;amp;face=52_22_93_67,https://scrap.kakaocdn.net/dn/bdnZHh/hyQtyRiZbz/Yj6suiQNiJypuI1WOlYEF1/img.png?width=940&amp;amp;height=705&amp;amp;face=0_0_940_705');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins &amp;amp; Slack 연동하기(Slack Notification) 및 파이프라인 작성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins &amp;amp; Slack Notification 연동 Slack에서 Jenkins CI 앱을 추가해주면 다음과 같은 웹 사이트로 이동이 되며 설정 지침에 따라 Jenkins 설정을 진행해 주도록 합시다. =) 먼저 Jenkins Server로 들어와 Slack Notifi&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;pre id=&quot;code_1667597908369&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pipeline {
    agent any

    stages {
        stage(&quot;Set Variable&quot;) {
            //공통사용 항목 변수 지정 및 build 유발자와 commit 내역을 함께 Slack 알림으로 전송
            steps {
                script {
                    //알림받을 채널
                    SLACK_CHANNEL = &quot;{사용하고자 하는 slack 채널명 입력}&quot;
                    SLACK_START_AND_FINISH_COLOR = &quot;#778899&quot;;
                    SLACK_SUCCESS_COLOR = &quot;#2C953C&quot;;
                    SLACK_FAIL_COLOR = &quot;#FF3232&quot;;
                    // Git Commit 계정
                    GIT_COMMIT_AUTHOR = sh(script: &quot;git --no-pager show -s --format=%an ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                    // Git Commit 메시지
                    GIT_COMMIT_MESSAGE = sh(script: &quot;git --no-pager show -s --format=%B ${env.GIT_COMMIT}&quot;, returnStdout: true).trim();
                }
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_START_AND_FINISH_COLOR,
                        message:
                        &quot;==================================================================\n&quot; +
                        &quot;\n&quot; +
                        &quot;배포 파이프라인이 시작되었습니다.\n&quot; +
                        &quot;${env.JOB_NAME}(${env.BUILD_NUMBER})\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_AUTHOR-\n&quot; +
                        &quot;:  ${GIT_COMMIT_AUTHOR}\n&quot; +
                        &quot;\n&quot; +
                        &quot;-GIT_COMMIT_MESSAGE-\n&quot; +
                        &quot;:  ${GIT_COMMIT_MESSAGE}\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}&quot;
                    )
                }
            }
        }

        //Git Checkout
        stage('gitea clone') {
            steps {
                echo&quot;Cloning Repository&quot;
                git branch: '{main or dev 등 checkout을 할 branch}',
                    credentialsId: '{jenkins 에서 등록한 github or gitea or gitlab 등의 credential}',
                    url: '{github or gitea or gitlab 등 URL}'
            }
            post{
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Gitea Checkout에 성공하였습니다.&quot;
                    )
                    echo &quot;Successfully Cloned Repository&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Gitea Checkout에 실패하였습니다.\n&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console\n&quot; + //실패시 젠킨스서버의 해당 빌드 log로 이동
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Fail Cloned Repository&quot;
                }
            }
        }
        
   }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Slack알림 연동을 완료 하였다면 기존 파이프라인 구문에서 slack과 관련된 내용이 추가될 것이고 위와 같이 작성이 될 수 있습니다. 추가 된 부분을 살펴보면 이제는 stage가 두 개가 되어 stages{}로 stage{}들을 감싸고 있는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Set Variable이라는 stage가 추가 되었는데 이부분은&lt;/span&gt; 모든 stage들이 시작되기 전 공통적으로 또는 여러번 사용될 수 있는 값들의 하드코딩을 방지하기 위해 변수값에 담아주어 어떠한 stage에서 해당 값을 필요로 할때 변수명으로 호출할 수 있도록 하는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 slack notification 연동이 되었으므로 Stage안의 step이 끝난 후 post안의 success와 failure에 slack에 대한 정보와 어떠한 메세지를 보낼지에 대한 내용이 담겨 있는 것을 확인할 수 있습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm1uBI/btrQrEeBnU5/I6Y2FPuXS9DT3Fr6faolv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm1uBI/btrQrEeBnU5/I6Y2FPuXS9DT3Fr6faolv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm1uBI/btrQrEeBnU5/I6Y2FPuXS9DT3Fr6faolv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm1uBI%2FbtrQrEeBnU5%2FI6Y2FPuXS9DT3Fr6faolv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;502&quot; height=&quot;214&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git push 또는 pull request를 통한 merge를 시도해보면 다음과 같이 슬랙으로 jenkins 파이프라인의 step별로 알림이 오는 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667599987353&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Gradle Build &amp;amp; Test
        stage('Build &amp;amp; Test') {
            steps {
                sh '''
                    echo 'Build Gradle Start'
                    ./gradlew clean build
                '''
            }
            post {
                success {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_SUCCESS_COLOR,
                        message: &quot;Build &amp;amp; Test 에 성공하였습니다.&quot;
                    )
                    echo &quot;Build Gradle Success&quot;
                }
                failure {
                    slackSend (
                        channel: SLACK_CHANNEL,
                        color: SLACK_FAIL_COLOR,
                        message: &quot;Build &amp;amp; Test 에 실패하였습니다.&quot; +
                        &quot;\n&quot; +
                        &quot;&amp;lt;-More info-&amp;gt;\n&quot; +
                        &quot;${env.BUILD_URL}console&quot;
                        &quot;==================================================================&quot;
                    )
                    echo &quot;Build Gradle Fail&quot;
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 stage는 Spring project를 build 하여 jar파일을 생성하는 단계입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 필자는 gradlew를 사용하였는데 이는 gradle wrapper를 뜻하고 이건 내장되어있는 gradle을 사용한다는 겁니다. Gradle에서는 각 프로젝트마다 내장 Gradle을 넣어주게 만들어졌고, 프로젝트에서 내장 gradle을 사용할 수 있게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 장점으로 gradle wrapper를 사용시 해당 프로젝트에서 사용하는 gradle의 버전에 맞추어 설치하지 않아도 되고, gradle wrapper를 이용한 빌드시 알아서 해당 프로젝트에서 사용하고자 하는 gradle 버전에 맞추어 gradle을 설치하여 빌드를 진행해줍니다. 여기서 추가적으로 gradlew는 맥과,리눅스용 스크립트 이며, gradle.bat은 위도우용 스크립트를 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clean 명령어란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 디렉토리 부분은 반복해서 파일이 생성되기 때문에, 이전에 생성된 파일과 중복되지 않도록 디렉토리를 한 번 비우고 build를 진행하게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 여기서 빌드 시 test를 하고 싶지 않다면 --exclude-task test를 추가하여 진행할 수 도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 본 CI/CD에서는 빌드 시 test를 진행하고 Jacoco 코드커버리지를 측정 및 Checkstyle을 통해 html과 xml로 리포트를 생성하고 SonarQube로 넘겨줄거기 때문에 test를 포함시켰습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이어서 gradle 에 Jacoco 설정을 진행해 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. Jacoco Code Coverage 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jacoco는 Java의 코드커버리지를 체크하는 라이브러리로 테스트코드를 test한 후 그 커버리지 결과를 html, xml, csv 로 만들어주는 도구입니다. 이러한 도구를 통해 얼마나 테스트케이스가 충족되었는지의 결과를 쉽게 확인할 수 있고, 어떠한 커버리지를 측정할건지에 대해 설정과 함께 %를 설정하여 해당 %를 충족시키지 못하면 빌드를 실패시키게 할 수 도 있습니다. 따라서 프로젝트의 코드품질 향상에 굉장한 도움을 주는 녀석입니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d63lFp/btrQrsMg5lp/PKzcdKraFK8A3MZs3twGP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d63lFp/btrQrsMg5lp/PKzcdKraFK8A3MZs3twGP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d63lFp/btrQrsMg5lp/PKzcdKraFK8A3MZs3twGP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd63lFp%2FbtrQrsMg5lp%2FPKzcdKraFK8A3MZs3twGP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;371&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667602322838&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;id 'jacoco'

jacoco {
    toolVersion = '0.8.7'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Gradle 파일로 들어가 준 후 jacoco plugin을 추가해주도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zUMiM/btrQsCUU700/1e0Q8gczPt4SdTG7kkG1sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zUMiM/btrQsCUU700/1e0Q8gczPt4SdTG7kkG1sK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zUMiM/btrQsCUU700/1e0Q8gczPt4SdTG7kkG1sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzUMiM%2FbtrQsCUU700%2F1e0Q8gczPt4SdTG7kkG1sK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;409&quot; height=&quot;165&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;165&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1667602510128&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;finalizedBy jacocoTestReport&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 하단부에 있는 test task의 useJunitPlatform 밑으로 finalizedBy jacocoTestReport 를 추가해주도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 test task가 먼저 수행 된 후 jacocoTestReport를 생성하겠다는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667602455912&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Jacoco 추가
jacocoTestReport {
    dependsOn test
    reports {
    	//여기서 설정을 통해 원하는 리포트 형태를 설정할 수 있음
        html.enabled true
        xml.enabled true
        csv.enabled true
        xml.destination = file(&quot;${buildDir}/jacoco/jacoco.xml&quot;) //파일경로 지정
    }
	
    def Qdomains = []
    for (qPattern in '**/QA'..'**/QZ') {
        Qdomains.add(qPattern + '*')
    }

    afterEvaluate {
        classDirectories.setFrom(
                files(classDirectories.files.collect {
                    fileTree(dir: it, excludes: [
                            '**.SpringInitProjectApplication*',
                            '**.*Request*',
                            '**.*Response*',
                            '**.constant.**',
                            '**.common.**',
                            '**.environment.**',
                            '**.*Dto*',
                            '**.*OAuthClient*',
                            '**.*Interceptor*',
                            '**.*Exception*',
                            &quot;**.Q*.class&quot;
                    ] + Qdomains)
                })
        )
    }
    //test -&amp;gt; testReport 생성 -&amp;gt; jacocoTestCoverageVerification 실행
    finalizedBy 'jacocoTestCoverageVerification' 
}

jacocoTestCoverageVerification {
    def Qdomains = []
    for (qPattern in '*.QA'..'*.QZ') {
        Qdomains.add(qPattern + '*')
    }

    violationRules {
        rule {
        	//커버리지를 측정할 기준(단위)
            element = 'CLASS'
            //해당 룰에대한 사용 boolean으로 표시
            enabled = true
            
            //조건문 등의 분기 수
            limit {
            counter = 'BRANCH'
            value = 'COVEREDRATIO'
            minimum = 0.80
            }
			
            //빈 줄을 제외한 실제 코드의 라인 수
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.80
            }
			
            //메서드 수
            limit {
                counter = 'METHOD'
                value = 'COVEREDRATIO'
                minimum = 0.80
            }

            excludes = [
                    '**.*SpringInitProjectApplication*',
                    '**.*Request*',
                    '**.*Response*',
                    '**.constant.**',
                    '**.common.**',
                    '**.environment.**',
                    '**.*Dto*',
                    '**.*OAuthClient*',
                    '**.*Interceptor*',
                    '**.*Exception*',
                    &quot;**.Q*.class&quot;
            ] + Qdomains
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의깊게 살펴봐야 할 부분은 violationRules 부분입니다. 이부분은 Jacoco의 Code Coverage를 측정할 때 어떤걸 기준으로 측정할건지와 어떠한 부분을 측정할건지 설정하는 부분입니다. 아래와 같은 항목들이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;BRANCH : 조건문 등의 분기 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;CLASS : 클래스 수, 내부 메서드가 한 번이라도 실행된다면 실행된 것으로 간주한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;COMPLEXITY :&amp;nbsp;복잡도&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;INSTRUCTION : Java 바이트코드 명령 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;METHOD : 메서드 수, 메서드가 한 번이라도 실행된다면 실행된 것으로 간주한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;LINE : 빈 줄을 제외한 실제 코드의 라인 수, 라인이 한 번이라도 실행되면 실행된 것으로 간주한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;minimum 부분은 위에서 설정한 rules에 얼만큼 부합해야 통과를 시킬지에 대한 설정입니다. 0.80은 80%를 의미하며 일반적으로 80%를 기준으로 잡는다고 합니다. =)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;excludes 부분은 jacoco Coverage 측정시 제외를 할 패키지 및 파일들을 지정할 수 있는 곳입니다. 일반적으로 dto와 같은 항목들은 테스트에서 제외시킨다고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;추가적으로 QueryDSL을 사용하고 있는 경우 자동으로 생성된 Qclass는 Coverage를 측정할 필요가 없기 때문에 위와 같이 제외를 시켜주었습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;맨위를 보시면 afterEvaluate라는 항목이 존재하는데 이부분은 gradle의 빌드 라이프 사이클에 대한 메서드로 프로젝트 평가가 완료된 후 실행될 수 있도록 해줍니다. =)&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8JT6I/btrQp64AahO/nKnN5mE9laeSKMc0xAjeFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8JT6I/btrQp64AahO/nKnN5mE9laeSKMc0xAjeFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8JT6I/btrQp64AahO/nKnN5mE9laeSKMc0xAjeFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8JT6I%2FbtrQp64AahO%2FnKnN5mE9laeSKMc0xAjeFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;295&quot; height=&quot;105&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 @Lombok을 사용하고 있는 경우 generated code를 커버리지에서 제외하기 위해선 프로젝트의 루트경로에 다음과 같이 lombok.config 파일을 생성하고 아래의 코드를 추가해줍니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;lombok.addLombokGeneratedAnnotation = true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEzORc/btrQqKmoWad/d13fm7GawIoq5jUrpXWqPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEzORc/btrQqKmoWad/d13fm7GawIoq5jUrpXWqPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEzORc/btrQqKmoWad/d13fm7GawIoq5jUrpXWqPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEzORc%2FbtrQqKmoWad%2Fd13fm7GawIoq5jUrpXWqPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;228&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 test를 할 겸 build 를 돌렸을 때 경로를 지정해준 xml report 파일이 잘 생성된 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rf4JY/btrQp4ez06R/r3ktjGbm3HuKN09gTB7II1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rf4JY/btrQp4ez06R/r3ktjGbm3HuKN09gTB7II1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rf4JY/btrQp4ez06R/r3ktjGbm3HuKN09gTB7II1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frf4JY%2FbtrQp4ez06R%2Fr3ktjGbm3HuKN09gTB7II1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;267&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kW0x4/btrQpWgN5KS/xHsHLts7Ue6vKsSKdtgkJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kW0x4/btrQpWgN5KS/xHsHLts7Ue6vKsSKdtgkJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kW0x4/btrQpWgN5KS/xHsHLts7Ue6vKsSKdtgkJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkW0x4%2FbtrQpWgN5KS%2FxHsHLts7Ue6vKsSKdtgkJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;746&quot; height=&quot;176&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 html 파일로 정상적으로 커버리지가 측정되는 것을 확인 할 수 잇습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6. CheckStyle 코드컨벤션 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음은 Check Style 플러그인 설치 및 적용을 해보도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필자의 경우 코드컨벤션 예제로 네이버 핵 데이의 네이버 Java 코드컨벤션을 적용하였고 해당 적용 과정은 필자가 최근에&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상세하게 작성해둔 글이 있어 해당 글로 대체 하도록 하겠습니다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1667605960788&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Jenkins&amp;amp;Sonaqube&amp;amp;Checkstyle 을 이용한 코드컨벤션 적용기(Naver Code Convention)&quot; data-og-description=&quot;필자의 경우 Jenkins를 이용한 CI/CD를 진행하며 코드 분석 툴로 Jacoco&amp;amp;Sonarqube를 사용하고 있는 상황이며, 더 나은 코드 품질을 위해 Sonarqube의 Rules 설정을 통한 코드컨벤션을 적용하려 합니다. 코드 &quot; data-og-host=&quot;0andwild.tistory.com&quot; data-og-source-url=&quot;https://0andwild.tistory.com/34&quot; data-og-url=&quot;https://0andwild.tistory.com/34&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJvcFz/hyQtuIa83R/jPBaPown6L6eosUsB0jvM0/img.png?width=625&amp;amp;height=377&amp;amp;face=0_0_625_377,https://scrap.kakaocdn.net/dn/c8eZMs/hyQsdVAAI1/TCJoQG31DATZ6k0sCX9BWk/img.png?width=625&amp;amp;height=377&amp;amp;face=0_0_625_377,https://scrap.kakaocdn.net/dn/vVGil/hyQr9FD78S/4DkOHYw3KhFRpkGiE1k690/img.png?width=940&amp;amp;height=507&amp;amp;face=0_0_940_507&quot;&gt;&lt;a href=&quot;https://0andwild.tistory.com/34&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0andwild.tistory.com/34&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJvcFz/hyQtuIa83R/jPBaPown6L6eosUsB0jvM0/img.png?width=625&amp;amp;height=377&amp;amp;face=0_0_625_377,https://scrap.kakaocdn.net/dn/c8eZMs/hyQsdVAAI1/TCJoQG31DATZ6k0sCX9BWk/img.png?width=625&amp;amp;height=377&amp;amp;face=0_0_625_377,https://scrap.kakaocdn.net/dn/vVGil/hyQr9FD78S/4DkOHYw3KhFRpkGiE1k690/img.png?width=940&amp;amp;height=507&amp;amp;face=0_0_940_507');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Jenkins&amp;amp;Sonaqube&amp;amp;Checkstyle 을 이용한 코드컨벤션 적용기(Naver Code Convention)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;필자의 경우 Jenkins를 이용한 CI/CD를 진행하며 코드 분석 툴로 Jacoco&amp;amp;Sonarqube를 사용하고 있는 상황이며, 더 나은 코드 품질을 위해 Sonarqube의 Rules 설정을 통한 코드컨벤션을 적용하려 합니다. 코드&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0andwild.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 글에서는 Sonarqube와의 연동까지 되어 있는데 우선 이부분은 다음과정에서 적용을 하시길 바라며 우선 로컬 프로젝트 환경에서 까지만 적용을 하신 후 체크를 진행하시길 바랍니다. =)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 check style 적용을 마무리로 1편을 마치며 다음 글에서 소나큐브 설치 및 셋팅, 도커이미지 생성, 도커허브 연동, Jenkins의 Publish Over SSH 플러그인을 통한 두 번째 EC2인스턴스와의 연동과 함께 NGINX 블루 그린 배포를 마무리 하도록 하겠습니다. =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DailyStudy/CI CD</category>
      <category>Blue Green 배포</category>
      <category>docker</category>
      <category>Docker hub</category>
      <category>Gitea</category>
      <category>jacoco</category>
      <category>Jenkins CI/CD</category>
      <category>nginx</category>
      <category>sonarqube</category>
      <category>Stylecheck</category>
      <author>Dev_0andWild</author>
      <guid isPermaLink="true">https://0andwild.tistory.com/35</guid>
      <comments>https://0andwild.tistory.com/35#entry35comment</comments>
      <pubDate>Sat, 5 Nov 2022 08:57:52 +0900</pubDate>
    </item>
  </channel>
</rss>