0808 ~ 0814


# 0808 ~ 0814

# 0808 - Procedure์™€ Function ์ฐจ์ด

# [ Procedure ํ”„๋กœ์‹œ์ €๋ž€? ]

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ผ๋ จ์˜ ์ž‘์—…์„ ์ •๋ฆฌํ•œ ์ ˆ์ฐจ๋ฅผ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์— ์ €์žฅํ•œ ๊ฒƒ์œผ๋กœ ์˜๊ตฌ์ €์žฅ๋ชจ๋“ˆ(Persistent Storage Module)์ด๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค.
์ผ๋ จ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋งˆ์น˜ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ฟผ๋ฆฌ์˜ ์ง‘ํ•ฉ์ด๋‹ค.
์ฆ‰, ํ•˜๋‚˜์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ฟผ๋ฆฌ์˜ ๋ชจ์Œ์ด๋‹ค.

CALL ํ”„๋กœ์‹œ์ €๋ช…(INํŒŒ๋ผ๋ฏธํ„ฐ๋ช…, @OUTํŒŒ๋ผ๋ฏธํ„ฐ๋ช…)
EXECUTE ํ”„๋กœ์‹œ์ €๋ช…(INํŒŒ๋ผ๋ฏธํ„ฐ๋ช…, @OUTํŒŒ๋ผ๋ฏธํ„ฐ๋ช…)

---

CREATE OR REPLACE PROCEDURE ํ”„๋กœ์‹œ์ ธ์ด๋ฆ„ (ํŒŒ๋ผ๋ฏธํ„ฐ1,ํŒŒ๋ผ๋ฏธํ„ฐ2...);

IS
๋ณ€์ˆ˜

BEGIN

์ฟผ๋ฆฌ๋ฌธ

END ํ”„๋กœ์‹œ์ ธ ์ด๋ฆ„;

---

CREATE OR REPLACE PROCEDURE GET_TIER(in_name IN VARCHAR2,out_tier OUT VARCHAR2)

IS

BEGIN
	
    SELECT TIER INTO out_tier FROM SUMMONER_TB WHERE NAME = in_name;

EXCEPTION
  --์†Œํ™˜์‚ฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์„ ๋•Œ
  WEHN NO_DATA_FOUND THEN
  
    out_tier:='NO_SUMMONER_FOUND';

END GET_TIER;

# [ Function ํ•จ์ˆ˜๋ž€? ]

ํ•˜๋‚˜์˜ ํŠน๋ณ„ํ•œ ๋ชฉ์ ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋…๋ฆฝ์ ์œผ๋กœ ์„ค๊ณ„๋œ ์ฝ”๋“œ์˜ ์ง‘ํ•ฉ.
์ฆ‰, ํ•จ์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์œ„ํ•œ ๊ธฐ๋Šฅ์ด๋ผ๋ฉด ํ”„๋กœ์‹œ์ €๋Š” ์ž‘์—…์„ ์ •๋ฆฌํ•œ ์ ˆ์ฐจ์ด๋‹ค.
๋ณดํ†ต ๋กœ์ง์„ ๋„์™€์ฃผ๋Š” ์—ญํ• ์ด๋ฉฐ, ๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ, ์ˆ˜์น˜ ๋“ฑ์„ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

SELECT ํ•จ์ˆ˜๋ช…(IN ํŒŒ๋ผ๋ฏธํ„ฐ๋ช…) FROM DUAL;

---

CREATE OR REPLACE FUNCTION ํ•จ์ˆ˜์ด๋ฆ„(ํŒŒ๋ผ๋ฏธํ„ฐ1์ด๋ฆ„ ํƒ€์ž…, ํŒŒ๋ผ๋ฏธํ„ฐ2์ด๋ฆ„ ํƒ€์ž…...)
RETURN ๋ฐ˜ํ™˜ํ• ํƒ€์ž…
IS
	๋ณ€์ˆ˜ ์„ ์–ธ
BEGIN
	์‹คํ–‰๋ฌธ ์ž‘์„ฑ
	RETURN ๋ฐ˜ํ™˜ํ• ๊ฐ’
END;

--- 

CREATE OR REPLACE FUNCTION SUM_TWICE(n1 NUMBER, n2 NUMBER)
RETURN NUMBER
IS
	twice_sum  NUMBER := 0;
