https://leetcode.com/problems/count-prefix-and-suffix-pairs-i/

 

이번 문제도 문자열을 비교하는 문제이다.

접두사 및 접미사의 쌍 계산 이라고 번역이 되는데 문제를 보자.

당신에게 0으로 시작하는 문자열 배열 words가 주어졌습니다.
두 문자열 str1과 str2를 인수로 받는 isPrefixAndSuffix라는 부울 함수를 정의해봅시다:

isPrefixAndSuffix(str1, str2) 함수는 str1이 str2의 접두사이면서 동시에 접미사인 경우 true를 반환하고,
그렇지 않은 경우 false를 반환합니다.

예를 들어, isPrefixAndSuffix("aba", "ababa")는 aba가 ababa의 접두사이자 접미사이기 때문에 true를 반환하지만,
isPrefixAndSuffix("abc", "abcd")는 false를 반환합니다.

이제 주어진 words 배열에서 i < j를 만족하는 인덱스 쌍 (i, j)의 수를 반환하세요. 이때, isPrefixAndSuffix(words[i], words[j])가 true인 경우만 포함됩니다.

 

그리고 예제를 보면

예제 1.
Input: words = ["a","aba","ababa","aa"]
Output: 4
Explanation: In this example, the counted index pairs are:
i = 0 and j = 1 because isPrefixAndSuffix("a", "aba") is true.
i = 0 and j = 2 because isPrefixAndSuffix("a", "ababa") is true.
i = 0 and j = 3 because isPrefixAndSuffix("a", "aa") is true.
i = 1 and j = 2 because isPrefixAndSuffix("aba", "ababa") is true.
Therefore, the answer is 4.
예제 2.
Input: words = ["pa","papa","ma","mama"]
Output: 2
Explanation: In this example, the counted index pairs are:
i = 0 and j = 1 because isPrefixAndSuffix("pa", "papa") is true.
i = 2 and j = 3 because isPrefixAndSuffix("ma", "mama") is true.
Therefore, the answer is 2.

 

딱 이 예제까지만 봤을때는 아 이 문제는 0번째 배열의 값부터 시작해서 마지막 값까지 비교해서

같은 문자열이 앞 뒤에 존재하는지 확인하는 문제구나! 라고 생각했다

그래서 그대로 코드를 짜 봤는데...

class Solution {
    public int countPrefixSuffixPairs(String[] words) {
        int count = 0;

        for(int i = 0; i < words.length; i++){
            for(int j = 0; j < words.length; j++){
                // 동일한 문자인지 체크
                if(!words[i].equals(words[j])){
                	// 접두사와 접미사가 동일한지 비교
                    if(words[i].startsWith(words[j]) && words[i].endsWith(words[j])){
                        count++;
                    }
                }
            }
        }
        return count;
    }
}

여기서 포인트는 startsWith() 함수와 endsWith() 함수다.

각각 문자열 앞자리와 뒷자리 부분이 동일한지 비교하여 boolean 값으로 반환하는 함수이다.

 

그래서 결과는 1,2 예제는 통과 했는데 마지막 예제를 통과하지 못했다.

예제 3.
Input: words = ["abab","ab"]
Output: 0
Explanation:
이 예에서 유일한 유효한 인덱스 쌍은 i = 0 및 j = 1이고
isPrefixAndSuffix("abab", "ab")는 false입니다. 그러므로 답은 0이다.

 

내 코드대로 계산한다면 "abab"에는 앞 뒤로 "ab", "ab"가 들어가기에 ture, 즉 1을 반환했는데 답은 false, 0 이였다.

이것때문에 어디서부터 잘못된건지 내가 뭘 잘못 이해하고 있는지 고민하다가 결국 문제 하단에 있는 토목록에서 힌트를 얻었다.

 

바로 문제에 하단에 나와있는 i < j 를 확인하란 것이였다.

그말은 즉슨 i 번 부터 j까지 확인하라, i의 값이 j에 접두사 및 접미사가 되느냐? 를 물어보는 문제였다.

고로 "abab" 가 i 이고, "ab"는 j 이기 때문에 "abab"가 "ab"의 접두사나 접미사가 될순 없기 때문에 틀린것이였다.

 

그래서 이를 참고해 코드를 수정했다.

class Solution {
    public int countPrefixSuffixPairs(String[] words) {
        int count = 0;

        for(int i = 0; i < words.length; i++){
            for(int j = i+1; j < words.length; j++){
                if(words[j].startsWith(words[i]) && words[j].endsWith(words[i])){
                    count++;
                }
            }
        }
        return count;
    }
}

 

