소프트웨어 개발이라는 분야에 입성해서 대략 2~3년차가 되면 코드의 함수와 클래스 레벨을 넘어서서

구현하는 프로그램의 전체 프로세스와 시스템 구성을 고민하게 되는데 그때부터 주니어라고 할 수 있다.

그렇게 5~6년 일하다보면 어느새 익숙해진 개발 역량 덕분에 쓰던거 계속 쓰고, 돌려 쓰고, 다른 사람이 개발해 놓은거 갖다 쓰고

하다보면 또 새로운걸 해야 한다는 압박이 들곤 했었다.

그런데 이제는 이 분야를 지원해서 이제 막 입문하는 뉴비들이 프로그램 개발을 위한 도구들에 익숙해지는 것도 중요하지만

그것과 더불어 함께 중요시 해야 하는 사안이 생겨났으니 ...

바로 주니어를 건너띄고 시니어로의 점핑을 염두에 두고 과외를 해놓아야만 경쟁력이 생긴다.

 

과거엔 위에서 얘기한 주니어들이 참 할일이 많았다.

당연하게도 개발 역량과 더불어 비즈니스에 대한 혜안도 열리는 시점이라서 일감을 마구 쏟아넣어도 꾸역 꾸역 아웃풋을 내어 놓을 역량이 되는 것이다.

그런데 이젠 그 자리에 AI가 함께 한다.

AI가 있어서 주니어가 1/3 만 있어도 이전과 같거나 더 높은 효율성을 보인다.

게다가 이녀석이 주니어들보다 아웃풋이 점점 더 좋아지고 있다.

 

모든 업계에 새로운 트랜드의 바람이 너무나 거세다.

오늘 ChatGPT와 Gemini에게 코드 작성을 의뢰하여 받은 결과물에 소름이 돋는 느낌이 들어서 이렇게 감회를 적었다.

다음은 그 내용이다.

 

Order

다음과 같은 로그의 내용에서 rp번호를 추출해야 하는데 대괄호 안에 rp 라는 키워드를 삽입한 형태가 대부분이지만 로그에 숫자만 5자리나 6자리를 입력한 형태도 있어, 이러한 로그에서 rp 라는 키워드로 명확하게 지정한 숫자의 나열은 당연히 rp번호이고 rp라는 키워드가 없는 로그에서 숫자가 5자리 또는 6자리는 rp번호로 간주해서 rp번호들을 추출하는 java code 를 작성해줘

2a8b000000 Metainfo Commit 2025-0...57.03
d3ec000000 Help Folder Commit 2025-05...30.14
d4b9000000 Metainfo Commit 2025-05...8:23.90
a8b0000000 [RP 101453] [접근성] TAB키...
1501000000 [RP 101453] [접근성] TAB키...
7f90000000 RP 101409 Edge에서 사이즈가 깨지...
8e3000000 RP 101409 ...에도 동일한 로직 반영
99c1000000 [RP : 102742, 102677] [202505패치] iPad에서 ondblclick 이벤트 ...
0c43000000 Merge branch 'RELE....0.700' of https://tfs2.to...00 into RELE....0.700
441e000000 Envi...ration meta initonly 수정
ca9d000000 Help Folder Commit 2025-0...03:19.64
d153000000 RP 101409 Edge브라우저에서 확대축소 오동작...정
2f23000000 [RP 101854] [접근성] 에디트 값 수정 후...용 안됨. - 원복
a00000000 RP 102223 추가 수정 (And... 문제)
7298000000 RP 101409 NRE 오류 수정
b34e000000 RP 101409 zoom이 적용된 화면에서 ... 현상 추가 수정
c824000000 RP 102598 Comb...) 수정
44e000000 environ...ion 값 툴에서만 설정되도록 변경

Result (ChatGPT)

아래는 설명하신 조건에 맞춰 **RP번호(5자리 또는 6자리 숫자)**를 추출하는 Java 코드입니다.

✅ 조건 요약
[RP ...], RP ..., RP: ... 등 RP 키워드가 있는 경우, 그 뒤에 나오는 5~6자리 숫자를 추출.

RP 키워드가 없는 경우에도 5자리 또는 6자리 숫자가 등장하면 RP번호로 간주해서 추출.

중복 RP 번호는 제거.