BEGIN
	twice_sum := (n1 + n2)*2;
	RETURN twice_sum;
END;

# [ ํ•จ์ˆ˜์™€ ํ”„๋กœ์‹œ์ €์˜ ์ฐจ์ด ]

ํ”„๋กœ์‹œ์ € ๋˜ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ณ , ํ•จ์ˆ˜ ๋˜ํ•œ ๋งค๊ฒจ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

# ๋งค๊ฐœ๋ณ€์ˆ˜

  • ํ”„๋กœ์‹œ์ €๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ, ์ถœ๋ ฅ, ์ž…์ถœ๋ ฅ ํ˜•์‹์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ ํ˜•์‹์œผ๋กœ๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

# ๋ฐ˜ํ™˜๊ฐ’

  • ํ”„๋กœ์‹œ์ €๋Š” ๋ฐ˜ํ™˜๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ๋„ ์žˆ๊ณ  ๊ฐ€์ง€์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜๋Š” ๋ฐ˜ํ™˜๊ฐ’์„ ๋ฐ˜๋“œ์‹œ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.

# ์ฟผ๋ฆฌ๋ฌธ ๋‚ด์—์„œ ์‹คํ–‰๊ฐ€๋Šฅ

  • ํ”„๋กœ์‹œ์ €๋Š” SELECT, WHERE ๋ฌธ๋“ฑ์—์„œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€ํ•˜๋‹ค.
  • ํ•จ์ˆ˜๋Š” SELECT, WHERE ๋ฌธ ๋“ฑ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

# ์ฒ˜๋ฆฌ ์žฅ์†Œ

  • ํ”„๋กœ์‹œ์ €๋Š” ํด๋ผ์ด์–ธํŠธ(ํ™”๋ฉด)์—์„œ ๊ฐ’์„ ๊ฑด๋„ค๋ฐ›์•„ ์„œ๋ฒ„์—์„œ ์ž‘์—…์„ ํ•œ ๋’ค ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค. ์ฆ‰, ์„œ๋ฒ„์—์„œ ์‹คํ–‰์ด ๋˜์–ด ์†๋„๋ฉด์—์„œ ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ค€๋‹ค.
  • ํ•จ์ˆ˜๋Š” ํด๋ผ์ด์–ธํŠธ(ํ™”๋ฉด)์—์„œ ์‹คํ–‰์ด ๋˜์–ด ํ”„๋กœ์‹œ์ €๋ณด๋‹ค ์†๋„๊ฐ€ ๋Š๋ฆฌ๋‹ค.

# 0809 - Feign Client

ํŽ˜์ธ์€ ๋„ทํ”Œ๋ฆญ์Šค์—์„œ ๊ฐœ๋ฐœํ•œ ์›น ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ ๋„๊ตฌ(Http Client ๋ชจ๋“ˆ)๋กœ ์• ๋…ธํ…Œ์ด์…˜์„ ํ…œํ”Œ๋ฆฟํ™”๋œ ์š”์ฒญ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ๋™์ž‘ํ•˜๋Š” HTTP ํด๋ผ์ด์–ธํŠธ ๋ฐ”์ธ๋”๋‹ค. ๊ธฐ์กด HTTP client ์ž‘์„ฑ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋ฉฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์• ๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ด๋Š” ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

# Feign ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

# [ ์˜์กด์„ฑ์ฃผ์ž… ]

  • maven
<properties>
    <spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • gradle
buildscript {
  dependencies {
    classpath "io.spring.gradle:dependency-management-plugin:1.0.10.RELEASE"
  }
}

ext {
  set('springCloudVersion', "Hoxton.SR8")
}

apply plugin: "io.spring.dependency-management"

dependencyManagement {
  imports {
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
  }
}

# [ Application ]

@SpringBootApplication
@EnableFeignClients
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

@EnableFeignClients ์–ด๋…ธํ…Œ์ด์…˜์ด ์ง€์ •๋œ package๋“ค์„ ๋Œ์•„๋‹ค๋‹ˆ๋ฉด์„œ @FeignClient ์–ด๋…ธํ…Œ์ด์…˜์„ ์ฐพ์•„ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

# [ Interface ์ž‘์„ฑ ]