더 간결해졌고 정답도 맞췄다.

 

항상 문제를 잘 읽고 먼저 이해한 다음에 코드를 작성해보자.

또 필요한 함수가 있는지 한번 더 체크해보고 작성해야겠다.

https://leetcode.com/problems/string-matching-in-an-array/description/

 

이 문제는 Input으로 여러 개의 문자열로 이루어진 리스트 타입 words를 입력받는데

예제는 아래와 같다.

예제 1.
Input: words = ["mass","as","hero","superhero"]
Output: ["as","hero"]
해설 : "as"가 "mass"에 포함되고 "hero"가 "superhero"에 속하기 때문에 답은 ["as","hero"]가 된다
예제 2.
Input: words = ["leetcode","et","code"]
Output: ["et","code"]
해설: "et", "code" 는 "leetcode"에 속한다.
예제 3.
Input: words = ["blue","green","bu"]
Output: []
해설 : 서로 포함되는 글자가 없기 때문에 답이 없다. 

 

이 문제를 보고 저번에 풀었던 RansomNote 문제에서 내가 처음에 작성했던 코드가 생각났다.

이번에는 반드시 맞을 것이라 생각하고 열심히 코드를 짠 결과

class Solution {
    public List<String> stringMatching(String[] words){
    	// 중복 제거용 set
        Set<String> set = new HashSet<>();
        int len = 0;
		
        // words 문자열을 하나씩 꺼냄
        for(String temp : words){
            len = temp.length();
            // 비교용 문자열을 꺼냄
            for(String temp2 : words){
            	// 만약 문자열이 같지않고, 문자열의 길이가 비교용 문자열보다 길다면
                if(!temp.equals(temp2) && len < temp2.length()){
                    for(int i = 0; i < temp2.length(); i++){
                    	// 문자열의 길이가 초과되지 않을때 까지 잘라서 비교한다.
                        if(len+i <= temp2.length()){
                            if(temp2.substring(i,len+i).equals(temp)){
                                set.add(temp);
                            }
                        }
                    }
                }
            }
        }
        // 결과를 다시 List<String> 타입으로 변환한다.
        List<String> result = new ArrayList<>(set);

        return result;
    }
}

 

이렇게 지저분한 코드가 완성됐다.

 

제출결과 맞긴 했는데 메모리를 45.1MB나 먹고 시간도 12ms나 걸렸다.

평균적으로 꼴찌였기에 새롭게 다시 짜기로 했다.

 

그러다가 Java에 문자열이 포함되어 있는 여부를 확인할 수 있는 함수인 .contains( )가 있다는 것을 알았고,

그 함수를 사용해서 다시 작성하였다.

class Solution {
    public List<String> stringMatching(String[] words){
    	// 중복 제거용 set
        Set<String> set = new HashSet<>();
        
        for(int i = 0; i < words.length;i++){
            for(int j = i+1; j < words.length; j++){
            	// 해당 문자열에 포함된다면...
                if(words[i].contains(words[j])){
                    set.add(words[j]);
                }else if(words[j].contains(words[i])){
                    set.add(words[i]);
                }
            }
        }
		// List<String>타입으로 변환
        List<String> result = new ArrayList<>(set);

        return result;
    }
}

여기서 if문이 있는데 한 번 더 비교한 이유는 그냥 if(words [i]. contains(words [j])) 만 작성하면

관련된 모든 값이 다 나와서 한 번 더 반대로 검증해야 했다.

 

코드는 여전히 지저분하지만 결과는 확실히 좋았다.

실행 시간은 5ms가 되었고 메모리는 42.6MB가 되었다.

 

그래도 아직 평균에 못 미치는데 그건 다음에 다시 봐야겠다.

'코테 > LeetCode' 카테고리의 다른 글

916. Word Subsets  (0) 2025.01.11
2185. Counting Words With a Given Prefix  (0) 2025.01.09
3042. Count Prefix and Suffix Pairs I  (0) 2025.01.08
383. Ransom Note  (1) 2025.01.06
876. Middle of The Linked List | 연결리스트의 중간  (1) 2025.01.06

https://leetcode.com/problems/ransom-note/description/

 

해당 문제는 String 타입의 ransomNote와 magazine가 주어지는데

여기서 ransomNote 에 포함된 알파벳들이  magazine에도 동일한 개수가 들어가있는지 확인하고 Boolean값을 반환하는 문제다.

 

예제1.

Input: ransomNote = "a", magazine = "b"
Output: false