✅ Java 코드
java
복사
편집
import java.util.*;
import java.util.regex.*;
import java.nio.file.*;
import java.io.*;

public class RpNumberExtractor {

    public static void main(String[] args) throws IOException {
        String logText = Files.readString(Paths.get("log.txt")); // log.txt에 로그를 저장해두었다고 가정

        Set<String> rpNumbers = new HashSet<>();

        // 1. RP 키워드가 있는 경우 추출: [RP 123456], RP 123456, [RP: 123456] 등
        Pattern rpPattern = Pattern.compile("(?i)\\bRP\\s*[:\\[\\(]?\\s*(\\d{5,6})");
        Matcher rpMatcher = rpPattern.matcher(logText);
        while (rpMatcher.find()) {
            rpNumbers.add(rpMatcher.group(1));
        }

        // 2. RP 키워드가 없는 5~6자리 숫자 추출
        Pattern numberPattern = Pattern.compile("\\b(\\d{5,6})\\b");
        Matcher numberMatcher = numberPattern.matcher(logText);
        while (numberMatcher.find()) {
            String number = numberMatcher.group(1);
            // 이미 추출된 RP번호가 아니면 추가
            if (!rpNumbers.contains(number)) {
                // 키워드 없이 등장한 경우인지 체크
                int index = numberMatcher.start();
                String context = logText.substring(Math.max(0, index - 20), Math.min(logText.length(), index + 20));
                if (!context.matches("(?i).*RP\\s*[:\\[\\(]?\\s*" + number + ".*")) {
                    rpNumbers.add(number);
                }
            }
        }

        // 출력
        System.out.println("추출된 RP 번호:");
        rpNumbers.stream().sorted().forEach(System.out::println);
    }
}
✅ 사용 방법
로그 텍스트를 log.txt에 저장합니다.

위 코드를 실행하면 로그에서 추출한 RP번호들을 중복 없이 출력합니다.

🔍 예시 출력
bash
복사
편집
101409
101453
101792
101854
102223
102598
102623
102668
102677
102713
102714
102742
필요하다면 파일 대신 문자열 입력으로 처리하거나 결과를 파일에 저장하는 기능도 추가 가능합니다.

 

Result (Gemini)


 

로그에서 RP 번호 추출 Java 코드

제공해주신 로그 내용에서 RP 번호를 추출하는 Java 코드를 작성해 드리겠습니다. 다음과 같은 규칙을 적용하여 번호를 추출합니다:

  1. RP 키워드가 명시된 경우: RP (대소문자 구분 없음) 키워드 뒤에 오는 숫자(5자리 또는 6자리)를 우선적으로 추출합니다. [RP 123456], RP 12345, [RP : 123456] 등 다양한 형태를 커버합니다.
  2. RP 키워드가 없는 경우: 로그 라인에서 단독으로 존재하는 5자리 또는 6자리의 숫자를 RP 번호로 간주하여 추출합니다.

이를 위해 **정규 표현식(Regular Expression)**을 강력하게 활용하겠습니다.


Java 코드 예제