@FeignClient(name = "stores", configuration = FooConfiguration.class, url = "${feign.url}")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    Page<Store> getStores(Pageable pageable);

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);
}
  • @FeignClent ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด feign์„ ์‚ฌ์šฉํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ผ๊ณ  ์•Œ๋ฆฐ๋‹ค.
  • configuration ์˜ต์…˜์„ ํ†ตํ•ด default ๊ฐ’์„ override ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • url ์˜ต์…˜์„ ํ†ตํ•ด ๋ถˆ๋Ÿฌ์˜ฌ url์„ ์„ธํŒ…ํ•œ๋‹ค.

# [ Service ์ž‘์„ฑ ]

@Service
public class StoreService {
    
    private final StoreClient storeClient;

	public StoreService(StoreClient storeClient) {
		this.storeClient = storeClient;
	}

    public List<Store> getStores() {
        return storeClient.getStores();
    }
}
  • getStores()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ FeignClient๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

# 0811 - jenkins pipeline

์›นํ›…์—†์ด ๊ธฐ๋ณธ์ ์ด pipeline์œผ๋กœ ํด๋ก , ๋นŒ๋“œ, ๋ฐฐํฌ๊นŒ์ง€๋งŒ ์ง„ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•

# [ Credentials ์„ธํŒ… ]

  • Jenkins ๊ด€๋ฆฌ -> Manage Credentials -> Add Credentials
  • Jenkins ๊ด€๋ฆฌ -> ์‹œ์Šคํ…œ ์„ค์ • -> GitHub -> ์„œ๋ฒ„๋“ฑ๋ก

# [ Git Parameter ]

  • Git Parameter Plug-In ์„ค์น˜
  • ํŒŒ์ดํ”„๋ผ์ธ -> ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ค์ •

# [ SSH ์„œ๋ฒ„๋กœ ํŒŒ์ผ์ „์†ก ]

  • publish over ssh ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜
  • Jenkins ๊ด€๋ฆฌ -> ์‹œ์Šคํ…œ ์„ค์ • -> ์›๊ฒฉ ์„œ๋ฒ„ ์„ค์ •

# [ ํŒŒ์ดํ”„ ๋ผ์ธ ์ƒ์„ฑ ]

  • ์ƒˆ๋กœ์šด item -> ํŒŒ์ดํ”„๋ผ์ธ ์ƒ์„ฑ
  • Pipeline Syntaxํ†ตํ•ด ์Šค๋‹ˆํŽซ ์„ค์ •
pipeline {
    agent any
    parameters {
        gitParameter branchFilter: 'origin/(.*)', defaultValue: 'develop', name: 'BRANCH', type: 'PT_BRANCH'
    }
    stages {
        stage('github clone') {
            steps {
                git branch: "${params.BRANCH}", credentialsId: 'jaesungahn91', url: 'https://github.com/wiiee-kr/wiiee-server.git'
            }
        }
        
        stage('build'){
            steps{
                sh'''
                    ./gradlew api:clean api:bootJar
                '''
            }
        }   
        
        stage('publish on ssh'){
            steps{
                sshPublisher(
                  publishers: 
                    [
                      sshPublisherDesc(
                        configName: 'wiiee-api-test', 
                        transfers: 
                          [
                            sshTransfer(
                              cleanRemote: false, 
                              excludes: '',
                              execCommand: 'sh /home/ec2-user/deploy.sh', 
                              execTimeout: 120000, 
                              flatten: false, 
                              makeEmptyDirs: false, 
                              noDefaultExcludes: false, 
                              patternSeparator: '[, ]+', 
                              remoteDirectory: './', 
                              remoteDirectorySDF: false, 
                              removePrefix: 'api/build/libs/', 
                              sourceFiles: 'api/build/libs/*.jar')
                          ], 
                        usePromotionTimestamp: false, 
                        useWorkspaceInPromotion: false, 
                        verbose: true)
                    ]
                )
            }
        }
    }
}

# 0813 - Git Submodule

credential ํŒŒ์ผ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ค‘ ํ•˜๋‚˜๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” Git Submodule์— ๋Œ€ํ•ด ํ•™์Šตํ•˜์ž.

  • git submodule
  • ์„ค์ •ํŒŒ์ผ ์•”ํ˜ธํ™”
    • Jasypt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • Spring Cloud Config๋ฅผ ํ†ตํ•œ ์„ค์ •ํŒŒ์ผ ๋ถ„๋ฆฌ

# [ Git Submodule์ด๋ž€ ]