이경우 'a'가 magazine에 포함되어 있지 않기때문에 false를 반환한다.

예제 2.

Input: ransomNote = "aa", magazine = "ab"
Output: false

여기서도 ransomNote에 'a'가 2개 포함되어있지만 magazine에는 'a'가 1개밖에 없기 때문에 false를 반환한다.

 

예제 3.

Input: ransomNote = "aa", magazine = "aab"
Output: true

이 경우에는 'a'값 두개가 magazine에 포함되어 있기 때문에 true를 반환한다.

 

나는 처음에 이 문제를 단순히 ransomNote의 값이 magazine에 포함되는 것인줄 알고 이렇게 코드를 작성했었다.

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int s = ransomNote.length();

        for(int i = 0; i < magazine.length(); i++){
            if(s+i <= magazine.length()){
                if(magazine.substring(i,s+i).equals(ransomNote)){
                    return true;
                }
            }
        }
        return false;
    }
}

 

해당 코드는 ransomNote의 길이만큼 magazine을 잘라서 비교하는 연산을 한다.

기본적으로 표시된 테스트케이스 3개는 모두 통과했기에 이 답이 맞는줄 알았으나

예제 4.

Input: ransomNote = "aab", magazine = "baa"
Output: false
Expected: true

이 예제에서 틀리고 말았다.

왜 틀린거지 false가 맞는거 아닌가 했는데, 애초에 문제 자체를 잘못 이해하고 있었다.

 

저 예제에서도 문자열의 순서가 중요한게 아니라

ransomNote에 'a'가 2개 'b'가 1개 있고 magazine 에도 같은 양의 알파벳이 있는가를 비교하는 문제였다.

 

그래서 코드를 수정했고 정답을 맞췄다.

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
    	// Map 생성
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
		
        // for-each문을 이용하여 magazine의 값을 순서대로 꺼냄
        for(char temp : magazine.toCharArray()){
        	// Map에 [문자,개수] 쌍으로 삽입
            map.put(temp,map.getOrDefault(temp,0)+1);
        }
        // 다시한번 for-each문을 통해 ransomNote값을 순서대로 꺼냄
        for(char temp2 : ransomNote.toCharArray()){
        	// 만약에 magazine에 해당 문자가 없다면 false
            if (!map.containsKey(temp2)){
                return false;
            }
            // 존재한다면 -1 시키고 0이 되면 Map에서 제거
            int count = map.get(temp2)-1;
            if (count > 0){
                map.put(temp2,count);
            } else{
                map.remove(temp2);
            }
        }

        return true;
    }     
}

 

Map을 이용해 각 문자의 개수를 세고 하나씩 비교하는 방식을 사용하였다.

이 방법이 가장 효과적인 방법은 아닌것 같은데 더 좋은 방법을 찾아봐야겠다.

https://leetcode.com/problems/middle-of-the-linked-list/description/

 

이 문제는 연결리스트에서 중간값을 찾아 중간부터 출력하는 문제다.

 

예시1.

Input : head = [1,2,3,4,5]

Output : [3,4,5]

 

중간값이 3이기 때문에 [3,4,5]가 출력되어야 한다.

 

예시2.

Input: head = [1,2,3,4,5,6]
Output: [4,5,6]

 

중간값이 4이기 때문에 [4,5,6]이 출력되어야 한다.

 

이 문제에서는 주석으로 ListNode의 구조가 주어지는데 이를 보고 출력을 결정하면 된다.

 

이 문제를 해결하는 핵심은 중간 노드를 어떻게 찾느냐인데,

두개의 노드를 만들어서 계산하면 된다.

fnode : 중간 지점을 반환할 노드

lnode : 2개씩 이동하며 연결 리스트를 2분할 하는 노드

 

즉, lnode가 2개씩 노드를 건너뛰어서 연결 리스트를 반으로 줄이고, fnode는 1개씩 이동하여 중간 지점을 정한다.

아래는 그것을 구현한 코드이다.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode fnode = head; // 시작 노드
        ListNode lnode = head; // 마지막 노드
		
        // 무한 반복
        while(true){
            try {
                lnode = lnode.next.next; // 마지막 노드는 2개씩 움직임
            }
            catch (NullPointerException e){ // 만약에 끝까지 도달했다면 탈출
                break;
            }
            fnode = fnode.next; // 시작 노드를 옮김
        }

        return fnode;
    }
}

 

여기서 아쉬운점은 내가 lnode가 끝에 다다랐을때 null을 반환하는것을 어떻게 처리할지 고민하다가