Java
 
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RpNumberExtractor {

    public static void main(String[] args) {
        // 예시 로그 데이터 (제공해주신 로그 내용을 String 배열로 만듦)
        String[] logs = {
            "2a8b000000 Metainfo Commit 2025-0...57.03",
            "d3ec000000 Help Folder Commit 2025-05...30.14",
            "d4b9000000 Metainfo Commit 2025-05...8:23.90",
            "a8b0000000 [RP 101453] [접근성] TAB키...",
            "1501000000 [RP 101453] [접근성] TAB키...",
            "7f90000000 RP 101409 Edge에서 사이즈가 깨지...",
            "8e3000000 RP 101409 ...에도 동일한 로직 반영",
            "99c1000000 [RP : 102742, 102677] [202505패치] iPad에서 ondblclick 이벤트 ...",
            "0c43000000 Merge branch 'RELE....0.700' of https://tfs2.to...00 into RELE....0.700",
            "441e000000 Envi...ration meta initonly 수정",
            "ca9d000000 Help Folder Commit 2025-0...03:19.64",
            "d153000000 RP 101409 Edge브라우저에서 확대축소 오동작...정",
            "2f23000000 [RP 101854] [접근성] 에디트 값 수정 후...용 안됨. - 원복",
            "a00000000 RP 102223 추가 수정 (And... 문제)",
            "7298000000 RP 101409 NRE 오류 수정",
            "b34e000000 RP 101409 zoom이 적용된 화면에서 ... 현상 추가 수정",
            "c824000000 RP 102598 Comb...) 수정",
            "44e000000 environ...ion 값 툴에서만 설정되도록 변경",
            "Some commit message with only 12345", // 5자리 숫자 예시
            "Another commit with 987654 in the middle", // 6자리 숫자 예시
            "This commit has no rp numbers",
            "It has 123 but not 5 or 6 digits",
            "And a long number 1234567890" // 5,6자리 아님
        };

        System.out.println("--- RP 번호 추출 결과 ---");
        for (String logLine : logs) {
            List<String> rpNumbers = extractRpNumbers(logLine);
            System.out.println("로그: \"" + logLine + "\" -> RP 번호: " + (rpNumbers.isEmpty() ? "없음" : rpNumbers));
        }
    }

    /**
     * 로그 문자열에서 RP 번호를 추출합니다.
     * RP 키워드 뒤에 오는 숫자(5-6자리)를 우선적으로 찾고,
     * 그렇지 않으면 단독으로 존재하는 5-6자리 숫자를 찾습니다.
     *
     * @param logLine RP 번호를 추출할 로그 문자열
     * @return 추출된 RP 번호들의 리스트 (발견되지 않으면 빈 리스트)
     */
    public static List<String> extractRpNumbers(String logLine) {
        List<String> rpNumbers = new ArrayList<>();

        // 1. "RP" 키워드가 명시된 경우를 위한 정규 표현식
        // RP 뒤에 올 수 있는 공백, 콜론, 대괄호 등을 유연하게 처리하고 5 또는 6자리의 숫자를 찾습니다.
        // 그룹 1: 실제 RP 번호 숫자
        Pattern rpPattern = Pattern.compile(
            "[Rr][Pp]\\s*[:\\s]*\\[?(\\d{5,6})\\]?|\\b[Rr][Pp]\\s*[:\\s]*(\\d{5,6})",
            Pattern.CASE_INSENSITIVE // 대소문자 구분 없이 "rp"를 찾도록 설정
        );
        Matcher rpMatcher = rpPattern.matcher(logLine);

        while (rpMatcher.find()) {
            // 첫 번째 그룹 (대괄호 안에 RP 숫자) 또는 두 번째 그룹 (일반 RP 숫자)에서 값을 가져옴
            String rpNum = rpMatcher.group(1);
            if (rpNum == null) {
                rpNum = rpMatcher.group(2);
            }
            if (rpNum != null && !rpNumbers.contains(rpNum)) { // 중복 방지
                rpNumbers.add(rpNum);
            }
        }

        // 2. "RP" 키워드가 없는 경우를 위한 정규 표현식 (5자리 또는 6자리 숫자만)
        // 단어가 시작/끝나는 경계(\\b)에 있으면서, 앞에 "RP" 같은 문자가 없는 경우를 찾습니다.
        // 이 패턴은 rpPattern에서 찾지 못한 경우에만 적용되어야 합니다.
        // 즉, rpNumbers가 이미 채워져 있다면 이 패턴은 건너뜁니다.
        if (rpNumbers.isEmpty()) {
            Pattern standaloneNumberPattern = Pattern.compile(
                "\\b(?<![Rr][Pp]\\s*[:\\s]*)(?<!\\d)(\\d{5,6})(?!\\d)\\b"
            );
            Matcher standaloneNumberMatcher = standaloneNumberPattern.matcher(logLine);

            while (standaloneNumberMatcher.find()) {
                String num = standaloneNumberMatcher.group(1);
                // "RP" 키워드 뒤에 오는 숫자가 아닌 경우만 추가 (Negative Lookbehind)
                // 이미 rpPattern에서 찾은 숫자가 아닌 경우에만 추가
                if (!rpNumbers.contains(num)) {
                    rpNumbers.add(num);
                }
            }
        }
        
        return rpNumbers;
    }
}