๋ฉ”์ธ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ํ•˜์œ„ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋‘๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ด๋‹ค. ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰, Git ์ €์žฅ์†Œ ์•ˆ์— ๋‹ค๋ฅธ Git ์ €์žฅ์†Œ๋ฅผ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋ถ„๋ฆฌํ•ด ๋„ฃ๋Š” ๊ฒƒ์ด ์„œ๋ธŒ๋ชจ๋“ˆ์ด๋‹ค. ๋‹ค๋ฅธ ๋…๋ฆฝ๋œ Git ์ €์žฅ์†Œ๋ฅผ Clone ํ•ด์„œ ๋‚ด Git ์ €์žฅ์†Œ ์•ˆ์— ํฌํ•จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ ์ €์žฅ์†Œ์˜ ์ปค๋ฐ‹์€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

# [ Git Submodule ์‚ฌ์šฉ๋ฐฉ๋ฒ• ]

# ์„œ๋ธŒ ๋ชจ๋“ˆ์ถ”๊ฐ€

  • git submodule add {URL}
$ git submodule add https://github.com/chaconinc/DbConnector
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ธŒ๋ชจ๋“ˆ์€ ํ”„๋กœ์ ํŠธ ์ €์žฅ์†Œ์˜ ์ด๋ฆ„์œผ๋กœ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค. ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์œผ๋กœ ์„œ๋ธŒ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

# ์„œ๋ธŒ๋ชจ๋“ˆ ํ™•์ธ

  • git status
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   .gitmodules
    new file:   DbConnector
  • .gitmodules
[submodule "DbConnector"]
    path = DbConnector
    url = https://github.com/chaconinc/DbConnector
  • git diff
$ git diff --cached DbConnector
diff --git a/DbConnector b/DbConnector
new file mode 160000
index 0000000..c3f01dc
--- /dev/null
+++ b/DbConnector
@@ -0,0 +1 @@
+Subproject commit c3f01dc8862123d317dd46284b05b6892c7b29bc
  • Git์€ DbConnector ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„œ๋ธŒ๋ชจ๋“ˆ๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์˜ ํŒŒ์ผ ์ˆ˜์ •์‚ฌํ•ญ์„ ์ง์ ‘ ์ถ”์ ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹  ์„œ๋ธŒ๋ชจ๋“ˆ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํ†ต์งธ๋กœ ํŠน๋ณ„ํ•œ ์ปค๋ฐ‹์œผ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค.
$ git diff --cached --submodule
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..71fc376
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "DbConnector"]
+       path = DbConnector
+       url = https://github.com/chaconinc/DbConnector
Submodule DbConnector 0000000...c3f01dc (new submodule)
  • git commit & git push
$ git commit -am 'added DbConnector module'
[master fb9093c] added DbConnector module
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 DbConnector

DbConnector ๋””๋ ‰ํ† ๋ฆฌ ๋ชจ๋“œ๋Š” 160000์ด๋‹ค. git์—๊ฒŒ ์žˆ์–ด 160000๋ชจ๋“œ๋Š” ์ผ๋ฐ˜์ ์ธ ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ ํŠน๋ณ„ํ•˜๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

$ git push origin master

# ์„œ๋ธŒ๋ชจ๋“ˆ ํฌํ•จํ•œ ํ”„๋กœ์ ํŠธ Clone