그냥 try-catch문으로 체크했는데 일단 작동은 잘 된다...;;

'코테 > LeetCode' 카테고리의 다른 글

916. Word Subsets  (0) 2025.01.11
2185. Counting Words With a Given Prefix  (0) 2025.01.09
3042. Count Prefix and Suffix Pairs I  (0) 2025.01.08
1408. String Matching in an Array | 배열의 문자열 일치  (1) 2025.01.07
383. Ransom Note  (1) 2025.01.06

이번 주 요약

1. 첫번째 팀 프로젝트 발표

30일과 31일일에는 팀프로젝트 마무리 준비 및 발표를 하였다.

팀 명은 DBDB DEEP, 프로젝트 명은 ShowTimeNow이다.

 

이번 팀 프로젝트는 ER-다이어그램을 그려보고 DB를 설계하는데 중점을 두었다

그래서 우리 팀은 영화관을 주제로 삼았다.

 

팀원 중 영화관에서 근무했던 사람이 두 명 있었기에 그 경험과 불편했던 사항을 조합해서 세부적인 내용을 작성해나갔다. 

요즘 영화관에서는 독점 상영을 하는 영화가 늘었기에 이에 초점을 두고 대형 영화 3사의 정보를 취합해 보여주기로 하였다.

그 결과 영화관 통합 예매 시스템을 구축하자는 결론이 나왔고,

그에 맞춰 요구사항 명세서를 작성하고, ERD 설계를 하기 시작하였다.

 

이 과정에서 많은 수정사항과 충돌이 있었지만 서로 상대를 설득하여 잘 풀어나갔다.

덕분에 다른 팀들보다 조금 더 빠르게 일이 진행될 수 있었고 프로젝트는 성공적으로 진행되는 듯 하였다.

 

결론적으로, 프로젝트는 잘 마무리가 되었고 지금 다시 회고해보면 좋았던 점과 개선해야할 점이 보였다.

 

좋았던 점

1. 우리 팀원 중 한분께서 DB를 AWS에 올려 모두 하나의 DB에서 작업할 수 있게 설정해주셨다.

   - 이는 매우 중요한 부분으로 모두 같은 DB를 공유함으로써 팀원 모두가 동일한 DB로 작업할 수 있었다.

2. DB의 모든 동작을 프로시저로 만듦으로써 SQL문의 관리와 시연이 매우 편리했다.

  - 또한 이 프로시저를 요구사항 명세서에 같이 정리함으로써 매우 쉽게 추가된 기능을 확인할 수 있었다.

개선해야할 점

1. 확실한 리더가 없었다.

  - 프로젝트의 가장 중요한 리더가 딱히 없었기에 의견이 충돌나거나 병합해야할 때 어려움을 겪었다.

    실제 리더와 실질적 리더가 달랐고, 이로인해 혼선이 생기기도 했다.

2. 주제에 대해 실제 가능한 프로젝트인가 생각해봐야 했고 확실한 차별점이 있어야했다.

  - 영화관을 통합한다고 했으면 영화관 통합만 되야하는데 매점이라는 부가기능을 넣음으로써 매점이 영화관에 종속되어버렸다.

    실제로는 영화관마다 매점이 다를것이고 영화 / 매점은 서로 완전히 다른 객체이지만 이를 한데 묶은것은 실수였다고 생각한다.

3. 역활이 올바르게 분배되지 않고 치우친 부분이 있었다.

  - 역활을 나눌 때 ERD를 보고 테이블별로 역활을 설정했는데 내 경우 예약과 좌석 테이블을 맡았기에 상대적으로 할일이 적었다.

    하지만 다른 조원들은 그보다 더 많은 작업이 필요했고, 절대적인 작업량에서 차이가 났기에 나는 맡은 부분을 끝내고

    다른 팀원을 도와서 작업을 진행하였다.

4. ERD가 잘 작성되었는지 확실하지 않다.

  - 우리 팀 모두 ERD 테이블에 대해서 그렇게 잘 아는편이 아니라서 많이 알아보면서 작성하긴 했지만

    최종 결과물에도 분명 문제는 있다. 특히, 관계설정에서 많이 애를 먹었다.

    나 또한 이게 잘못되었음을 인지하였지만 조원들을 설득할 만큼 알고있지 않았기에 어찌할 수 가 없었다.

5. 발표 시에 PPT를 준비하지 않고 깃허브에 올라간 README를 보고 발표했다.

  - 다른 팀들이 발표하는것을 보고 많이 주눅들었었다. 우리팀이 그리 못한건 아니라고 생각하는데 적어도 발표를 한다면

    PPT라도 하나 만들어서 그걸로 발표하는게 맞았던것 같다. 

