ํ ๋ฆฌํ์คํธ๋น 10๊ฐ์ ๋ฌธ์ ๋ฅผ ์ง์ ํ๋ ์ ์ ๋ถ์ ๋๊ตฌ๊ฐ ์๋๋ฐ, ๊ทธ์ค 2๊ฐ๋ ์ค์ ๋ฌธ์ ์ด๊ณ 8๊ฐ๋ ์คํ์ด๋ผ๋ฉด, ์์ ๋๋ ๋์ ์ฌ์ฉ ์ค์ง๋ฉ๋๋ค. ๊ฒฝ๊ณ ํผ๋ก๋ ์ ์ ๋ถ์ ํ๋ก๊ทธ๋จ์ด ์ค์ ๋ก ์คํจํ๋ ๊ฐ์ฅ ํํ ์ด์ ์ ๋๋ค. ๊ฐ๋ฐ์๋ค์ 8๊ฐ์ ์คํ์ ์กฐ์ฌํด์ 2๊ฐ์ ์ค์ ๋ฌธ์ ๋ง ๋ฐ๊ฒฌํ๊ฒ ๋๋ฉด, ๊ฒฐ๊ตญ ์กฐ์ฌ๋ฅผ ๊ฑด๋๋ฐ๊ฒ ๋ฉ๋๋ค. ์ผ๋ง ์ง๋์ง ์์ ๋๊ตฌ๋ ๊ณ์ ์คํ๋๋ฉด์ ์๋ฌด๋ ์ฝ์ง ์๋ ๊ฒฝ๊ณ ๋ง ์์ฑํ๊ณ , ์ค์ ๋ณด์ ํ๋์ ์์ผ๋ฉด์๋ ๋ณด์ ํ๋์ ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ๋ง๋ญ๋๋ค.
์ ์ ๋ถ์ ๋๊ตฌ๊ฐ ์คํ์ ๋ฐ์์ํค๋ ๊ฒ ์์ฒด๊ฐ ๋ฌธ์ ๋ ์๋๋๋ค. ์ด๋ก ์ ์ผ๋ก ์์ ํ ์ฝ๋์กฐ์ฐจ๋ ์ค๋ฅ๋ก ํ์ํ ์๋ฐ์ ์๋ ์ค๊ณ์์ ํ๊ณ ๋๋ฌธ์ ๊ณผ๋ํ๊ฐ๋ ๋ถ๊ฐํผํฉ๋๋ค. ์ง์ง ๋ฌธ์ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ์ฌํ ๊ฐ๋ฅํ๋ฉฐ, ์ค์ ๋ณ๊ฒฝ, ์ค๋ฅ ์ต์ ๋๋ ๋ ๋์ ๋๊ตฌ๋ฅผ ํตํด ์์ ๊ฐ๋ฅํ ์คํ์ ๋๋ค. ์ด๋ฌํ ์คํ์ ์ค์ด๊ธฐ ์ํด ๋ถ์์ ์๊ฒฉํจ์ ํฌ๊ธฐํ ํ์๋ ์์ต๋๋ค. ๊ฐ ์คํ์ด ๋ฐ์ํ ์ด์ ๋ฅผ ํ์ ํ๊ณ , ๊ท์น ์กฐ์ ์ด๋ ์ค๋ฅ ์ต์ ๋ฅผ ํตํด ์ ๊ฑฐํ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ํ๋จํ๋ฉฐ, ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์คํ ๋ฐ์๋ฅ ์ด ๊ฐ์ ๋๋์ง ์ธก์ ํ๋ ๋ฐฉ๋ฒ์ ์์์ผ ํฉ๋๋ค.
์ฌ์ฉ๋์ง ์๋ ์ฝ๋์์ ๋ฐ๊ฒฌ๋ ๋ด์ฉ์ ๋ํ ์กฐ์ฌ ์์ ์ ์ค๋จํ์ธ์.
SMART TS XL ํ์ด ์๊ฐ์ ๋ญ๋นํ๊ธฐ ์ ์ ์ ๊ทผํ ์ ์๋ ์ฝ๋์ ์ด๋ค ํ๋๊ทธ๋ ํจํด์ด ์๋์ง ์๋ณํฉ๋๋ค.
๋ ๋ง์ ์ ๋ณด์ ์ ์ฝ๋ ๋ถ์์์ ์คํ(False Positive)์ด๋ ๋ฌด์์ธ๊ฐ์?
์คํ(false positive)์ ์ ์ ๋ถ์ ๋๊ตฌ๊ฐ ์ค์ ๋ก๋ ์ฌ๋ฐ๋ฅธ ์ฝ๋๋ฅผ ๋ฌธ์ ์๋ ์ฝ๋๋ก ์๋ชป ํ์ํ๋ ๊ฒฝ์ฐ๋ฅผ ๋งํฉ๋๋ค. ํ์๋ ์ฝ๋๋ ๋ฐํ์ ์ ๋ฒ๊ทธ, ์ทจ์ฝ์ ๋๋ ํ์ง ์๋ฐ์ ๋ฐ์์ํค์ง ์์ต๋๋ค. ๋๊ตฌ์ ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ํ๋ก๊ทธ๋จ์ ์ค์ ๋์๊ณผ ์ผ์นํ์ง ์๋ ๊ฒ์ ๋๋ค.
์ ์ฒด ๋ถ๋ฅ ์ฒด๊ณ๋ฅผ ์ดํดํ๋ฉด ๋ฌด์์ ๋จผ์ ์์ ํด์ผ ํ ์ง ์ฐ์ ์์๋ฅผ ์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
| ๊ฒฐ๊ณผ ์ ํ | ๋๊ตฌ๊ฐ ๋งํฉ๋๋ค | ํ์ค | ๋ฌด์์ํด์ผํ ์ง |
|---|---|---|---|
| ์ง์ ํ ๊ธ์ | ๋ฌธ์ ๋ฐ๊ฒฌ | ์ง์ง ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค | ์ฝ๋๋ฅผ ์์ ํ์ธ์ |
| ๊ฑฐ์ง ๊ธ์ | ๋ฌธ์ ๋ฐ๊ฒฌ | ๋ณ๋ฌธ์ ์์ด์ | ๊ท์น์ ์ต์ ํ๊ฑฐ๋ ์กฐ์ ํฉ๋๋ค. |
| ์ง์ ํ ๋ถ์ | ๋ฌธ์ ์์ | ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. | ์์ํ๋ ๋๋ก, ์ข๋ค์ |
| ์์์ฑ | ๋ฌธ์ ์์ | ์ง์ง ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค | ๋ถ์ ์ฌ๋/๊ท์น์ ๊ฐ์ ํ์ธ์ |
์ ์ถฉ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์คํ์ ์ค์ด๋ฉด(์ ๋ฐ๋๊ฐ ๋์์ง๋ฉด) ์ข ์ข ๋ฏธํ์ด ์ฆ๊ฐํฉ๋๋ค. ๊ท์น์ ๋ฏผ๊ฐ๋๋ฅผ ๋ฎ์ถ๋ฉด ๋ ธ์ด์ฆ๋ ์ค์ด๋ค์ง๋ง ์ค์ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ ๊ฐ๋ฅ์ฑ๋ ์ค์ด๋ญ๋๋ค. ๋ชฉํ๋ ์คํ์ ์์ ํ ์์ ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ๋ฐ์๊ฐ ๋๊ตฌ๋ฅผ ์ ๋ขฐํ๊ณ ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ์กฐ์ฌํ ์ ์์ ๋งํผ ์คํ๋ฅ ์ ๋ฎ์ถ๋ ๊ฒ์ ๋๋ค.
์ ์ ๋ถ์์์ ์คํ์ด ๋ฐ์ํ๋ ์ด์ : ๊ธฐ์ ์ ์์ธ
๊ฐ ์คํ ์ ํ์ ๋ฐ์ ๋ฉ์ปค๋์ฆ์ ์ดํดํ๋ฉด ์ฌ๋ฐ๋ฅธ ํด๊ฒฐ์ฑ ์ ์ฐพ์ ์ ์์ต๋๋ค.
1. ๋งฅ๋ฝ ์๋ ์ ์ฐจ ๋ด ๋ถ์
๋ง์ ๊ท์น์ ํธ์ถ์๊ฐ ์ด๋ฏธ ์ํํ ์์ ์ ์์ง ๋ชปํ ์ฑ ๋จ์ผ ํจ์ ๋ด์์ ์๋ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํธ์ถ์๊ฐ ํจ์ ํธ์ถ ์ ์ ํญ์ ํฌ์ธํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋๋ผ๋, ๋ ๊ฒ์ฌ ์์ด ํฌ์ธํฐ๋ฅผ ์ญ์ฐธ์กฐํ๋ ํจ์๋ ์ค๋ฅ๋ก ํ์๋ ์ ์์ต๋๋ค. ๋ถ์๊ธฐ๋ ํจ์ ๊ฒฝ๊ณ๋ฅผ ๋์ด ๋ด๋ถ ๋์์ ํ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
c
// Caller always validates before calling -- analyzer doesn't know this
void process(Data *d) {
int result = d->value; // flagged: potential null dereference
// But every caller looks like:
// if (d != NULL) process(d);
}
ํด๊ฒฐ ๋ฐฉ๋ฒ: ์ ์ฐจ ๊ฐ ๋ถ์์ผ๋ก ์ ํํ๊ฑฐ๋, ์ฃผ์์ ์ฌ์ฉํ์ฌ ๋ถ์๊ธฐ์ ์ฌ์ ์กฐ๊ฑด์ ์๋ ค์ฃผ์ธ์.
2. ๊ฐ ๋ฒ์์ ๊ณผ๋ ์ถ์
๋ณ์ ๋ฒ์๋ฅผ ๋ณด์์ ์ผ๋ก ์ถ์ ํ๋ ๊ฐ๊ฒฉ ๊ธฐ๋ฐ ๋ถ์๊ธฐ๋ ์ ์์ ๋ฒ์๊ฐ ๋๋ฌ ๊ฐ๋ฅํ ๋ชจ๋ ์ํ์์ 0์ ํฌํจํ์ง ์๋๋ผ๋ ๋๋์ ์ 0์ผ๋ก ๋๋๋ ๊ฒ์ผ๋ก ํ์ํ ์ ์์ต๋๋ค.
์๋ฐ
// Analyzer computes divisor range as [0, 100] and flags division by zero
// Actual runtime: config.getMinBatchSize() always returns >= 1
int batchCount = totalItems / config.getMinBatchSize(); // flagged
๊ณ ์น๋ค: ๋ถ์๊ธฐ๊ฐ ์ถ์ ํ๋ ๋ฒ์๋ฅผ ์ขํ๋ ์ด์ค์
๋๋ ์ฌ์ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฑฐ๋, ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ๋ถ์๊ธฐ๋ฅผ ๊ตฌ์ฑํ์ญ์์ค. getMinBatchSize().
3. ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค๊ฒฝ๋ณด
์ ์ ๋ถ์๊ธฐ๋ ์ผ๋ฐ์ ์ผ๋ก ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์์ ๋ํ ๋ชจ๋ธ์ ์ ๊ณตํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ ๋ ฅ๊ฐ์ ๋ด๋ถ์ ์ผ๋ก ๊ฒ์ฆํ๋ ์ํธํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๋ ๋ถ์๊ธฐ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์ค ์ฝ๋๋ฅผ ๊ฒ์ฌํ ์ ์๊ธฐ ๋๋ฌธ์ ์ถ๋ ฅ๊ฐ์ ์ ์ฌ์ ์ผ๋ก ์ ๋ขฐํ ์ ์๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํฉ๋๋ค.
4. ์๋ฏธ๋ก ์ ์ดํด ์์ด ์ ์ฉ๋๋ ํจํด ๊ท์น
๋ง์ ๋ณด์ ๊ท์น์ ํจํด ๊ธฐ๋ฐ์ ๋๋ค. ์๋ฅผ ๋ค์ด, "์ฌ์ฉ์ ์ ๋ ฅ์ SQL ๋ฌธ์์ด๋ก ์ฐ๊ฒฐํ๋ ๋ชจ๋ ํ์๋ SQL ์ธ์ ์ ๊ณต๊ฒฉ์ด๋ค."์ ๊ฐ์ ๊ท์น์ด ์์ต๋๋ค. ์ด ๊ท์น์ ์ทจ์ฝํ ์ฝ๋์์๋ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง๋ง, ์ ๋ ฅ๊ฐ์ ์ฐ๊ฒฐํ๊ธฐ ์ ์ ๊ฒ์ฆํ๋ ์ฝ๋์์๋ ์๋ชป ์๋ํฉ๋๋ค. ํจํด ๊ท์น์ด ๊ฒ์ฆ์ด ์ฌ๋ฐ๋ฅด๊ฑฐ๋ ์์ ํ์ง ํ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
5. ์ ์ ์ผ๋ก ํ๊ฐ๋ ์กฐ๊ฑด
์ด๋ SC ์ฟผ๋ฆฌ "์กฐ๊ฑด์ด ์ ์ ์ผ๋ก ๊ฑฐ์ง์ผ๋ก ํ๊ฐ๋์๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๋ถ์๋์ง ์์ต๋๋ค"์ ๊ทผ๋ณธ์ ์ธ ์์ธ์ ๋๋ค. Coverity/Clang ๋ถ์๊ธฐ์์ ํํ ๋ฐ์ํ๋ ๊ฒฝ๊ณ ์ด๋ฏ๋ก ๋ณ๋์ ์น์ ์์ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
"์กฐ๊ฑด์ด ์ ์ ์ผ๋ก ๊ฑฐ์ง์ผ๋ก ํ๊ฐ๋์๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๋ถ์๋์ง ์์ต๋๋ค."
์ด ๊ฒฝ๊ณ ๋ Coverity, Clang Static Analyzer ๋ฐ ์ ์ฌํ ๋๊ตฌ์์ ๋ถ์๊ธฐ๊ฐ ๋ถ๊ธฐ ์กฐ๊ฑด์ด ํญ์ ๊ฑฐ์ง์ด๋ผ๊ณ ํ๋จํ ๋ ๋ํ๋ฉ๋๋ค. ์ฆ, ํด๋น ๋ถ๊ธฐ ๋ด์ ์ฝ๋๋ ์ด๋ค ์คํ์์๋ ๋๋ฌํ ์ ์์ผ๋ฏ๋ก ๋ถ์๊ธฐ๊ฐ ํด๋น ๋ถ๊ธฐ ๋ด๋ถ ๋ถ์์ ์ค๋จํ๋ค๋ ์๋ฏธ์ ๋๋ค.
๋ฐ์ ์์ธ:
c
#define DEBUG 0 // compile-time constant
void process_record(Record *r) {
if (DEBUG) {
validate_record(r); // never analyzed -- condition always false
}
use_record(r); // potential issue here not caught if validate_record was needed
}
๋ถ์๊ธฐ๋ ํ๊ฐํฉ๋๋ค if (DEBUG) as if (0)์ด ๊ฒฝ๊ณ ๋ ํญ์ ๊ฑฐ์ง์ด๋ฉฐ ๋ณธ๋ฌธ์ ๋ถ์ํ์ง ์์ต๋๋ค. ์ด๋ ์ฌ๋ฐ๋ฅธ ๋์์
๋๋ค. ์ฝ๋๋ ์ค์ ๋ก ๋๋ฌํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ๊ณ ๋ ์ ๋ณด ์ ๊ณต์ฉ์ด๋ฉฐ ๋ฒ๊ทธ์ ๋ํ ์คํ์ด ์๋๋๋ค.
๋ฌธ์ ๊ฐ ๋๋ ์์ :
๋๋ฌํ ์ ์๋ ๋ถ๊ธฐ์ ํญ์ ์คํ๋๋๋ก ์๋๋ ์์ ๋๋ ๋ณด์ ๊ฒ์ฌ๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ, ๊ฒฝ๊ณ ๋ ๋ถ์ ์ค๋ฅ๊ฐ ์๋ ๋ ผ๋ฆฌ ์ค๋ฅ๋ฅผ ๋ํ๋ ๋๋ค. ์ฝ๋๊ฐ ์คํ๋์ง ์๋๋ก ๋ง๋๋ ์์์ ์๋ชป๋ ์กฐ๊ฑด๋ถ ์คํ ์กฐ๊ฑด์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ ์์ธ:
c
// Pattern 1: debug-only guard on production-required code
if (ENABLE_VALIDATION) { validate_input(data); } // if ENABLE_VALIDATION=0, no validation
// Pattern 2: error return always overwritten before checked
int result = do_operation();
result = 0; // overwrites result -- subsequent if (result != 0) is always false
if (result != 0) { handle_error(); } // never reached
// Pattern 3: overly conservative NULL check after guaranteed assignment
ptr = malloc(sizeof(Data));
if (ptr == NULL) { ... } // valid -- malloc can return NULL
ptr->value = 0;
if (ptr == NULL) { ... } // always false -- analyzer warns here correctly
ํด๊ฒฐ ๋ฐฉ๋ฒ: ํด๋น ๋ถ๊ธฐ์ ๋๋ฌํด์ผ ํ๋ ๊ฒฝ์ฐ ์กฐ๊ฑด์ ์์ ํ์ญ์์ค. ์๋์ ์ผ๋ก ์ฌ์ฉ๋์ง ์๋ ์ฝ๋์ด๋ฏ๋ก ์ ๊ฑฐํ ์ ์๋ ์ฝ๋๋ผ๋ฉด ์ ๊ฑฐํ์ญ์์ค. ๋๋ฒ๊ทธ ์ ์ฉ ์ฝ๋์ด๊ณ ์กฐ๊ฑด๋ฌธ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์์ฑ๋ ๊ฒฝ์ฐ, ๊ฒฝ๊ณ ๋ ์์๋๋ ๊ฒ์ด๋ฏ๋ก ํ์ํ์ง ์์๋ ๋ฉ๋๋ค.
๋ค์ํ ๋๊ตฌ์ ๊ฑธ์น ์ต์ ๋ฉ์ปค๋์ฆ
์ต์ (Suppression)๋ ํน์ ์์น์์ ํน์ ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์ํ๋๋ก ๋๊ตฌ์ ์ง์ํฉ๋๋ค. ์ฃผ์ ์ ์ ๋ถ์ ๋๊ตฌ๋ ๋ชจ๋ ์ต์ ๊ตฌ๋ฌธ์ ์ ๊ณตํฉ๋๋ค. ๊ท์น ์กฐ์ ์ด ํ์ค์ ์ผ๋ก ์ด๋ ค์ด, ํ์ธ๋ ์คํ์ ๋ํด ์ต์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ญ์์ค.
๊ฒฝ๊ณ : ์ฐจ๋จ ๊ธฐ๋ก์ ์ฃผ๊ธฐ์ ์ผ๋ก ๊ฒํ ํด์ผ ํฉ๋๋ค. 2023๋ ์ ์คํ์ผ๋ก ์ธํด ์ถ๊ฐ๋ ์ฐจ๋จ ์กฐ์น๊ฐ 2025๋ ์ ๋์ผํ ์์น์ ๋์ ๋ ์ค์ ์ทจ์ฝ์ ์ ์ฐจ๋จํ ์๋ ์์ต๋๋ค.
ESLint(์๋ฐ์คํฌ๋ฆฝํธ/ํ์ ์คํฌ๋ฆฝํธ)
์๋ฐ ์คํฌ๋ฆฝํธ
// Suppress next line
// eslint-disable-next-line no-unused-vars
const legacyAdapter = require('./legacy');
// Suppress a block
/* eslint-disable @typescript-eslint/no-explicit-any */
function processLegacyData(data: any): void { ... }
/* eslint-enable @typescript-eslint/no-explicit-any */
์๋ํ๋ธ / ์๋๋ฆฐํธ
์๋ฐ
@SuppressWarnings("java:S2077") // Suppress SQL injection rule for this method
public List<User> searchUsers(String query) {
// This method uses a parameterized query builder, not raw string concat
return queryBuilder.executeParameterized(query);
}
๋๋ SonarQube์์ ์ธ๋ผ์ธ ์ฃผ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ:
์๋ฐ
String hash = md5(password); // NOSONAR - md5 used for non-security cache key only
Pylint(ํ์ด์ฌ)
ํ์ด์ฌ
import os # pylint: disable=unused-import -- required for side-effect registration
def legacy_function():
pass # pylint: disable=W0107 -- intentionally empty for interface compliance
์ ๊ทธ๋
์
# .semgrepignore -- exclude paths
tests/fixtures/
vendor/
# Inline: suppress specific rule at a line
result = eval(expression) # nosemgrep: python.lang.security.audit.eval-injection
์ปค๋ฒ๋ฆฌํฐ
c
/* coverity[null_returns] */
Data *ptr = get_config(); // Coverity: ptr may be NULL
// Function contract guarantees non-NULL return when config is initialized
์ฒด๊ณ์ ์ธ ์คํ์ ์ค์ด๊ธฐ ์ํ ์กฐ์ ๊ท์น
์ต์ ๋ ๊ฐ๋ณ ์ฌ๋ก๋ฅผ ๋ค๋ฃน๋๋ค. ๊ท์น ์กฐ์ ์ ๊ท์น์ด ์ ์์ ์ธ ์ฝ๋์ ๋ํด ์ง์์ ์ผ๋ก ์คํ์ ์์ฑํ๋ ์ฒด๊ณ์ ์ธ ํจํด์ ํด๊ฒฐํฉ๋๋ค.
์
# SonarQube quality profile configuration
# Reduce sensitivity for cognitive complexity rule
sonar.java.cognitive.complexity.threshold=20 # default 15; raises bar for flagging
# Exclude generated code from analysis
sonar.exclusions=**/generated/**,**/proto/**,**/target/**
sonar.coverage.exclusions=**/*Test.java,**/*Spec.java
# Configure security hotspot categories by risk
# In sonar-project.properties:
sonar.security.hotspot.threshold=HIGH # only show HIGH severity hotspots
์
# ESLint: rule-level tuning
# .eslintrc or eslint.config.js
rules:
"@typescript-eslint/no-explicit-any": "warn" # was "error" -- downgrade for gradual migration
"complexity": ["warn", { "max": 20 }] # was 10 -- adjust for legacy codebase baseline
"max-lines-per-function": ["warn", { "max": 60, "skipBlankLines": true }]
๊ฒฝ๋ก ์ ์ธ๋ ๊ฐ์ฅ ๊ฐ์น ์๋ ํ๋ ์์ ์ค ํ๋์ ๋๋ค. ์์ฑ๋ ํ์ผ, ํ ์คํธ ํฝ์ค์ฒ, ๋ฒค๋ ์ฝ๋ ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ ์คํฌ๋ฆฝํธ๋ ์ ์์ ์ธ ํจํด์ด์ง๋ง ํ๋๊ทธ๊ฐ ์ง์ ๋ ์ ์์ต๋๋ค. ์ด๋ฌํ ํญ๋ชฉ์ ๋ถ์ ๋ฒ์์์ ์ ์ธํ๋ฉด ํ๋ก๋์ ์ฝ๋์ ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ ํ์ํค์ง ์์ผ๋ฉด์ ์คํ ๋ฐ์๋ฅ ์ ์ฆ์ ์ค์ผ ์ ์์ต๋๋ค.
CI/CD ํ์ดํ๋ผ์ธ์ ์คํ์ง
๋ถ์ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ๋ณํฉ์ ์ฐจ๋จํ๋ CI/CD ํ์ดํ๋ผ์ธ์์ ์คํ์ ๊ฐ๋ฐ ์๋์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ๋ณํฉํ ๋๋ง๋ค ์คํ 3๊ฐ๋ก ์ธํด ํ ๋ฆฌํ์คํธ๊ฐ ์ฐจ๋จ๋๋ฉด ๊ฐ๋ฐ์๋ ํด๋น ์ฐจ๋จ ๊ธฐ๋ฅ์ ์ ๋ขฐํ๊ธฐ๋ณด๋ค๋ ์ฐํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ๊ฒ ๋ฉ๋๋ค.
ํ์ดํ๋ผ์ธ๋ณ ์คํ ๊ด๋ฆฌ ์ ๋ต:
์๋ก์ด ์ฝ๋์๋ง ํ์ง ๊ฒ์ดํธ๋ฅผ ์ ์ฉํฉ๋๋ค. SonarQube, CodeClimate ๋๋ ์ด์ ์ ์ฌํ ๋๊ตฌ๋ฅผ ๊ตฌ์ฑํ์ฌ ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค๊ฐ ์๋ ํ ๋ฆฌํ์คํธ์ ์ถ๊ฐ๋ ์ฝ๋์๋ง ํ์ง ๊ฒ์ดํธ๋ฅผ ์ ์ฉํ๋๋ก ํฉ๋๋ค. ๊ธฐ์กด ์ฝ๋๋ฒ ์ด์ค์ ์คํ์ ์๋ก์ด ์์ ์ ์ฐจ๋จํ์ง ์์ผ๋ฉฐ, ์ ์ฝ๋์์ ๋ฐ๊ฒฌ๋ ์๋ก์ด ์ค๋ฅ๋ง ์ฐจ๋จํฉ๋๋ค.
์
# .github/workflows/analysis.yml
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
with:
args: >
-Dsonar.pullrequest.base=${{ github.base_ref }}
-Dsonar.pullrequest.branch=${{ github.head_ref }}
# New-code analysis only: existing findings don't block
์ฌ๊ฐ๋ ์๊ณ๊ฐ์ ์ค์ ํฉ๋๋ค. ์ฌ๊ฐ๋๊ฐ '์ฌ๊ฐ' ๋ฐ '๋์'์ธ ๊ฒฝ์ฐ์๋ง ํ์ดํ๋ผ์ธ์ ์คํจ ์ฒ๋ฆฌํฉ๋๋ค. '์ค๊ฐ' ๋ฐ '๋ฎ์'์ธ ๊ฒฝ์ฐ๋ ์ฐจ๋จํ์ง ์๊ณ ๊ฒฝ๊ณ ๋ก ํ์ํฉ๋๋ค.
๊ธฐ์ค ํ์ผ. Semgrep ๋ฐ Grype์ ๊ฐ์ ๋๊ตฌ๋ ํน์ ์ปค๋ฐ ์์ ์ ์กด์ฌํ๋ ๋ฐ๊ฒฌ ์ฌํญ์ ๊ธฐ๋กํ๋ ๊ธฐ์ค ํ์ผ์ ์ง์ํฉ๋๋ค. ์ ์คํ ์์๋ ๊ธฐ์ค ํ์ผ ์ดํ์ ๋ฐ์ํ ๋ฐ๊ฒฌ ์ฌํญ๋ง ๋ณด๊ณ ๋๋ฉฐ, ๊ธฐ์กด์ ์คํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ๋ณ ์ธ์คํด์ค ์ต์ ์์ด ์ต์ ๋ฉ๋๋ค.
์ธ๊ฒ ๋๋ฆฌ๋ค
# Semgrep: establish baseline, then compare
semgrep scan --baseline-commit=main --output=results.sarif src/
# Only findings introduced since main are reported
์คํ๋ฅ ์ธก์ ๋ฐ ์ถ์
์ธก์ ์์ด ์คํ์ ์ค์ด๋ ๊ฒ์ ์ถ์ธก์ ๋ถ๊ณผํฉ๋๋ค. ๋ค์ ์งํ๋ค์ ์๊ฐ์ ๋ฐ๋ผ ์ถ์ ํ์ธ์.
| ๋ฉํธ๋ฆญ | ๊ณ์ฐ ๋ฐฉ๋ฒ | ๋ชฉํ |
|---|---|---|
| ์คํ์จ | ํ์ง๋ ์์์ฑ ์ฌ๋ก ์ / ์ ์ฒด ์ง๋จ ๊ฑด์ ร 100% | ๋ณด์ ๋๊ตฌ์ ๊ฒฝ์ฐ 20% ๋ฏธ๋ง, ํ์ง ๋๊ตฌ์ ๊ฒฝ์ฐ 10% ๋ฏธ๋ง |
| ์ต์ ๋ฐ๋ | ์ฝ๋ 1,000์ค๋น ์ต์ ํ์ | ์์น ์ถ์ธ๋ ์ฒด๊ณ์ ์ธ ์ค๋ฅ์จ ๋ฌธ์ ์ด๋ฏ๋ก ๊ท์น ์กฐ์ ์ด ํ์ํฉ๋๋ค. |
| ๋ฌธ์ ๋ฐ๊ฒฌ ๋ ํด๊ฒฐ ๋น์จ | ํ์ ๋ ๊ฒ์ฌ ๊ฒฐ๊ณผ / ์ด ๊ฒ์ฌ ๊ฒฐ๊ณผ | ๋น์จ ์์น = ๋๊ตฌ ์ ๋ขฐ๋ ํฅ์ |
| ์กฐ์ฌํ ์๊ฐ | ๊ฐ๋ฐ์๊ฐ ๋ฐ๊ฒฌ ์ฌํญ๋น ์์ํ๋ ํ๊ท ์๊ฐ | ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ฐ์ํ๋ ๊ฒ์ FP ๋น์จ์ด ๊ฐ์ ๋จ์ ์๋ฏธํฉ๋๋ค. |
์ต์ ๋ฐ๋๋ฅผ ์ถ์ ํ๋ ๊ฒ์ ํนํ ์ ์ฉํฉ๋๋ค. ์ธ๋ผ์ธ ์ต์ ํ์๊ฐ ์ฝ๋๋ฒ ์ด์ค ์ฆ๊ฐ ์๋๋ณด๋ค ๋น ๋ฅด๊ฒ ์ฆ๊ฐํ๋ ๊ฒฝ์ฐ, ์ธ์คํด์ค๋ณ ์ต์ ๋ณด๋ค ๊ท์น ์กฐ์ ์ด ๋ ํจ์จ์ ์ผ ์ ์์์ ๋ํ๋ ๋๋ค.
ํต์ฌ ์์น: ๋ฌธ์ํ ์์ด ํ๋ก๋์ ํ๊ฒฝ์ผ๋ก ๋ฐฐํฌ๋๋ ์ค๋ฅ ์์ ์ ๊ธฐ์ ์ ๋ถ์ฑ์ ๋๋ค. ๋ชจ๋ ์ค๋ฅ ์์ ์๋ ๋จ์ํ ์ค๋ฅ ์์ ์ฌ์ ๋ฅผ ์ค๋ช ํ๋ ์ฃผ์์ด ํฌํจ๋์ด์ผ ํ๋ฉฐ, ๋จ์ํ ์ค๋ฅ ์์ ์ฌ์ ๋ฅผ ๋์ดํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค.
NOSONAR์ฃผ์.
๋ฐฉ๋ฒ SMART TS XL ๊ตฌ์กฐ ๋ถ์์ ํตํด ์คํ์ ์ค์ ๋๋ค.
์ ์ ๋ถ์์์ ๋ฐ์ํ๋ ๋๋ถ๋ถ์ ์คํ์ ๋๊ตฌ๊ฐ ๋ ๋์ ๋งฅ๋ฝ, ์ฆ ํธ์ถ์๊ฐ ์ด๋ฏธ ๊ฒ์ฆํ ๋ด์ฉ, ์ข ์์ฑ ๊ทธ๋ํ์ ๊ตฌ์กฐ, ํ๋ก๋์ ์ง์ ์ ์์ ์ค์ ๋ก ๋๋ฌ ๊ฐ๋ฅํ ๊ฒฝ๋ก ๋ฑ์ ์ดํดํ์ง ๋ชปํ ์ฑ ํ์ผ์ด๋ ํจ์๋ง ๋ถ์ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค.
SMART TS XL์ ์ ์ ์ฝ๋ ๋ถ์ ๊ฐ ํ์ผ์ ๊ฐ๋ณ์ ์ผ๋ก ๋ถ์ํ๋ ๋์ , ์ฝ๋๋ฒ ์ด์ค์ ์์ ํ ๊ตฌ์กฐ์ ๋ชจ๋ธ, ์ฆ ์ข ์์ฑ ๊ทธ๋ํ, ํ๋ก์์ ๊ฐ์ ์ ์ด ํ๋ฆ, ๋ชจ๋ ๊ฐ์ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ตฌ์ถํ ํ ๋ฌธ์ ๋ฅผ ํ์ํฉ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ์ ๋งฅ๋ฝ์ ํ์ผ ๋ด ํจํด ๋งค์นญ์ผ๋ก ์ธํด ๋ฐ์ํ๋ ์คํ๊ณผ ํ๋ก๊ทธ๋จ์ ์ค์ ๋๋ฌ ๊ฐ๋ฅ์ฑ ๋ฐ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ธฐ๋ฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ถํ๋ ๊ธฐ์ค์ด ๋ฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ข ์์ฑ ๋งคํ ๊ธฐ๋ฅ์ ๊ตฌ์ฑ ์์ ๊ฐ ์ํธ ์์ฉ ๋ฐฉ์์ ๋ํ ์ปจํ ์คํธ ์ ๋ณด ๋ถ์กฑ์ผ๋ก ๋ฐ์ํ๋ ์คํ์ ์ค์ฌ์ค๋๋ค. COBOL ํ๋ก๊ทธ๋จ์ ๋ณด์ ํจํด์ ํด๋น ํ๋ก๊ทธ๋จ์ ์คํ ํ๊ฒฝ์ ์ ์ดํ๋ โโJCL ์์ ์ด๋ ํธ์ถ ํ๋ก๊ทธ๋จ์ด ํธ์ถ ์ ์ ์ด๋ฏธ ๊ฒ์ฆํ ๋ด์ฉ์ ๋ํ ์ ๋ณด๋ง์ผ๋ก ์ดํดํ ์ ์๋ ๊ฒฝ์ฐ, ์ด๋ฌํ ๊ตฌ์ฑ ์์ ๊ฐ ์ปจํ ์คํธ ์ ๋ณด๊ฐ ๋ถ์์ ํฌํจ๋์ด ๋๋ฝ๋๋ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
์ํฅ ๋ถ์ ๊ธฐ๋ฅ์ ๋๊ท๋ชจ ๋ ๊ฑฐ์ ์ฝ๋๋ฒ ์ด์ค์์ ์คํ์ ๊ฑธ๋ฌ๋ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ํ์ ์ํํ๋ค๊ณ ํ์๋ ํจํด์ ์กฐ์ฌํ๋ ๋ฐ ์๊ฐ์ ํฌ์ํ๊ธฐ ์ ์ ํด๋น ํจํด์ด ์ค์ ์ด์ ํ๊ฒฝ์์ ์คํ๋ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ํ๋จํ ์ ์์ต๋๋ค. ์ด๋ก ์ ์ผ๋ก๋ ์ํํ ์ ์์ง๋ง ์ค์ ๋ก๋ ๋๋ฌํ ์ ์๋ ํจํด์ธ ์ฌ์ฉ๋์ง ์๋ ์ฝ๋์์ ๋ฐ๊ฒฌ๋ ์ฌํญ์ ๊ฐ๋ฐ์์ ํ๋จ์๋ง ์์กดํ๋ ๊ฒ์ด ์๋๋ผ ๊ตฌ์กฐ์ ๋๋ฌ ๊ฐ๋ฅ์ฑ ์ฆ๊ฑฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฐ์ ์์๊ฐ ๋ฎ์์ง๋๋ค.
์ ๋ขฐ๊ฐ ๊ฐ์ฅ ์ค์ํ ์ฒ๋์ ๋๋ค.
์คํ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ์ฑ๊ณต ์ฌ๋ถ๋ ์คํ๋ฅ ์์ฒด๋ก ์ธก์ ๋๋ ๊ฒ์ด ์๋๋ผ, ๋ถ์ ๊ฒฐ๊ณผ์ ๋ํ ๊ฐ๋ฐ์์ ์ ๋ขฐ๋๋ก ํ๊ฐ๋ฉ๋๋ค. ๋๊ตฌ๊ฐ ์ค์ ๋ฌธ์ ๋ฅผ ์ ํํ๊ฒ ํ์ํ๋ค๋ ๊ฒ์ ์๊ณ ๋ชจ๋ ๋ฐ๊ฒฌ ์ฌํญ์ ์ฒ ์ ํ ์กฐ์ฌํ๋ ํ์ ์ ์ ๋ถ์์ ํตํด ๊ฐ์น๋ฅผ ์ป๋ ํ์ ๋๋ค. ๋ฐ๋๋ก, ๊ณผ๊ฑฐ์ ๋๋ถ๋ถ์ ๋ฐ๊ฒฌ ์ฌํญ์ด ์คํ์ด์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ฌด์ํ๋ ํ์ ๋ถ์ ํ๋ก๊ทธ๋จ์ด ์ด๋ฏธ ์คํจํ ๊ฒ์ด๋ ๋ค๋ฆ์์ต๋๋ค.
๋ชฉํ ๋ฌ์ฑ์ ์ํด์๋ ์ด ๊ฐ์ด๋์ ์ค๋ช ๋ ์ฌ๋ฌ ์์๋ค์ ์กฐํฉํด์ผ ํฉ๋๋ค. ์ฆ, ๊ฐ ์คํ ์ ํ์ด ๋ฐ์ํ๋ ์ด์ ๋ฅผ ์ดํดํ๊ณ , ๋ฌธ์ํ๋ ๊ทผ๊ฑฐ๋ฅผ ๋ฐํ์ผ๋ก ํ์ธ๋ ์คํ์ ์ต์ ํ๊ณ , ์ฒด๊ณ์ ์ธ ํจํด์ด ๋ํ๋๋ ๋ถ๋ถ์์ ๊ท์น์ ์กฐ์ ํ๊ณ , ๋ ธ์ด์ฆ๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์ค์ ๋ฐ๊ฒฌ ์ฌํญ์ ๋ํด์๋ง ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๊ณ , ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ฐ์ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ์ํด ์คํ๋ฅ ์ ์ธก์ ํด์ผ ํฉ๋๋ค. ์ ์ ๋ถ์์ ํฌ์ํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์คํ์ ๊ด๋ฆฌํ๋ ์ฒด๊ณ์ ์ธ ๋ ธ๋ ฅ์ด ๋ฐ๋ก ๊ทธ ํฌ์๋ฅผ ๊ฒฐ์ค์ ๋งบ๊ฒ ํ๋ ํต์ฌ์ ๋๋ค.