코드 설명:

  1. extractRpNumbers(String logLine) 메서드:
    • 주어진 로그 라인에서 RP 번호를 추출하는 핵심 메서드입니다.
    • rpNumbers라는 List<String>을 반환하여 추출된 모든 RP 번호를 담습니다.
  2. 첫 번째 정규 표현식 (rpPattern):
    • "[Rr][Pp]\\s*[:\\s]*\\[?(\\d{5,6})\\]?|\\b[Rr][Pp]\\s*[:\\s]*(\\d{5,6})"
    • 이 패턴은 RP 키워드가 명시적으로 포함된 경우를 처리합니다.
    • [Rr][Pp]: 대소문자 구분 없이 "Rp" 또는 "RP"를 찾습니다.
    • \\s*: 0개 이상의 공백 문자를 의미합니다.
    • [:\\s]*: 0개 이상의 콜론(:) 또는 공백 문자를 의미합니다. ([RP : 12345])
    • \\[?: 0개 또는 1개의 여는 대괄호([)를 의미합니다. (옵션)
    • (\\d{5,6}): 5자리 또는 6자리의 숫자를 찾고, 이를 캡처 그룹 1로 만듭니다. 이 부분이 우리가 추출하려는 RP 번호입니다.
    • \\]?: 0개 또는 1개의 닫는 대괄호(])를 의미합니다. (옵션)
    • |: OR 연산자입니다.
    • \\b[Rr][Pp]\\s*[:\\s]*(\\d{5,6}): 대괄호가 없는 "RP 123456" 형태를 처리합니다. (\\b는 단어 경계)
    • Pattern.CASE_INSENSITIVE: 대소문자를 구분하지 않고 RP를 찾도록 설정합니다.
    • rpMatcher.find()를 통해 로그 라인에서 모든 일치하는 부분을 찾고, rpMatcher.group(1) 또는 rpMatcher.group(2)를 사용하여 실제 RP 번호(숫자 부분)를 추출합니다.
  3. 두 번째 정규 표현식 (standaloneNumberPattern):
    • "\\b(?<![Rr][Pp]\\s*[:\\s]*)(?<!\\d)(\\d{5,6})(?!\\d)\\b"
    • 이 패턴은 RP 키워드가 명시되지 않은 경우에 단독으로 존재하는 5자리 또는 6자리 숫자를 찾습니다.
    • 이 패턴은 rpNumbers 리스트가 비어 있을 때만 실행됩니다. 즉, RP 키워드를 찾지 못했을 때만 순수 숫자 패턴을 검사합니다.
    • \\b: 단어 경계를 나타냅니다. 숫자가 다른 문자에 붙어있는 경우를 방지합니다 (예: long12345에서 12345를 추출하지 않음).
    • (?<![Rr][Pp]\\s*[:\\s]*): 부정형 후방 탐색 (Negative Lookbehind) 입니다. 이 패턴이 일치하는 숫자 바로 앞에 "RP", "rp", "RP :" 등 RP 관련 키워드가 없는 경우에만 일치시킵니다.
    • (?<!\\d): 숫자 바로 앞에 다른 숫자가 없는 경우에만 일치시킵니다. (예: 1234567에서 567을 추출하지 않음)
    • (\\d{5,6}): 5자리 또는 6자리의 숫자를 찾고, 이를 캡처 그룹 1로 만듭니다.
    • ?!\\d: 부정형 전방 탐색 (Negative Lookahead) 입니다. 숫자 바로 뒤에 다른 숫자가 없는 경우에만 일치시킵니다. (예: 1234567에서 123456을 추출하지 않음)
    • \\b: 단어 경계를 다시 한 번 확인합니다.
  4. 중복 방지:
    • !rpNumbers.contains(rpNum)를 사용하여 이미 추출된 RP 번호가 리스트에 추가되는 것을 방지합니다.

이 코드는 제공해주신 로그 샘플에서 모든 RP 번호를 정확하게 추출하며, 불필요한 숫자들은 RP 번호로 간주하지 않습니다.


 

응답해준 프로그램이 맞고 틀리고를 떠나서

질문한지 단 5초만에 결과를 내놓는다...

리더나 매니저급 개발  시니어들이 주니어들을 잔뜩 데리고 있을 필요가 없어졌다.

개발 시니어들도 이제 더이상 개발 레벨에서는 의미가 없는 직종이 되었고 투자자 또는 경영주와의 파트너 쉽이 너무나 중요해졌다. 

+ Recent posts