6. 기능 명세서에 완료/보류/폐기 를 같이 정리하면 좋을 것 같다.

  - 다른 팀원들의 발표를 보니 그런식으로 기능 명세서에 생각나는 기능을 모두 적고 상태를 따로 표시하여 정리하였다.

    이렇게 하면 다음에 기능을 수정할 때 많은 도움이 될 것 같다.

 

그리고 발표가 끝나고 강사님이 피드백을 해주셨고 정리해보자면 다음과 같다.

- 이러한 비슷한 기능을 가진 시스템이 존재하지 않는가?

- 멤버십 할인도 추가하면 좋을 것 같고 할인에 대해서 좀 더 고민해보면 좋을 것 같다.

- DB는 직접 다 등록했겠지만 실무에서는 회사 등 에서 지원하는 API를 통해 DB를 삽입할것이다.

- 프로시저를 사용한것은 좋은 선택이였다.

 

이번 프로젝트는 정말 많은 것을 배웠고 다음 프로젝트때는 이보다 더 확실하게 준비하고 싶다.

위의 개선사항들을 모두 종합하여 아쉬움이 남지 않는 프로젝트를 진행하고 싶다.

깃허브
 

GitHub - beyond-sw-camp/be13-1st-DBDBDEEP-ShowTimeNow

Contribute to beyond-sw-camp/be13-1st-DBDBDEEP-ShowTimeNow development by creating an account on GitHub.

github.com

2. JAVA 기초 학습

JAVA 기초에 대해서는 거의 다 알기때문에 특별할건 없지만,

인텔리제이 얼티밋을 6개월동안 제공해주셔서 사용해보았는데 생각보다 엄청나게 편리했다.

 

이를 활용해서 더 확실하게 JAVA의 기초를 쌓아가야겠다.

 

마무리 하며...

어느덧 24년이 끝나고 25년이 되었다.

24년은 정말 다사다난한 해 였고, 많이 배우기도 했다.

25년에는 내 기반을 더 열심히 갈고닦아서 꼭 취업하고 싶다.

 

ps.
이번에 교과목 평가도 봤는데 1등이랑 2문제 차이가 났다.
기초적인걸 틀리다니 아직 더 공부해야겠다.

어느덧 3주 차에 접어들었다.

이번주는 MariaDB를 리눅스에서 사용하는 방법과 Git의 사용법, 소프트웨어 공학에 대한 기초를 배웠다.

그중 Git 사용법에 대해 배웠던 것에 대해 이야기해보려고 한다.

 

Git이란

소스코드를 효과적으로 관리하기 위해 개발된 분산형 버전 관리 시스템이다.

나도 이전에 몇 번 Git을 사용하기도 했고 이를 활용해서 버전 관리를 하고 백업도 하는 식으로 유용하게 썼었다.

이전에 알고 있던 건 단순히 Git에 커밋하거나 복사하는 방법만 알고 있었다.

 

무엇을 배웠는가?

이번 시간에는 SourceTree를 활용하여 Git의 세부 기능들에 대해서 배우게 되었다.

Git에는 단순히 소스코드를 올리는 커밋뿐만 아니라 올라간 소스코드에 대한 버전관리를 할 수 있는 기능이 있다.

여기서 중요한 기능은 독립적인 저장소를 생성하는 브렌치라고 생각한다.

이를 활용하여 여러 개발자들이 동시에 다양한 분기를 나눌수 있는 기능이 있다.

 

여기서 Git frow를  사용해서 브렌치를 마스터, 개발, 기능,  릴리즈, 핫픽스 등의 브렌치로 나눠서 버전을 관리할 수 있는데

충돌이나 커밋 초기화, 폐기, 합치기 등등 관리 방법을 배웠다.

이를 활용하면 좀 더 체계적인 프로젝트 관리를 할 수 있다.

 

어떻게 활용할 수 있을까

이번에 배운 Git의 세부기능들을 활용해서 현재 관리 중인 꿈찾사 프로젝트나 앞으로 진행할 프로젝트에 적용시켜서

버전 관리를 더 효율적으로 할 수 있을 것 같다.

특히 꿈찾사 프로젝트의 경우에는 1인 개발이긴 하지만 실제 배포중이므로 개발중인 브렌치와 메인 브렌치를 나누면 더  효율적으로 관리할 수 있을것이라 기대된다.

 

그 외

이 외에도 소프트웨어 공학 기초는 이론적인 부분에 대해서만 배웠는데