$ git clone https://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
$ cd MainProject
$ ls -la
total 16
drwxr-xr-x   9 schacon  staff  306 Sep 17 15:21 .
drwxr-xr-x   7 schacon  staff  238 Sep 17 15:21 ..
drwxr-xr-x  13 schacon  staff  442 Sep 17 15:21 .git
-rw-r--r--   1 schacon  staff   92 Sep 17 15:21 .gitmodules
drwxr-xr-x   2 schacon  staff   68 Sep 17 15:21 DbConnector
-rw-r--r--   1 schacon  staff  756 Sep 17 15:21 Makefile
drwxr-xr-x   3 schacon  staff  102 Sep 17 15:21 includes
drwxr-xr-x   4 schacon  staff  136 Sep 17 15:21 scripts
drwxr-xr-x   4 schacon  staff  136 Sep 17 15:21 src
$ cd DbConnector/
$ ls
$
  • ํ”„๋กœ์ ํŠธ๋ฅผ Cloneํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ธŒ๋ชจ๋“ˆ ๋””๋ ‰ํ† ๋ฆฌ๋Š” ๋นˆ ๋””๋ ‰ํ† ๋ฆฌ์ด๋‹ค.
  • ์ดํ›„์— git submodule init ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ์„œ๋ธŒ๋ชจ๋“ˆ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋กœ์ปฌ ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ์ด ์ค€๋น„๋œ๋‹ค. ์ดํ›„ git submodule update ๋ช…๋ น์œผ๋กœ ์„œ๋ธŒ๋ชจ๋“ˆ์˜ ๋ฆฌ๋ชจํŠธ ์ €์žฅ์†Œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์„œ๋ธŒ๋ชจ๋“ˆ์„ ํฌํ•จํ•œ ํ”„๋กœ์ ํŠธ์˜ ํ˜„์žฌ ์Šค๋ƒ…์ƒท์—์„œ Checkout ํ•ด์•ผ ํ•  ์ปค๋ฐ‹ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€์„œ ์„œ๋ธŒ๋ชจ๋“ˆ ํ”„๋กœ์ ํŠธ์— ๋Œ€ ํ•œ Checkout์„ ํ•œ๋‹ค.
$ git submodule init
Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
$ git submodule update
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
  • DbConnector ๋””๋ ‰ํ† ๋ฆฌ๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปค๋ฐ‹์„ ํ–ˆ๋˜ ์ƒํƒœ๋กœ ๋ณต์›๋œ๋‹ค.
  • ๋ฐฉ๊ธˆ ๊ณผ์ •์„ ๋ฉ”์ธ ํ”„๋กœ์ ํŠธ๋ฅผ Clone ํ•  ๋•Œ git clone ๋ช…๋ น ๋’ค์— --recurse-submodules ์˜ต์…˜์„ ๋ถ™์ด๋ฉด ์„œ๋ธŒ๋ชจ๋“ˆ์„ ์ž๋™์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
$ git clone --recurse-submodules https://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'

๋ฉ”์ธ ํ”„๋กœ์ ํŠธ์— submodule์ด ์ด๋ฏธ ์žˆ๊ณ , ํ•˜์œ„ ํ”„๋กœ์ ํŠธ์˜ ์ƒˆ๋กœ์šด ์ปค๋ฐ‹์„ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—์„  update ๋ช…๋ น์–ด๋ฅผ ํ™œ์šฉํ•œ๋‹ค. ์ด ๋ช…๋ น์–ด๋กœ ๋ฉ”์ธ ํ”„๋กœ์ ํŠธ์—์„œ submodule์˜ ์ปค๋ฐ‹์„ ๊ฐ€์ ธ์˜ค๋ฉด, ์ด์ „์— ๋ดค๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒˆ๋กœ ์ปค๋ฐ‹ํ•ด์•ผ ํ•˜๋Š” ํŒŒ์ผ์ด ์ƒ๊ธด๋‹ค. ์•ž์„œ ํ•œ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ ํ•ด๋‹น ํŒŒ์ผ์„ add, commit, pushํ•ด์„œ ๋กœ์ปฌ๊ณผ ์›๊ฒฉํ”„๋กœ์ ํŠธ์— ๋ฐ˜์˜ํ•œ๋‹ค.

$ git submodule update --remote --merge

// .gitmodules ํŒŒ์ผ์— ์ •์˜๋˜์–ด ์žˆ๋Š” ๋ธŒ๋žœ์น˜(default๋Š” main ๋˜๋Š” master)์˜ ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ์—…๋ฐ์ดํŠธ
// $ git submodule update --remote

// ๋กœ์ปฌ์—์„œ ์ž‘์—… ์ค‘์ธ ๋ถ€๋ถ„๊ณผ ์›๊ฒฉ์— ์ž‘์—…๋œ ๋ถ€๋ถ„์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ ๋จธ์ง€๊นŒ์ง€ ์ง„ํ–‰
// $ git submodule update --remote --merge

# 0814 - ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ(Annotation Processor)

# Annotation Processor๋ž€?

โ€œAnnotation Processingโ€ is a hook into the compile process of the java compiler, to analyse the source code for user defined annotations and handle then (by producing compiler errors, compiler warning, emitting source code, byte code โ€ฆ).

