📌 사용계기

깃헙에서 같은 형식의 이슈를 자주 발행하거나 형식을 공통화 시킬 때를 위해 이슈 템플릿을 만들어 쓸 수 있는데

혼자 공부할때도 형식을 통일시켜 깔끔하게 써보기 위해 적용하려고 한다.

 

 

 

📍 적용과정

1. github > setting

2. general에서 화면을 내리면 features 구간이 있는데 여기서 set up templates를 누른다.

3. Custom template를 선택

4. 그러면 아래처럼 나오는데 Preview and edit을 클릭

5. 아래처럼 화면이 펼쳐지고 연필을 클릭해 수정하면 된다.

6. 예시)

7. 모두 수정했으면 Propose changes를 클릭

8. 템플릿 업데이트에 대한 Commit 메세지를 결정하여 commit해준다.  

9. 그러면 이슈를 발생할 때마다 이런 화면이 나와서 템플릿을 선택할 수 있게 되고

10. 템플릿이 적용된다!

 

끝!

📌 김영한 님의 "스프링 핵심 원리 - 기본편" 강의 듣고 정리

목차

     

    Section 1 . 객체 지향 설계와 스프링

    스프링이란? 

     

    ☘️ 스프링 생태계

    필수!

    • 스프링 프레임워크
    • 스프링 부트 : 스프링 기술들을 편하게 사용할 수 있게 도움을 주는 기술

    👆 선택

    • 스프링 데이터 : 데이터베이스를 사용하는 데 도움을 주는 기술 (가장 많이 쓰는게 Spring Data JPA)
    • 스프링 세션 : 세션 기능을 편리하게 사용할 수 있도록 도움을 주는 기술
    • 스프링 시큐리티 : 보안
    • 스프링 Rest Docs : API 문서와 테스트를 엮어 편리하게 도움을 주는 기술
    • 스프링 배치 : 배치 처리에 특화된 기술
    • 스프링 클라우드 : 클라우드에 특화된 기술
    • 등등 

     

    ☘️ 스프링 프레임 워크

    • 핵심 기술: 스프링 DI 컨테이너, AOP, 이벤트, 기타 (강의의 초점!!)
    • 웹 기술: 스프링 MVC, 스프링 WebFlux
    • 데이터 접근 기술: 트랜잭션, JDBC, ORM 기원, XML 지원
    • 기술 통합: 캐시, 이메일, 원격접근, 스케쥴링
    • 테스트: 스프링 기반 테스트 지원
    • 언어: 코틀린, 그루비
    • 최근에는 스프링 부트를 통해서 스프링 프레임원크의 기술들을 편리하게 사용

     

    ☘️ 스프링 부트

    • 스프링을 편리하게 사용할 수 있도록 지원, 최근에는 기본으로 사용
    • 단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게 생성
    • Tomcat 같은 웹 서버를 내장해서 별도의 웹 서버를 설치하지 않아도 됨
    • 손쉬운 빌드 구성을 위한 starter 종속성 제공
    • 스프링과 3rd party(외부) 라이브러리 자동 구성, 의존성 버전 관리
    • 메트릭, 상태 확인, 외부 구성 같은 프로덕션 준비 기능 제공 (모니터링 제공)
    • 관례에 의한 간결한 설정
    • 스프링 부트는 스프링과 별도로 사용가능한 것이 아니다! 스프링 프레임워크 위에서 편리하게 기능을 사용할 수 있도록 돕는다!

     

    ☘️ 스프링 단어?

    스프링이라는 단어는 문맥에 따라 다르게 사용된다.

    • 스프링 DI 컨테이너 기술
    • 스프링 프레임워크
    • 스프링 부트, 스프링 프레임워크 등을 모두 포함한 스프링 생태계 

     

    ☘️ 스프링 왜 만들었나요?

    핵심 개념: 이 기술을 왜 만들었는가? 이  기술의 핵심 컨셉은? (로드존슨이랑 유겐 힐러가 왜 만들었을까!?!?!)

     

         ❓웹 애플리케이션 만들고, DB 접근 편리하게 해주는 기술?

         ❓전자정부 프레임워크?

         ❓웹 서버도 자동으로 띄워주고?

         ❓클라우드, 마이크로 서비스?

     

    인걸까?? ❌ 이건 다 결과물일 뿐이다

     

     * 스프링의 진짜 핵심

    • 스프링은 자바 언어 기반의 프레임워크
    • 자바 언어의 가장 큰 특징 - 객체 지향 언어
    • 스프링은 객체 지향 언어가 가진 강력한 특징을 살려내는 프레임워크
    • 스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크

    사람들이 스프링 등장에 열광했던 건 스프링 이전의 EJB는 객체 지향의 장점을 망치는 기술이었기 때문에 이걸 살릴 수 있었던 기술에 열광했던 거다!! 

     

     


    좋은 객체 지향 프로그래밍이란?

     

    ☘️ 객체 지향 특징

    • 추상화 
    • 캡슐화
    • 상속
    • 다형성

     

    ☘️ 객체 지향 프로그래밍

    • 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위,
      "객체"들의 모임으로 파악하고자 하는 것이다. 각자의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. (협력)
      • 혼자 있는 객체는 없다.
      • 객체끼리 뿐만 아니라 수많은 객체 클라이언트와 객체 서버는 서로 협력 관계를 가진다. (요청과 응답하면서)
      • 서버끼리도, 시스템끼리도! 
    • 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다. 

    유연하고, 변경이 용이하다? 

    객체 단위로 개발하기 때문에

    • 레고 블럭 조립, 키보드 마우스 교체, 컴퓨터 부품 교체 처럼
    • 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법

    이런 궁극의 유연함을 가질 수 있게 하는 객체 지향의 핵심! 다형성(Polymorphism) 이다. 

     

     

    ☘️ 다형성(Polymorphism) 

    자동차라는 역할이 존재하고 이 자동차 역할에 그 어떤 종류에 자동차가 구현(K3든, 아반떼든, 테슬라든) 되어도 운전자는 자동차를 운전할 수 있다. 운전자는 자동차 역할이라는 인터페이스에 의존하고 있기 때문에 구현이 어떤게 와도 상관없다.

    이는 운전자를 위한 것이다.

    자동차 내부 동작 방식이 바뀌어도 운전자에게는 영향이 없기 때문에 쓰던 방식 그대로 쓸 수 있다. 운전자는 새로 뭔가를 배울 필요가 없다. 또한 구현체를 바꿔버려도 운전이 그대로 가능하니까 자동차 역할만 지키면 새로운 구현체도 들어올 수 있어 확장성이 생긴다.

    이게 가능한 것이 역할과 구현을 나눠놨기 때문이다.  (연극에서 하나의 역할을 여러사람이 할 수 있는 것도)

     

     

    ☘️ 역할과 구현을 분리

    • 역할과 구현으로 구분하면 세상이 단순해지고, 유연해지며 변경도 편리
    • 장점
      • 클라이언트는 대상의 역할(인터페이스)만 의존
      • 클라이언트는 구현 내부 몰라도 된다. 변경도 몰라도 되며, 심지어 구현 대상 자체가 바뀌어도 영향 X

    프로그래밍 언어에서도 이러한 장점을 받아들이게 된다.

     

     

    ☘️ 자바 언어에서는 이걸 어떻게 받아들였을 까?

    자바 언어의 다형성을 활용한 방식은 객체 설계시 역할과 구현을 명확하게 분리했다.

    객체 설계시 역할(인터페이스)을 먼저 부여하고, 그 역할을 수행하는 구현 객체 만드는 방식으로 차용

    • 역할 = 인터페이스
    • 구현 = 인터페이스를 구현한 클래스,  구현 객체

    역할 > 구현. 역할이 더 중요하다

     

    오버라이딩 된 메서드가 실행될 때 다형성으로 인터페이스를 구현한 객체를 실행 시점에 유연하게 변경 할 수 있다.

    상속 관계에서도 다형성, 오버라이딩 적용 가능

     

     

    ☘️ 다형성의 본질

    • 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경 할 수 있다. 
    • 다형성의 본질을 이해하려면 협력이라는 객체사이의 관계에서 시작해야한다. 
    • 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다. 

     

    ☘️ 역할과 구현을 분리 : 정리

    • 역할과 구현이라는 컨셉을 다형성을 통해 객체화 할 수 있다.
    • 유연하고 변경이 용이
    • 확장 가능
    • 클라이언트에 영향을 주지 않는 변경이 가능

    따라서, 인터페이스를 안정적으로 잘 설계하는 것이 중요하다. 

     

     

    ☘️ 하지만 한계도 있다

    역할(인터페이스)이 변하면 클라이언트, 서버 모두 변경이 발생한다. 그래서 더더욱 안정적인 인터페이스가 필요하다.  

     

     

    ☘️ 스프링과 객체 지향

    객체지향의 꽃은 다형성

    스프링은 이런 다형성을 극대화해서 이용이 가능하게 한다.

    스프링에서 말하는 제어의 역전(IoC), 의존관계 주입(DI)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원해주는 역할을 해준다!

    그래서 결론! 스프링을 사용하면 블럭 조립하든 구현을 편리하게 변경할 수 있다!

     

    다형성이 스프링에 굉장히 중요한데 여기서 한가지가 더 있어야 완전히 스프링을 설명할 수 있다.

    그게 바로 좋은 객체 지향 설계의 5가지 원칙, 소위 SOLID 라고 불리는 원칙이다.


    좋은 객체 지향 설계의 5가지 원칙 (SOLID)

     

    ☘️ SRP (단일 책임의 원칙 / Single reponsibility principle)

    한 클래스는 하나의 책임만 가져야 한다는 원칙. 하지만 하나의 책임이라는 게 모호하고 문맥과 상황따라 다를 수 있는 거라 중요한건 변경을 기준으로 한다. 변경의 이유를 하나만 가질 것 변경의 이유가 여러가지가 생겼다면 한가지 이상의 책임을 맡고 있는 것이다. 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이다.

     

    ☘️ OCP (개방-폐쇄 원칙 / Open-Closed principle)

    소프트웨어 요소는 확장에는 열려있고, 변경에는 닫혀있어야 한다. 

    다형성을 활용해 이 원칙을 지킬수가 있다. 인터페이스를 구현한 새로운 클래스를 만들어 새로운 기능을 구현하면 확장에는 열려있다. 그리고 이 변화가 외부의 기존 코드에 변경을 주지 않는다. 변경에는 닫혀있는 것이다. 

     

    그런데, 개발 폐쇄 원칙은 문제점이 있다. 

    만약 MemberRepository m = new MemoryMemberRepository(); 를 

    MemberRepository m = new JdbcMemberRepository();로 구현 객체를 변경할 경우

    클라이언트가 코드에서 변경을 해야한다. 다형성을 사용했으나 OCP 원칙을 지킬 수 없는데 이 문제를 해결하기 위해 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다. 

     

    이 역할을 스프링의 컨테이너가 해준다! 이 원칙을 지키기위해 IoC(제어의 역전)도 DI(의존성 주입)도 필요한 것!

     

    ☘️ LSP (리스코프 치환 원칙 / Liskov Substitution principle)

    프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 

    이것은 단순히 코드에 상위 타입이 하위타입의 인스턴스로 교체를 성공하여 컴파일이 성공하는 걸 의미하지 않는다.  

    상위 타입의 객체를 하위 타입의 객체로 치환했다고 하더라도 상위 타입으로 동작하던 기존 프로그램은 정상적으로 동작해야하는 원칙이다. 상위의 엑셀 기능이 하위 타입으로 교체했을 때 후진 기능이 되버리면 리스코프 치환 원칙에 위배된 것이다. 하위 클래스는 인터페이스 규약을 다 지켜야한다. 그래서 다형성을 지원하기 위해 필요한 원칙으로 인터페이스를 구현한 구현체를 믿고 사용하려면 이 원칙이 필요하다. 

     

    ☘️ ISP (인터페이스 분리 원칙 / Interface segregation principle)

    특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다. 

     

    자동차 인터페이스 > 운전 인터페이스, 정비 인터페이스 로 분리

    사용자 클라이언트 > 운전자 클라이언트, 정비사 클라이언트로 분리

    이런식으로 분리하면 정비 인터페이스를 변경해도 정비사 클라이언트만 영향을 주지 운전자 클라이언트는 영향을 주지않는다. 기능을 적당한 크기로 자르는 것이 중요. 인터페이스(역할)이 명확해지고, 하나의 큰 역할이 아닌 보다 작은 역할들로 잘라낸 것이라 대체 가능성이 높아진다.

     

    ☘️ DIP (의존관계 역전 원칙 / Dependency inversion principle)

    구체화에 의존하지 말고 추상화에 의존해라! = 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻

     

    SOLID에서 특히 중요한 원칙이 OCP와 DIP

    앞서 이야기한 역할에 의존해야하는 것과 같은 이야기! 클라이언트가 인터페이스를 의존해야 유연하게 구현체를 바꿀 수 있기 때문이다. 

     

    만약 MemberRepository m = new MemoryMemberRepository(); 를

    MemberRepository m = new JdbcMemberRepository();로 구현 객체를 변경할 경우

     

    이 예시를 보면 인터페이스를 의존하면서도 구현 클래스에도 결국 같이 의존하고 있어 결국 구현체 변경시 코드까지 변경해야 하는 것이다. (DIP 위반)

    그럼 어떻게 하라는 거지?

     

    ☘️ 정리

    객체 지향의 핵심은 다형성이지만 다형성만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.
    결국 구현 객체 변경시 클라이언트 코드 또한 변경해야하기 때문에 OCP, DIP를 지킬수 없다.

    이걸 지키기 위해 무언가가 필요한데 그걸 지키기 위해 탄생한게 스프링이다!

     


    객체 지향 설계와 스프링

     

    ☘️ 스프링 이야기가 객체 지향에서 나오는 이유?

    스프링은 아래 기술로 다형성 + OCP, DIP를 가능하게 지원한다

    • DI(Dependency Injection) : 의존관계, 의존성 주입
    • DI 컨테이너 제공

    이 기술들로 클라이언트 코드 변경 없이 기능을 확장이 가능하게 하고 부품 교체하듯 대체도 가능하다.

     

    ☘️ 정리

    • 모든 설계에 역할구현을 분리 (예시였던 자동차와 연극의 역을 생각해!)
    • 애플리케이션 설계도 인터페이스(역할)을 만들어두고 언제든 유연하게 변경할 수 있도록 만드는 게 좋은 객체 지향 설계다.  (> 이걸 가능하게 하는 것이 스프링 컨테이너)

    이상적으로는 모든 설계에 인터페이스 부여 하지만 이걸 도입하려면 추상화라는 비용이 발생한다.

    따라서 기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하고, 후에 리팩토링을 통해 인터페이스를 도입하는 것도 방

    'Programming > Spring' 카테고리의 다른 글

    QueryDSL 적용 방법  (0) 2023.04.01
    WebRTC 시그널링 서버 (Spring Boot로 구현)  (1) 2023.01.12
    Query DSL  (0) 2022.12.15
    스프링 부트(Spring Boot) 다운 그레이드  (0) 2022.12.07
    ORM / JPA / Hibernate / Spring Data JPA  (0) 2022.12.05

    📌 파이썬 으로 풀이

     

    📌 문제 링크 :

     

    프로그래머스

    코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

    programmers.co.kr

     

    📌 문제 설명 :

    다음 규칙을 지키는 문자열을 올바른 괄호 문자열이라고 정의합니다.

    • (), [], {} 는 모두 올바른 괄호 문자열입니다.
    • 만약 A가 올바른 괄호 문자열이라면, (A), [A], {A} 도 올바른 괄호 문자열입니다. 예를 들어, [] 가 올바른 괄호 문자열이므로, ([]) 도 올바른 괄호 문자열입니다.
    • 만약 A, B가 올바른 괄호 문자열이라면, AB 도 올바른 괄호 문자열입니다. 예를 들어, {} 와 ([]) 가 올바른 괄호 문자열이므로, {}([]) 도 올바른 괄호 문자열입니다.

    대괄호, 중괄호, 그리고 소괄호로 이루어진 문자열 s가 매개변수로 주어집니다. 이 s를 왼쪽으로 x (0 ≤ x < (s의 길이)) 칸만큼 회전시켰을 때 s가 올바른 괄호 문자열이 되게 하는 x의 개수를 return 하도록 solution 함수를 완성해주세요.

     

    📌 제한 사항

    • s의 길이는 1 이상 1,000 이하입니다.

     

    📌 입출력 예


    추측) 

    괄호짝을 배열로 만들어 준비한다. 

    문자열 s를 리스트로 만들어 맨앞에 것을 pop해 뒤로 append해주는 방식으로 회전을 시키고 문자열로 합쳐준다 (처음 회전이 필요없는 경우는 그냥) 

    그리고 그 문자열에서 괄호짝 배열 for문을 돌려 짝을 찾으면 삭제하는 방식을 반복한다. 

    대신 3개의 괄호짝이 없을 경우 각각 flag를 0으로 바꾸어주고 모두 0이 되면 카운팅 없이 나오기

    text길이가 0이되면 모두 지워냈으므로 올바른 괄호문자열이라 카운팅한다

    이를 반복해서 마지막에 카운트를 반환

     

    소스코드) 

    * 1차) 실패 : 정확도 78.6

    def solution(s):
        answer = 0
        bracket = ['()', '[]', '{}']
        s_list = list(s)
        for i in range(len(s)):
            text = ""
            if i != 0:
                s_list.append(s_list.pop(0))
                text = ''.join(one for one in s_list)
            else :
                text = s
    
            flag_list = [1, 1, 1]
            flag = True
            while flag:
                if len(text) == 0 :
                    answer += 1
                    break
    
                if flag_list == [0, 0, 0]:
                    break
    
                for x in range(len(bracket)) :
                    if bracket[x] in text:
                        text = text.replace(bracket[x], "")
                    else:
                        flag_list[x] = 0
                        pass
    
        return answer

    * 2차) 실패 : 정확도 92.9 😭 악 단하나의 케이스가

    def solution(s):
        answer = 0
        bracket = ['()', '[]', '{}']
        s_list = list(s)
        for i in range(len(s)):
            text = ""
            if i != 0:
                s_list.append(s_list.pop(0))
                text = ''.join(one for one in s_list)
            else :
                text = s
    
            flag_list = [1, 1, 1]
            flag = True
            while flag:
                if len(text) == 0 :
                    answer += 1
                    break
    
                if flag_list == [0, 0, 0]:
                    if text.find(bracket[0]) and text.find(bracket[1]) and text.find(bracket[2]):
                        break
    
                for x in range(len(bracket)) :
                    if bracket[x] in text:
                        text = text.replace(bracket[x], "")
                    else:
                        flag_list[x] = 0
                        pass
    
        return answer

    * 3차) 성공

    def solution(s):
        answer = 0
        bracket = ['(',')', '[',']', '{','}']
        s_list = list(s)
        for i in range(len(s)):
            if i != 0:
                s_list.append(s_list.pop(0))
    
            stack = []
            for one in s_list:
                stack.append(one)
                stack_len = len(stack)
                if stack_len >= 2:
                    for x in range(0,len(bracket),2) :
                        if stack[stack_len-2:stack_len] == bracket[x:x+2]:
                            stack = stack[:stack_len-2]
    
            if len(stack) == 0 :
                answer += 1
    
        return answer

     

     

    리뷰) 

     

    1차)

    플래그를 세울기점을 잘 생각해봐야 할듯하다.

    왜냐면 지금 내 로직대로는 만약 ({}) 괄호 경우 () 차례에서 이걸 못찾아서 플래그를 0으로 넣고 {} 이걸 지우고 나서야 ()를 판별할 수 있는데 이미 플래그는 0이 됬기 때문

     

    2차) 

    통과하지 못한 1번 케이스 뭐지..  1번 케이스로 고민하다가 전에 이거랑 비슷한 문제를 풀었던게 생각나서 햄버거 문제에서 썼던 stack 방식을 응용하니 바로 3차에서 성공 오오오!!!! 이런 유형이 바로 스택 유형!

     

     

    Programmers] 햄버거 만들기

    📌 파이썬 으로 풀이 📌 문제 링크 : 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을

    littlezero48.tistory.com

     

    그런데! 3차 방식으로 통과한거랑 2차에 하나의 케이스만 실패한 경우를 비교하면 2차가 더 말도안되게 빠름... 

    2차는 for/while/for 로 사용한 3중 문인데 훨씬더 속도가 빠르다 😯😯

    2차가 통과하지 못한 케이스에 대해 좀더 생각해봐야할 듯 하다.

     

    3차 결과
    2차 결과

    'Coding Test > Algorithm' 카테고리의 다른 글

    Programmers] 멀리 뛰기  (0) 2023.03.18
    Programmers] [1차] 캐시  (0) 2023.03.18
    Programmers] 최솟값 만들기  (0) 2023.03.13
    Programmers] N개의 최소공배수  (0) 2023.03.07
    Programmers] 최댓값과 최솟값  (0) 2023.03.06

     

    🤔 더미 데이터가 왜 필요해?

    상품 데이터는 쿠팡에서 크롤링해 왔지만 실서비스를 목적으로 하지 않는 우리 프로젝트에 유저 경우에는 더미 데이터로 진행하기로 했다.

    랜덤으로 데이터를 생성해주는 서비스를 이용하여 집어 넣을 예정이었는데, 언어가 한글인 게 없어서 직접 코딩하기로!

     

    간단히 파이썬으로 코딩

     


    😃 더미 데이터 생성 코드

    🪪 랜덤 이름

    # 이름 생성 함수들
    def firstName():
        first = ["김", "이", "박", "최", "정", "강", "조", "윤", "장", "임", "한", "오", "서", "신", "권", "황", "안",
                 "송", "류", "전", "홍", "고", "문", "양", "손", "배", "조", "백", "허", "유", "남", "심", "노", "정",
                 "하", "곽", "성", "차", "주", "우", "구", "신", "임", "나", "전", "민", "유", "진", "지", "엄", "채",
                 "원", "천", "방", "공", "강", "현", "함", "변", "염", "양", "변", "여", "추", "노", "도", "소", "신",
                 "석", "선", "설", "마", "길", "주", "연", "방", "위", "표", "명", "기", "반", "왕", "금", "옥", "육",
                 "인", "맹", "제", "모", "장", "남", "탁", "국", "여", "진", "어", "은", "편", "구", "용"]
    
        return random.choice(first)
    
    def LastName():
        last =  ["가", "강", "건", "경", "고", "관", "광", "구", "규", "근", "기", "길", "나", "남", "노", "누", "다",
                "단", "달", "담", "대", "덕", "도", "동", "두", "라", "래", "로", "루", "리", "마", "만", "명", "무", "문", "미", "민", "바", "박",
                "백", "범", "별", "병", "보", "빛", "사", "산", "상", "새", "서", "석", "선", "설", "섭", "성", "세", "소", "솔", "수", "숙", "순",
                "숭", "슬", "승", "시", "신", "아", "안", "애", "엄", "여", "연", "영", "예", "오", "옥", "완", "요", "용", "우", "원", "월", "위",
                "유", "윤", "율", "으", "은", "의", "이", "익", "인", "일", "잎", "자", "잔", "장", "재", "전", "정", "제", "조", "종", "주", "준",
                "중", "지", "진", "찬", "창", "채", "천", "철", "초", "춘", "충", "치", "탐", "태", "택", "판", "하", "한", "해", "혁", "현", "형",
                "혜", "호", "홍", "화", "환", "회", "효", "훈", "휘", "희", "운", "모", "배", "부", "림", "봉", "혼", "황", "량", "린", "을", "비",
                "솜", "공", "면", "탁", "온", "디", "항", "후", "려", "균", "묵", "송", "욱", "휴", "언", "령", "섬", "들", "견", "추", "걸", "삼",
                "열", "웅", "분", "변", "양", "출", "타", "흥", "겸", "곤", "번", "식", "란", "더", "손", "술", "훔", "반", "빈", "실", "직", "흠",
                "흔", "악", "람", "뜸", "권", "복", "심", "헌", "엽", "학", "개", "롱", "평", "늘", "늬", "랑", "얀", "향", "울", "련"]
    
        return random.choice(last)
    
    # 사용시
    name = firstName() + LastName() + LastName()

     

    📨 랜덤 주소

    이번 더미데이터 생성의 핵심!

    주소 같은 경우에는 어떻게 생성해야하나 고민했는 데 구글링 하다가 전국 건물 주소를 제공하는 서비스가 있었다.

    이를 다운 받고 랜덤 줄을 받아와 파이프기준으로 list형태를 만들어 가공해 필요한 정보만 가져오는 식으로 정제하는 방법을 채택했다.

     

    -원 정보 형태 (아래 사이트에서 전국 시도 기준으로 txt 파일을 제공하고 있다. 참고로 2018년 때의 주소!!! 주의!!!) 

     

    주소정제전환서비스

    주소를 입력하세요. 정제된 도로명주소 및 지번주소로 자동 변환

    www.sujiewon.com

    - 위 파일을 사용하여 주소 추출

    def address():
        f_Ad = open('build_seoul.txt', 'r')
        random_line = random.choice(list(f_Ad.readlines())).splitlines()[0]
        f_Ad.close()
        return random_line
    
    # 사용시
    address_full = address()
    address_list = address_full.split('|')
    
    sido = address_list[1]
    sigungu = address_list[2]
    eupmyeondong = address_list[3]
    street = address_list[9]
    zipcode = address_list[19]
    

     

     

    🪪 랜덤 아이디와 이메일

    def loginId():
        n = random.randrange(5,10)
        loginId = ""
        for x in range(n):
            loginId += str(random.choice(string.ascii_lowercase))
    
        return loginId
    
     # 사용시
    login_Id = loginId()
    email = login_Id + "@google.com"
    
    

     

    🔒 랜덤 패스워드

    password_make = string.ascii_letters + string.digits
    
    def password():
        lenNum = 64
        password = "";
        for y in range(64) :
            password += random.choice(password_make)
    
        return password
    
    # 사용시
    password()
    

     

    📄 CSV파일로 변환

    password_make = string.ascii_letters + string.digits
    create_cnt = 1000
    
    f_Save = open('random_member.csv', 'w', encoding='utf-8', newline='')
    wr = csv.writer(f_Save)
    
    for i in range(create_cnt) :
        name = firstName() + LastName() + LastName()
        address_full = address()
        address_list = address_full.split('|')
    
        login_Id = loginId()
        email = login_Id + "@google.com"
    
        sido = address_list[1]
        sigungu = address_list[2]
        eupmyeondong = address_list[3]
        street = address_list[9]
        zipcode = address_list[19]
    
        wr.writerow([sido, sigungu, eupmyeondong, street, zipcode, email, login_Id, name, password()])
        print([sido, sigungu, eupmyeondong, street, zipcode, email, login_Id, name, password()])
    
    f_Save.close()
    

     

    🎉 결과물

     

    📌 파이썬 으로 풀이

     

    📌 문제 링크 :

     

    프로그래머스

    코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

    programmers.co.kr

     

    📌 문제 설명 :

    길이가 같은 배열 A, B 두개가 있습니다. 각 배열은 자연수로 이루어져 있습니다.
    배열 A, B에서 각각 한 개의 숫자를 뽑아 두 수를 곱합니다. 이러한 과정을 배열의 길이만큼 반복하며, 두 수를 곱한 값을 누적하여 더합니다. 이때 최종적으로 누적된 값이 최소가 되도록 만드는 것이 목표입니다. (단, 각 배열에서 k번째 숫자를 뽑았다면 다음에 k번째 숫자는 다시 뽑을 수 없습니다.)

    예를 들어 A = [1, 4, 2] , B = [5, 4, 4] 라면

     

    • A에서 첫번째 숫자인 1, B에서 첫번째 숫자인 5를 뽑아 곱하여 더합니다. (누적된 값 : 0 + 5(1x5) = 5)
    • A에서 두번째 숫자인 4, B에서 세번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 5 + 16(4x4) = 21)
    • A에서 세번째 숫자인 2, B에서 두번째 숫자인 4를 뽑아 곱하여 더합니다. (누적된 값 : 21 + 8(2x4) = 29)
      즉, 이 경우가 최소가 되므로 29를 return 합니다.

      배열 A, B가 주어질 때 최종적으로 누적된 최솟값을 return 하는 solution 함수를 완성해 주세요.

     

    📌 제한 사항

    • 배열 A, B의 크기 : 1,000 이하의 자연수
    • 배열 A, B의 원소의 크기 : 1,000 이하의 자연수

     

    📌 입출력 예


    추측) 

    가장 최솟값을 만들려면 가장 작은값과 가장큰 값을 곱해서 누적해야 할 듯하다. A도 B도 정렬을 하되 하나는 역순 정렬을 하고 for문으로 같은 인덱스값 곱해줘서 누적시키고 누적값을 리턴!

     

    소스코드) 

    * 1차) 성공!

    def solution(A,B):
        answer = 0
        A.sort()
        B.sort(reverse = True)
    
        for i in range(len(A)):
            answer += A[i] * B[i]
        
        return answer

     

    리뷰) 

    다른 사람들의 풀이를 보니 한줄 for문과 리스트 표현식에 sum 함수로 한줄로 정리도 된다 와우!

    람다 방식로도 풀었던데 다양한 방식으로 나중에 도전해보고 어떤게 효율적인지 봐야겟다. 

    'Coding Test > Algorithm' 카테고리의 다른 글

    Programmers] [1차] 캐시  (0) 2023.03.18
    Programmers] 괄호 회전하기  (0) 2023.03.14
    Programmers] N개의 최소공배수  (0) 2023.03.07
    Programmers] 최댓값과 최솟값  (0) 2023.03.06
    Programmers] 카드 뭉치  (0) 2023.02.28

    + Recent posts