이건 사실 이론보다는 실제로 이런 상황을 겪어보는게 가장 중요하다고 생각한다.

그래서 이미 정처기나 학부생때 배우기도 했어서 머리에 잘 들어오진 않았다. 

 

ps.
아무튼 이렇게 또 한주가 마무리 되었고 이제 다음주면 2024년도 끝이난다.
이 번 한해도 잘 마무리 하고 2025년도 이보다 더 유익하고 즐거운 시간이 되었으면 좋겠다.

이번에 팀프로젝트  하면서 SQL 데이터를 다량으로 삽입해야할 때가 있었는데

이걸 만들어서 간단하게 해결했다.

 

CREATE, INSERT, UPDATE 문 생성가능

범위는 999999 행/열 까지 삽입가능

SQL쿼리 생성기.xlsm
0.04MB

 

회고를 하기 앞서...

아직 부족한 회고록이였지만 우수 회고자 선정  감사드립니다.

앞으로 더욱 좋은 글을 쓸수있도록 노력해야겠습니다.

이번 주 요약

이번 주는 저번 주 말에 했던 MariaDB의 진도를 계속 나갔다.

다음주면 MariaDB도 끝날 것 같다

 

첫 주에 DB를 배울 때를 생각해보면 나는 아는 지식에 더해서 배운다고 생각했었는데

생각보다 나는 모르는게 많았던 것 같다... 하나하나 다시 머릿속에 집어넣고 있다.

 

이번 주에는 가장 중요하다 했던 JOIN에  대해서 배웠는데

역시 JOIN이 추가되니 SQL을 배우고 있다는 느낌이 확실히 들었다.

수업시간에서 가장 좋았던건 역시 강사님이 수업시간 마지막 마다 문제를 내주시고

그걸 스스로 풀어보는게 이해하는데 도움도 되고 좋았던 것 같다.

팀 프로젝트의 서막

이번 주 부터 팀 프로젝트를 위한 팀이 구성되고 본격적으로 프로젝트를 시작하게 되었다.

기한은 12월 31일까지, 결과물은 내가 이해한 바로는 서비스를 하나 만들어서

그에 대한 요구사항 명세서와 ERD를  작성하는 것이다.

 

이 이야기를 듣자마자 처음 팀 프로젝트를 할때가 생각났다.

그때도 분명 요구사항 명세서 작성하고 ERD 작성하고 했었지... 참 어려웠는데...

이번에도 똑같았다. 명세서 작성은 쉽지 않았고 그것보다 어려운건 ERD 작성...

가장 어려운건 테이블 끼리의 관계와 정규화를 맞추는게 가장 어려웠다.

 

물론 아직 다 완성된 것 도 아니고 아직 한참 수정해야하지만

솔직히 지금 다시 보면 이전에 작성한 것들 모두 싹 갈아엎어야 한다고 생각한다.

가장 중요한 주제선정이 제대로 안된 것 같아서 이 부분을 해결해야 한다...

 

이번 프로젝트 회의를 하면서 좀 아쉬운건 정규화나 테이블 연관관계에 대해서 실습을 할 기회를

조금 더 많이 마련해줘야 했지 않나 그런 생각이 들었다.

아직 수업이 끝나지 않았지만 이에 관련해서  명세서의 중요성이나 ERD 테이블에 대해 좀 더

깊이있는 실습과 예제가 더 주어져야 했다고 생각한다.

기억에 가장 남는 것

금요일에 배웠던 인덱스 시간에 MySQL의 공식 DB를 사용하여 인덱스를 생성해보는 예제는 정말 기억에 남았다.

특히 MySQL 공식 DB의 양이 생각보다 엄청나게 방대해서 이걸로 실습 해보는 것은  정말 좋은 경험이였다.

물론 DB가 몇만개가 넘지만 이것 가지고도 유의미한 성능차는 알 수 없었지만,

그래도 이정도 양을 테스트 할 기회가 얼마나 있겠는가?

 

이에 대해서는 나중에 블로그에 자세히 기록할 예정이므로 필요한 사람은 보고 실습해봐도 좋을 것 같다

이번주를 마치며

이제  2주가 되었는데  이 쯤 되니 이 생활이나 환경에 조금이나마 익숙해진 것 같다.

매일 정시에 일어나고 똑같은 장소에서 수업을 듣고 점심을 먹고 회의 하고 집에 돌아오는 삶

내가 원했던 생활과 조금은 가까워지지 않았을까.

 