Annotation Processor๋Š” ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ Annotation์— ์ •์˜๋œ ์ผ๋ ฌ์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋นŒ๋“œ ๋‹จ๊ณ„์—์„œ ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๊ณ  ์†Œ์Šค์ฝ”๋“œ ๋ฐ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์‚ฌ์šฉํ•˜๋Š” ์˜ˆ๋กœ ์ž๋ฐ”์˜ @Override๊ฐ€ ์žˆ์œผ๋ฉฐ, Lombok(๋กฌ๋ถ) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์žˆ๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด ์•„๋‹ˆ๋ฉด annotationProcessor๋ฅผ ํ†ตํ•ด ์ถ”๊ฐ€ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

# Lombok๊ณผ Annotation Processor

Lombok์ด๋ž€ @Getter, @Setter, @Builder ๋“ฑ์˜ Annotation๊ณผ Annotation Processor๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ‘œ์ค€์ ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•  ์ฝ”๋“œ๋ฅผ ๊ฐœ๋ฐœ์ž ๋Œ€์‹  ์ƒ์„ฑํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.
์ปดํŒŒ์ผ ์‹œ์ ์— Annotation Processor๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ abstract syntaxtree๋ฅผ ์กฐ์ž‘ํ•œ๋‹ค.

# ์ž‘๋™์›๋ฆฌ

# Moja Interface

@Magic
public interface Moja {

    String pullOut();
}

# Magic ์• ๋…ธํ…Œ์ด์…˜

  • Target์„ TYPE์œผ๋กœ ์ง€์ •ํ•˜๋ฉด, ์ธํ„ฐํŽ˜์ด์Šค, ํด๋ž˜์Šค, ENUM์— ์ง€์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • Rentention์ •๋ณด๋ฅผ ์†Œ์Šค๋ ˆ๋ฒจ ๊นŒ์ง€๋งŒ ์œ ์ง€ํ•˜๊ณ , ์ปดํŒŒ์ผ ์‹œ์ ์— ์• ํ† ๋„ค์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•ด MagicMoja๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
@Target(ElementType.TYPE) // TYPE ์œผ๋กœ ์ง€์ •ํ•˜๋ฉด, ์ธํ„ฐํŽ˜์ด์Šค ,ํด๋ž˜์Šค, enum์— ์ง€์ •์ด ๊ฐ€๋Šฅํ•จ.
@Retention(RetentionPolicy.SOURCE) // ์†Œ์Šค๋ ˆ๋ฒจ์—์„œ ๋งŒ ์œ ์ง€ํ•˜๊ณ , ์ปดํŒŒ์ผ์‹œ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋กœ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ• ๊ฒƒ์ž„
public @interface Magic {

}
public class App {
    public static void main( String[] args ) {
        // MagicMoja ๊ฐ€ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ์ƒ์„ฑํ•  ํด๋ž˜์Šค์ด๋‹ค.
        Moja moja = new MagicMoja();
        System.out.println(moja.pullOut());
    }
}
  • ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, @Magic ์• ๋…ธํ…Œ์ด์…˜์ด ์ ์šฉ๋œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์กด์žฌํ•˜๋ฉด, MagicMoja ๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

# MagicMojaProcessor

/**
 * Process ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋„ ๋˜์ง€๋งŒ, ์ž๋ฐ”์—์„œ ์ œ๊ณตํ•˜๋Š” AbstractProcessor ์ถ”์ƒํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋„ ๋œ๋‹ค.
 * Process ์—์„œ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋“ค์„ ๊ตฌํ˜„ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.
 */
public class MagicMojaProcessor extends AbstractProcessor {