이전에는 그렇게 정해진 활동 없이 유유히 시간을 보내기만 했지만 (물론 그렇다고 놀기만 한건 아니다)

매일 수업을 듣고 잠자리에 들 때면 많은 생각을 하곤 한다.

내가 왜 여기에 있는가. 나는 왜 이곳에서 이러고 있는가.

내일은 더 나은 생활을 해야지 하고 눈을 감는다.

 

내가 여기에서 경험 하고 얻을 수 있는건 모두 얻어가고 싶다.

그러기 위해 여기까지 온거니깐.

 

ps.
이번에 자격증 공부를 위해 'AWS 공인 솔루션 아키텍트 스터디 가이드' 라는 책을 빌렸는데
내 생각보다 훨씬 어려운것 같다... 그래도 도전해봐야지.

첫 일주일이 지났다

이번주에는 리눅스 기초를 2일에 걸쳐 진도를 나갔고 이후 MariaDB에 대해서 배우고 있다.

리눅스와 MariaDB 둘 다 아는 내용에 더해서 세세하게 내가 놓친 부분들에 대한 학습을 하고있다고 생각한다.

 

이것도 정말 중요하다고 생각하는데

내가 알고있는 지식들은 거대한 뭉탱이이고 그 사이사이 분명 빈 공간이 존재한다.

나는 이번 수업들이 그러한 빈 공간을  채우기 위한 모래라고 생각한다.

이렇게 생각하니 브라질너트  효과가 생각났다만은 조금 다르지만 내가 말하는 바와는 비슷하다고 생각한다.

리눅스

리눅스의 경우에는 이번에 새로운 프로그램을 배웠다

난 항상 리눅스와 SSH연결을 할 때면 칙칙한 PuTTY를 사용했었다.

그런데 이번에 MobaXterm라는 프로그램을 사용해보았는데 PuTTY보다 보기좋고 기능도 좋았다.

특히 제일 맘에 들었던건 연결된 컴퓨터의 라이브러리가 실시간으로 보이고 파일 전송도 쉽고 간편한게 좋았다.

이전에 쓰던 PuTTY는 그런 기능없이 정말 단순하게 터미널 창만 제공했었다.

그래서 쉬운 파일 공유를  위해서 WinSCP라는 프로그램도 별도로 연결하여 운용했었는데

MobaXterm은 그 기능이 합쳐져있어서 정말 편리하게 사용할 수 있었다.

(방금 검색해보니깐 PuTTY도 해당 기능이 있긴 했다)

 

아 그리고 리눅스 마스터 2급 공부할 때 보다도 더 재밌었다.

역시 손으로 직접치고 공부하는게 제일 재미있는것 같다.

 

MariaDB

MariaDB의  경우 MariaDB를 쓰는 것 뿐이지 실제로는 SQL의 기초 문법에 대해서 배우고 있다.

학부생때 들었던 데이터베이스 수업을 다시 듣는 느낌이 났다.

물론 그때랑은 내공이 다르지만 여전히 SQL은 쉽지않다.

문제를 너무 복잡하게 꼬아서 생각한다던지 뭐 그런 부분이 아직 부족하다는게 느껴진다.

 

이번 MariaDB시간에 가장 기억에 남는건 이 문제였다.

employee 테이블에서 이메일 중 _ 앞 글자가 3자리인 주소를 가진 사원의 사번, 직원명, 이메일 조회
예시) sun_di@kh.or.kr

 

단순하게 생각했을때 LIKE 문을 써서 조회 해야지 했는데 한가지 문제에 부딪힌다.

바로 LIKE 문을 사용할때 _ 와 % 는 조건을 설정할 때 쓴다는것이다.

이 문제를 풀 대는 생각 못했었는데 학부생때도 교수님이 비슷한 문제를 내준적이 있었단 사실을 지금 깨달았다.

아무튼 이 문제를 해결하기 위해서는 ESCAPE에 대해서 알아야한다

SELECT emp_id, emp_name, email
FROM employee
WHERE email LIKE '___#_%' ESCAPE '#'
-- WHERE email LIKE '___\_%'
-- 이스케이프 문자는 _ % 같은 특수문자를 검색할수 있게 해준다.
-- 기본적으로 \ 로 설정되어 있지만 ESCAPE '[문자]' 를 사용해 지정해 줄수도 있다.

 

주석에 써둔 것 처럼  \_ 또는 \%를 사용해서 특수문자를 검색할 수 있게 하고

또는 ESCAPE '[문자]'를 통해서 사용자 지정 ESCAPE 문자를 지정할 수 도 있다.

 

이 사실에 대해 모를때는 어거지로 문제를 풀긴 했는데

모든 이메일 테이블의 주소가 aaa_aa@ 이런식으로 앞자리가 구성된다는 사실을 알고

LIKE '______@%' 라고 입력하니깐 되긴 했다.

물론 정답은 아니긴 하지만 특정 상황에 대해서는 정답이였다. 물론 실제로 이렇게 코드를 짜면 나중에 고생한다;;

 

아무튼 기초도 매우 중요하지만 내 생각에 조인하고 외래키 만들고 하는 관계도 형성이 가장 중요하다고 생각한다. 

아마 다음주에 배우지 않을까 싶은데 기대가 된다.

 

이번주를 마무리 하며

블로그에 글을 쓰는게 초등학교 이후 거의 처음이라 아직 많이 어색하다

어떻게  하면 깔끔하게 글을 쓸 수 있을지 더 찾아봐야겠다.

이번주에 배운 내용들은 모두 Notion에 기록했다. 정말 좋은 개인 메모장이다.

하지만 이번주 부터는  여기 적으면서 공부했던 내용들을 내 블로그에 하나씩 올려볼까 한다

정보는 공유할 때 그 진가를 발휘한다고 생각한다.

 

ps.

매일마다 고등학생처럼 수업을 들으니깐 그 당시의 내가 어떻게 버틴거지 라는 생각이 든다;;

지원 계기

이번 연도에 졸업하고 나서 취업을 하기 위해 자기소개서를 쓰다 보니 막상 내세울만한 기록이 없다는 것을 알게 되었다.

물론 개인 프로젝트도 하고 졸업 작품을 만들며 여러 경험을 했지만 이걸로는 부족하다고 느껴졌다.

특히 진행 중이던 개인 프로젝트도 중간중간 막히는 부분이 있거나 기간이 늘어지기 일쑤였다.

그러다 친구가 부트캠프에 참여해서 배우면 어떻겠냐고 추천했었고, 그렇게 알아보던 중 한화시스템 BEYOND SW캠프를 찾게 되었고 오프라인으로 모여서 같이 프로젝트를 진행하고 배우며 피드백을 받을 수 있는 기회인 이번 SW캠프를 신청하게 되었다.

서류합격 이후의 인터뷰

지원서 자체는 별 내용이 없었지만 인터뷰를 통해 관련 경험이나 경력이 있는지 왜 이곳을 선택했는지 등 많은 것을 물어보셨다. 매우 딱딱한 분위기 일 것이라 생각하고 경직되어 있었는데 웃으며 질문을 해주셔서 편안하게 인터뷰를 할 수 있었다.

OT는 어떻게 진행되었는가

OT는 교육수강 안내 → 커리큘럼 설명 → 네트워킹 순으로 진행되었고

대략적인 커리큘럼은 5번의 프로젝트를 통하여 Spring을 활용한 풀스택 개발이 목표인 것 같다.

네트워킹은 즉석에서 5~6명이서 팀을 이뤄 자기소개, 팀 명 정하기, 팀을 표현하는 블록 만들기를 했다.

덕분에 딱딱했던 분위기가 편하게 풀어졌고 즐거운 마음으로 팀원뿐만 아니라 이번 캠프에 참여한 다른 분들의 이야기도 들어볼 수 있었다.

지원하신 이유도 다양하고 비전공자도 많으셨는데 이야기를 들어보니 이들 모두의 공통점은 개발에 대해서 제대로 배우고 싶어서 왔다는 것이 느껴졌다.

이번 OT에서의 느낀 점

지방에 사는 나의 입장에서 서울에서 오프라인 강의를 듣는 것은 정말 큰 도전이었다.

하지만 첫 자취임과 동시에 항상 서울로 올라오겠다는 다짐을 했던 나날들을 생각해 보며 기대감에 가슴이 떨렸다.

OT 때 와서 커리큘럼 등을 들었을 때 정말 잘 선택했다는 생각이 들었다.

이번 캠프를 발판 삼아서 탄탄한 기초를 다지고 더 나은 개발자가 되고 싶다.

또한 이번 기회에 만들게 된 이 블로그를 적극 활용하고 나만의 포트폴리오를 만들고 싶다.

 

다음 주부터 시작하는 1 주차가 기대된다

 

ps.
나는 ‘내일 배움 카드’를 발급받지 않은 상황이어서 급하게 발급받았었다.
관련 교육을 듣고 싶다면 미리 발급받고 신청하는 게 더 좋을 것 같다.

 

+ Recent posts