    /**
     * ์ด ํ”„๋กœ์„ธ์„œ๊ฐ€ ์–ด๋–ค ์• ๋…ธํ…Œ์ด์…˜๋“ค์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ์ง€ ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ.
     *
     * Element๋ž€ ?
     * - ํŒจํ‚ค์ง€
     * - ํด๋ž˜์Šค
     * - ๋ฉ”์„œ๋“œ
     * ์†Œ์Šค์ฝ”๋“œ์˜ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์—˜๋ฆฌ๋จผํŠธ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค
     * ๊ฐ ์—˜๋ฆฌ๋จผํŠธ๋“ค์ด ํ”„๋กœ์„ธ์Šค๋ฅผ ํ• ๋•Œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
     * @return
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Set.of(Magic.class.getName());
    }

    /**
     * ๋ช‡ ๋ฒ„์ „์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ์„ค์ •.
     * - ์ตœ์‹ ๋ฒ„์ „ ์ง€์›ํ•˜๋„๋ก ์„ค์ •
     * @return
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    /**
     * ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋Š” ๋ผ์šด๋“œ ๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
     * - ์—ฌ๋Ÿฌ ๋ผ์šด๋“œ์— ๊ฑฐ์ณ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
     * - ๊ฐ ๋ผ์šด๋“œ๋งˆ๋‹ค ํ”„๋กœ์„ธ์„œ์—๊ฒŒ ํŠน์ • ์• ๋…ธํ…Œ์ด์…˜์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ฐพ์œผ๋ฉด ์ฒ˜๋ฆฌ๋ฅผ ์š”์ฒญํ•œ๋‹ค.
     * - ์ฒ˜๋ฆฌ๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค์Œ ๋ผ์šด๋“œ์—๊ฒŒ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋‹ค.
     * - Filter Chaining ๊ณผ ์–ด์ฐŒ๋ณด๋ฉด ๋น„์Šทํ•œ ๋Š๋‚Œ์ด๋‹ค.
     *
     * ๋งŒ์•ฝ ์—ฌ๊ธฐ์„œ true๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉด, ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๊ฐ€ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๊ฒƒ์ด๋‹ค.
     * true๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉด, ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์„œ๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
     * @param annotations
     * @param roundEnv
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        /* ์ ์ ˆํ•œ ์œ„์น˜์— ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ–ˆ๋Š”์ง€ ์ฒดํฌ */
        /* ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ ์—˜๋ฆฌ๋จผํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ์ˆ˜ ์žˆ๋‹ค.*/
        Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(Magic.class);
        for (Element element : elementsAnnotatedWith) {
            /* ์• ๋…ธํ…Œ์ด์…˜์ด ์ธํ„ฐํŽ˜์ด์Šค ์•„๋‹Œ๊ณณ์— ์‚ฌ์šฉํ–ˆ์„ ๊ฒฝ์šฐ */
            if (element.getKind() != ElementKind.INTERFACE) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@Magic ์• ๋…ธํ…Œ์ด์…˜์€ Interface๋งŒ ์ง€์›ํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜ ์ž…๋‹ˆ๋‹ค.");
            } else {
                // ๋กœ๊น…
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing " + element.getSimpleName());
            }
        }
        return true;
    }
}
  • Processor Interface๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋˜์ง€๋งŒ, ์ž๋ฐ”์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” AbstractProcessor ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผํ•  ๊ฒƒ๋“ค์„ ์–ด๋Š์ •๋„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.

์ฃผ์š” ๋ฉ”์„œ๋“œ

  • getSupportedAnnotationTypes : ์ด ํ”„๋กœ์„ธ์„œ๊ฐ€ ์ฒ˜๋ฆฌํ•  ์• ๋…ธํ…Œ์ด์…˜๋“ค์„ ์ง€์ •ํ•œ๋‹ค.
  • getSupportedSourceVersion : ์†Œ์Šค์ฝ”๋“œ ๋ฒ„์ „์„ ๋ช‡๊นŒ์ง€ ์ง€์›ํ•  ๊ฒƒ์ธ์ง€ ์ง€์ •ํ•œ๋‹ค.
  • process : ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๊ฐ€ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๊ฐ€ ์ฒ˜๋ฆฌํ•  ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์—˜๋ฆฌ๋จผํŠธ ๋“ค์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์—˜๋ฆฌ๋จผํŠธ๋ž€? ์†Œ์Šค์ฝ”๋“œ์˜ ๊ตฌ์„ฑ์š”์†Œ๋“ค์„ ์—˜๋ฆฌ๋จผํŠธ๋ผ๊ณ  ํ•œ๋‹ค(ํŒจํ‚ค์ง€ ์—˜๋ฆฌ๋จผํŠธ, ํด๋ž˜์Šค ์—˜๋ฆฌ๋จผํŠธ, ๋ฉ”์„œ๋“œ ์—˜๋ฆฌ๋จผํŠธ)
    • ๊ฐ ์—˜๋ฆฌ๋จผํŠธ๋“ค์„ ํ”„๋กœ์„ธ์Šคํ• ๋•Œ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
Last update: September 13, 2022 21:44
Contributors: ahnjs