📌 공부 계기

원티드 챌린지가 이번 달 제공하는 강의는 Docker! Docker 강의가 총 4번 이루어지는 데 정리해보려고 합니다.

 

Docker 강의 1 : 

목차

     

    📍이론편 : 도커 개념

    * 도커 공식 홈페이지

     

    Docker: Accelerated, Containerized Application Development

    Docker is a platform designed to help developers build, share, and run modern applications. We handle the tedious setup, so you can focus on the code.

    www.docker.com

    도커 이론 편은 이전 도커 개념을 정리한 포스팅에 고병현님의 강의내용을 추가해 정리

     

    Docker] 개념

    📌 공부 이유 실전 프로젝트하면서 백엔드를 고도화하면서 여러기술에 도전해보고 있다. Docker도 그 중 하나로, 이름만 알고 뭐하는 녀석인지 전혀 몰랐기 때문에 먼저 개념을 공부해보고 실습

    littlezero48.tistory.com

     

     

    📍실습편 1 : 기본 CLI

    공식 홈페이지의 Command-line reference (공식 홈페이지를 공부하자!)

     

    Docker run reference

     

    docs.docker.com

     

    0️⃣ 사전 준비 

    더보기

     

    📢 참고 : 저는 윈도우에 리눅스를 사용할 수 있게 하는  WSL2 설치한 환경에서 진행 했습니다. 

     

    * 파워쉘에서 명령어 wsl 접속 or Ubuntu on Windows 실행

    * Docker Desktop 실행도 해줘야 함

    파워쉘 경우
    Ubuntu on Windows 실행

     


     

    1️⃣ 도커 이미지 다운로드 

    - Docker hub로 부터 httpd 이미지를 다운받아 본다 

    docker pull 이미지이름

     

    - pull하고 나서 이미지 조회 하면 추가된 걸 확인 할 수 있다

     


     

    2️⃣ 이미지를 통해 컨테이너 생성 

    - run 명령어를 통해 해당 이미지에 대한 컨테이너 생성

    * 주의 : httpd 같은 경우 run 시키면 이 화면을 더 이상 사용할 수 없게 된다. 화면을 분할해서 이후 명령어를 사용해보자

    (아니면 d 옵션을 함께 주어 데몬모드로 run!)

    더보기

    ✅ 화면 분할 방법

     방법1) 탭 타이틀에서 오른쪽 클릭 (단, 세로 -> 가로 -> 세로 -> ... 식으로 분할)

     

    방법2) Ctrl + Shift + P 로 명령 도구 모음을 실행해서 

     

    추가할 방향을 선택해 클릭

     

    결과 

     

     

    - 컨테이너 실행 확인 (이름 설정을 안하면 container name은 임의로 결정됨)

    docker ps

     

    - 이름옵션을 사용해 컨테이너 이름을 설정하고 컨테이너 생성 (secondContainer 라는 이름으로)

    docker run --name 컨테이너이름 사용할이미지이름

    지정이름으로 생성 확인! 그리고 run으로 하면 무조건 새로 컨테이너 생성

     


     

    3️⃣ 컨테이너의 포트와 연동시키기 (Port Forwarding)[각주:1]

    - 컨테이너 생성시 p 옵션으로 LocalPort : ContainerPort 로 해서 포트를 연결한다.

    docker run -p 로컬포트:컨테이너포트 --name 컨테이너이름 사용할이미지이름

    포트포워딩이 된 걸 확인
    아파치 서버(포트80) 기본 페이지 데이터가 서빙된 걸 확인

     


     

    4️⃣ 이미지 내부의 파일을 교체하기 

    - 교체하려는 파일이 있는 디렉토리로 찾아감

     

     - 해당 디렉토리에 대해 VScode 실행

    code .

     

    - 위 경로의 index.html을 서빙하도록 교체하고 싶다! 

    v 옵션을 통해서 볼륨 마운트가 가능한데 이게 이미지의 파일을 호스트의 파일로 덮어씌우는 걸 말한다. 

     

    여기서 -v HostPath : ContainerPath 로 앞의 HostPath는 덮어씌울 파일이 있는 경로로 

    내가 덮어씌우려는 경로는 아래 그림의 하늘색 글자 부분과 같다. 

    호스트 경로 방식 적용은 윈도우랑 우분투랑 다르니 참고!

    우분투의 home/계정/ 아래부터 경로 시작
    윈도우 경우는 절대경로
    다른 index.html로 적용된 모습

     


     

    5️⃣ 컨테이너 STOP 

    docker stop 컨테이너ID 
    docker stop 컨테이너이름

    컨테이너 ID로 정지
    컨테이너 이름으로 정지

     


     

    6️⃣ 컨테이너 START 

    run 처럼 컨테이너 생성과 동시에 실행하는 게 아닌 멈춤 컨테이너를 다시 실행시키는 명령어

     

    - 일단 docker ps가 실행되고 있는 컨테이너만 조회했다면 여기에 -a 옵션 (all)을 붙여 실행여부와 상관없이 생성되어있는 모든 컨테이너를 조회한다.

    docker ps -a

     

    - 실행

    STATUS를 보면 Exited 에서 Up으로 변경되며 실행

    docker start 컨테이너ID 
    docker start 컨테이너이름

    컨테이너 ID로 실행
    컨테이너 이름으로 실행

     


     

    7️⃣ 컨테이너 제거 

    rm 명령어 (remove) 를 사용해 컨테이너 제거 

    docker rm 컨테이너ID 
    docker rm 컨테이너이름

    둘다 지우고 나니 ps -a 시 아무것도 안나오는 것 확인!

     

     

    + 참고로 실행 중인 컨테이너는 삭제할 수 없다. stop으로 정지하고 지울 것

     


     

    8️⃣ 이미지 제거 

    rmi 명령어 (remove image) 를 사용해 이미지 제거

    docker rmi 이미지이름

    이미지 삭제 확인

     

    + 이미지 역시 이 이미지를 사용하는 컨테이너가 존재한다면 지울 수 없다. 해당 이미지를 사용하는 컨테이너를 모두 지워야 제거 가능

     

     

     

    📍실습편 2 : 커스텀 이미지 생성

     

    Dockerfile reference

     

    docs.docker.com

     

    실습 내용

    httpd 이미지를 pull 받아 실습 1때 처럼 index.html을 교체하고 포트포워딩까지 해서 run 하는 이미지를 생성

     

    1️⃣ 도커 파일 생성 

    도커파일은 yaml(야믈)파일로 만들어진다 

    yaml파일 명령어는 ARG(환경변수), From(베이스이미지), CMD(명령 실행) 등이 있는데 위의 공식 홈페이지에 더 많이 있다. 이번은 간략하게 3가지 명령어 만을 사용하여 실습!

     

    * 도커파일

    FROM : httpd:latest 이미지를 베이스로

    COPY : host 현재 경로의 index.html 파일을 컨테이너의 /usr/local/apache2/htdocs/index.html의 경로로 복사한다

    EXPOSE : 그리고 80포트를 연다

     

     


     

    2️⃣ 도커 이미지 생성 

    build 명령어로 이미지를 생성하며 새로 생성하는 이미지는 -t 옵션 (tag)을 통해 이미지 이름이 설정되고 

    경로 경우 현재 경로로 부터의 위치를 말하는 것으로 이미 그 위치에 있었기 때문에 . 으로 표현

    docker build -t 이미지이름 경로

    보면 설정한 태그로 이미지가 생성된걸 확인할 수 있다

     


    3️⃣ 커스텀한 이미지 실행 

    포트포워딩해서 컨테이너 생성 및 실행
    확인

    볼륨 마운트 과정없이 바로 커스텀 index.html로 적용된 걸 볼 수 있다.

     

    이런식으로 만든 것을 docker hub에 올려 언제든 다운받아 사용도 가능하다.

     

     

     


    첫번째 강의 끝


    1. 포트포워딩이란?
      외부 주소와 내부 주소를 이어주는 것 [본문으로]

     

    📌 공부 이유

    실전 프로젝트하면서 백엔드를 고도화하면서 여러기술에 도전해보고 있다. Docker도 그 중 하나로, 이름만 알고 뭐하는 녀석인지 전혀 몰랐기 때문에 먼저 개념을 공부해보고 실습하면서 익혀보려고 한다.

    + 원티드 챌린지 23년 4월 Docker 강사 고병현님의 강의 내용을 참고하여 더 추가했습니다.

     

     

    📌 Docker 왜 써요? 

    나만 해도 윈도우 OS를 쓰고 있지만 서버는 AWS Ubuntu를 사용하고 있다. 개발환경과 배포환경이 전혀 다르다.

    그래서 로컬로 개발하고 로컬환경에서 돌리면 잘 돌아가는데 서버에 올리면 예상치 못한 오류를 접할 때가 많다. 그러면 개발환경을 서버에 맞춰주고 로컬에서 개발하면 서버에서 오류가 나는게 훨씬 줄어들겠지? 싶지만 평소 사용하는 환경은 Windows를 쓰기 때문에 이걸 밀고 Ubuntu로 사용할 수는 없다 (컴퓨터가 하나 더있음 모를까 ㅠ) 

    그리고 이번엔 Ubuntu지만 다음에 다른 환경이면? 그때 마다 개발 컴퓨터 OS를 밀고 새로 환경을 맞춰줘야 줘야 한다? 말도 안된다. 그리고 개발 컴퓨터에서 하나의 프로그램만 개발하는 것이 아니지 않나.

    또한 고성능으로 서버를 열어두었을 때, 서버 활용성이 100인데 하나의 어플리케이션이 10이면 나머지 90을 사용 못하면 얼마나 비효율 적일까! 그래서 등장한 기술이 가상화 기술이다. 

     

     

     

    📌 가상화 기술은 또 뭐지 ?

    고성능 서버에 하나의 어플리케이션만 쓰는 것이 낭비가 되어 이를 어떻게 효율적으로 사용할 수 있을까 하는 물음에서 탄생한 기술이다. 

    하나의 물리적인 컴퓨터 자원(CPU, 메모리, 저장장치 등)을 가상적으로 분할하여 여러 개의 가상 컴퓨터 환경을 만들어 내는 기술이다. 이를 통해 물리적인 컴퓨터 자원을 더욱 효율적으로 사용할 수 있으며, 서버나 애플리케이션 등을 운영하는데 있어 유연성과 안정성을 제공한다. 

     

    최초의 가상화 기술에서는 Hypervisor [각주:1] 를 사용해 가상 머신마다 Guest OS를 만들어 물리적으로는 하나의 디바이스지만 여러 디바이스처럼 돌릴 수 있도록 했다. 가상 머신(VM / Virtual Machine)을 사용하기 위해 OS위에 또다른 OS환경을 설치하는 방식으로 이전 가상화 기술 중 대표적으로 VMware가 있었다. (VMware를 사용해 본 기억히 새록새록.. )

    Virtual Machine 가상화 기술 방식

    아무튼 기존 컴퓨터의 OS도 무거운데, 새로운 환경을 맞춰주기 위해 OS위에 OS를 다시 설치하는 방식은 용량과 속도에 많은 영향을 미쳤다. 게다가 독립적인 플랫폼을 하나하나 증가 시킬때 마다 또 OS를 설치해야 하니 너무 비효율적이기까지 하다.

     

    그래서 등장한 것이 컨테이너 기술이고 이 기술을 제공하는 소프트웨어 중 현재 가장 유명한 것이 바로 Docker다.

    Container 가상화 기술 : Guest OS가 모두 빠진 모습

    Docker는 이전 가상 머신과 달리 OS 위에 OS를 올리는 방식이 아닌 library와 bin(실행파일)파일들만을 올려 가볍고 기존 호스트OS를 공유하기 때문에 별도의 설치 또한 필요가 없어서 확장성과 시간 절약에도 좋다. 게다가 무거운 OS가 단 하나이니 속력 또한 빠르다. 

     

     

     

    📌 컨테이너(Container)는 뭐지? 

    컨테이너는 개별 소프트웨어의 실행에 필요한 실행환경을 독립적으로 운용할 수 있도록 다른 환경으로 부터의 간섭을 막고 독립 실행을 확보해 주는 운영체계 수준의 격리 기술로 가상화 기술 중 하나이다. 한마디로 호스트 운영체제 위에 여러개 격리된 환경을 생성해 소프트웨어 하나가 간섭받지 않고 잘 돌아갈 수 있게 격리해주는 기술이라 할 수 있다. 리눅스 커널 기능을 사용하여 만들어졌고 프로세스 단위의 격리환경을 제공한다. [각주:2]

     

     

     

    📌 그래서 Docker란? 

    Docker 단어 자체의 의미는 부두에서 컨테이너를 다루는 노동자를 의미한다.

     

    Docker란 이름은 원래 의미와 마찬가지로 "컨테이너"를 관리한다는 의미에서 붙인 이름인 듯 하다. 이처럼 Docker는 서버 혹의 호스트 컴퓨터에서 컨테이너를 관리해 편의성을 제공하는데 정확한 개념은 컨테이너 기반의 오픈소스 가상화 플랫폼이다.

     

    하나의 호스트 OS안에서 애플리케이션을 분리하여 컨테이너로 추상화 시키고(프로세스를 격리, 독립적 실행가능하게) 여러 컨테이너를 동시에 실행도 가능하게 한다. 또한 컨테이너의 라이프 사이클을 관리하고 어떤 프로그램도 컨테이너로 추상화 할 수 있고 어디서든 실행 할 수 있게 해준다. 인프라를 어플리케이션 관리하는 것 처럼 관리할 수도 있어, 신속하게 코드를 배포할 수 있도록 한다. 

     

    * 도커 요약 :

    • 컨테이너 기반의 가상화 도구
      • 리눅스 컨테이너 기술인 LXC(Linux Containers) 기반
    • 애플리케이션을 컨테이너 단위로 격리하여 실행하고 배포하는 기술
    • 다양한 운영체제에서 사용가능
    • 컨테이너화된 어플리케이션에 대한 빌드, 배포, 관리 등의 다양한 기능 제공

    ➡ 위 기능 통해 어플리케이션을 빠르게 개발, 효율적으로 배포, 관리 가능

     

     

    Docker: Accelerated, Containerized Application Development

    Docker is a platform designed to help developers build, share, and run modern applications. We handle the tedious setup, so you can focus on the code.

    www.docker.com

     

     

    📌 어떻게 사용?

    그럼 어떻게 컨테이너를 만들지?

    도커에서는 이미지 라는 개념이 있다. 

    이미지는 컨테이너 실행에 필요한 파일과 설정값을 포함하고 있는 것으로 변하지 않는 값을 가지고 있다.

    (필요한 프로그램, 라이브러리, 소스 등 포함으로 읽기 전용이다)

    컨테이너를 실행 시키기 위한 모든 정보를 가지고 있기 때문에 이 이미지를 다운 받아 컨테이너를 생성한다. 

    같은 이미지에서 여러 컨테이너를 생성하는 것도 가능한데,  변하는 값은 모두 컨테이너가 가지고 있기 때문에 어떤 하나의 컨테이너가 사라져도, 모든 컨테이너가 사라져도, 이미지는 처음 그 값 그대로를 유지한다.

     

    이미지는 누구나가 배포할 수 있고 다른 사람의 배포한 이미지를 가져다 쓸 수 있다.

    허브에 배포되어있는 이미지 중 신뢰도가 높은 걸 다운받아 사용한다면 문제 없는 환경이라는 뜻일 거고 이를 받아 컨테이너를 생성해 배포해 본다면 문제가 어디있는지도 확인할 수 있다.

    물론 자신의 배포환경과 동일하게 구성한 이미지를 배포 및 관리하는 것도 가능하다.

     

    이렇게 이미지를 도커에 실행시킨 뒤 사용하면 되는데, 이미지가 실행된 상태가 바로 컨테이너 라고 한다. 

     

     

     

    📌 Docker 구조는?

    출처 : https://docs.docker.com/get-started/overview/

    1️⃣ Docker Host

    Docker가 깔려있는 디바이스 (현재 우리 컴퓨터)

     

    2️⃣ Docker daemon (=dockerd)

    • 도커 엔진[각주:3]의 핵심 구성 요소
    • 도커 호스트에서 컨테이너를 관리하고 실행하는 역할 (컨테이너 생성, 시작, 중지, 삭제 등의 작업수행)
    • 컨테이너 이미지 관리
    • 외부에서 이미지 다운 및 빌드하는 작업 수행

    3️⃣ Docker Client

    • Docker와 상호 작용
    • Docker 명령어를 사용하면 Docker daemon으로 보내 실행

    4️⃣ Docker Object 

    • Docker Image
      • 도커 컨테이너를 만들기 위한 읽기 전용 템플릿
    • Docker Container
      • 한 도커 이미지의 실행 가능한 인스턴스
      • 애플리케이션을 실행하기 위한 모든 파일과 설정 정보를 포함하는 패키지

    5️⃣ Docker Registries

    • 도커 이미지를 관리하고 저장하는 곳
    • 디폴트 레지스트리로 누구나 접근 가능한 공개형 저장소인 Docker hub가 존재한다. 
     

    Docker Hub Container Image Library | App Containerization

    Deliver your business through Docker Hub Package and publish apps and plugins as containers in Docker Hub for easy download and deployment by millions of Docker users worldwide.

    hub.docker.com

     

     

    📌 공부 영상 및 자료 :

     

    컨테이너 및 도커 개념정리

    소프트웨어는 OS와 라이브러리에 의존성을 뛴다. 그러므로 하나의 컴퓨터에서 성격이 다른(OS,라이브러리 버전이 다른) 소프트웨어를 한번에 실행할 때 어려움을 가질 수 있고 관련된 구성을 관

    velog.io

     

    Docker 개념과 Architecture 정리

    1. Docker docker는 컨테이너 기반 가상화 도구이다. 기존에 사용하던 가상 머신(VM)은 사용하기 위해서 항상 OS를 설치해야 했고, 이미지 안에 OS가 포함되어 있기 때문에 용량이 매우 크고 속도도 느

    www.leafcats.com

     

     

    1. Hypervisor (하이퍼바이저)
      1️⃣ 가상 머신을 생성하고 구동하는 소프트웨어
      2️⃣ OS에 자원을 할당 및 조율
      3️⃣ OS들의 요청을 번역하여 하드웨어에 전달 [본문으로]
    2. 그래서 Linux만 되나?
      리눅스에 국한되는 것은 아니고 Windows나 Mac OS에서 Hyper-V나 xhyve라는 기술로 가상 머신을 생성해 Linux환경을 실행할 수 있게 한다. [본문으로]
    3. 도커 엔진? 컨테이너 엔진?
      컨테이너를 생성하고 제어하는 컨테이너 엔진 기능을 도커에서 구현한 걸 도커 엔진이라고 한다 [본문으로]

    문제

    📌 MySQL 으로 풀이

     

    📌 문제 링크 :

     

    프로그래머스

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

    programmers.co.kr

     

    📌 문제 설명 :

    USER_INFO 테이블과 ONLINE_SALE 테이블에서 년, 월, 성별 별로 상품을 구매한 회원수를 집계하는 SQL문을 작성해주세요. 결과는 년, 월, 성별을 기준으로 오름차순 정렬해주세요. 이때, 성별 정보가 없는 경우 결과에서 제외해주세요.

     

    📌 테이블

    다음은 어느 의류 쇼핑몰에 가입한 회원 정보를 담은 USER_INFO 테이블과 온라인 상품 판매 정보를 담은 ONLINE_SALE 테이블 입니다.USER_INFO 테이블은 아래와 같은 구조로 되어있으며 USER_ID, GENDER, AGE, JOINED는 각각 회원 ID, 성별, 나이, 가입일을 나타냅니다.

    USER_ID INTEGER FALSE
    GENDER TINYINT(1) TRUE
    AGE INTEGER TRUE
    JOINED DATE FALSE

    GENDER 컬럼은 비어있거나 0 또는 1의 값을 가지며 0인 경우 남자를, 1인 경우는 여자를 나타냅니다.

    ONLINE_SALE 테이블은 아래와 같은 구조로 되어있으며, ONLINE_SALE_ID, USER_ID, PRODUCT_ID, SALES_AMOUNT, SALES_DATE는 각각 온라인 상품 판매 ID, 회원 ID, 상품 ID, 판매량, 판매일을 나타냅니다.

    ONLINE_SALE_ID INTEGER FALSE
    USER_ID INTEGER FALSE
    PRODUCT_ID INTEGER FALSE
    SALES_AMOUNT INTEGER FALSE
    SALES_DATE DATE FALSE

    동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다.


    풀이

    추측) 

    분류하고자 하는 3개 컬럼과 회원 아이디 만을 질의하는 쿼리 먼저하고 이를 분류 컬럼으로 Group by해줘서 count하면 될듯하다. 

     

    쿼리) 

    * 1차) 성공

    SELECT A.YEAR, A.MONTH, A.GENDER, COUNT(A.USER_ID) AS USERS
    FROM
        (SELECT 
            YEAR(SALES_DATE) AS YEAR, 
            MONTH(SALES_DATE) AS MONTH,
            GENDER,
            U.USER_ID
        FROM ONLINE_SALE AS O
        LEFT OUTER JOIN USER_INFO AS U
        ON O.USER_ID = U.USER_ID
        WHERE U.GENDER IS NOT NULL
        GROUP BY YEAR, MONTH, GENDER, U.USER_ID) AS A
    GROUP BY A.YEAR, A.MONTH, A.GENDER
    ORDER BY YEAR ASC, MONTH ASC, GENDER ASC

    * 2차) 성공

    SELECT A.YEAR, A.MONTH, A.GENDER, COUNT(A.USER_ID) AS USERS
    FROM
        (SELECT DISTINCT
            YEAR(SALES_DATE) AS YEAR, 
            MONTH(SALES_DATE) AS MONTH,
            GENDER,
            U.USER_ID
        FROM ONLINE_SALE AS O
        LEFT OUTER JOIN USER_INFO AS U
        ON O.USER_ID = U.USER_ID
        WHERE U.GENDER IS NOT NULL) AS A
    GROUP BY A.YEAR, A.MONTH, A.GENDER
    ORDER BY YEAR ASC, MONTH ASC, GENDER ASC

     

    리뷰) 

    + 같은 달의 중복 구매 회원을 제외 할 필요도 있었다

     

    그리고 좀더 효율적으로 바꾸고 싶어!

    1차에서의 Group by를 제외하고 Distinct로 중복을 제거하는 방식으로 같은 달에 여러번 구매한 회원수를 제외했다.

    이러니까 여러모로 공수가 많이 드는 Group by를 하나 제외할 수 있었음!

    문제

    📌 MySQL 로 풀이

     

    📌 문제 링크 :

     

    프로그래머스

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

    programmers.co.kr

     

    📌 문제 설명 :

    CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하여 자동차 ID와 AVAILABILITY 리스트를 출력하는 SQL문을 작성해주세요. 이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시해주시고 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.

     

    📌 테이블 :

    다음은 어느 자동차 대여 회사의 자동차 대여 기록 정보를 담은 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블입니다. CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블은 아래와 같은 구조로 되어있으며, HISTORY_ID, CAR_ID, START_DATE, END_DATE 는 각각 자동차 대여 기록 ID, 자동차 ID, 대여 시작일, 대여 종료일을 나타냅니다.

    HISTORY_ID INTEGER FALSE
    CAR_ID INTEGER FALSE
    START_DATE DATE FALSE
    END_DATE DATE FALSE

     

     


    풀이

    쿼리) 

    SELECT 
        C.CAR_ID,
        CASE WHEN A.CAR_ID IS NULL THEN '대여 가능' ELSE '대여중' END AS AVAILABILITY
    FROM (SELECT DISTINCT CAR_ID 
          FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY) AS C
    LEFT OUTER JOIN 
        (SELECT DISTINCT CAR_ID
        FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
        WHERE '2022-10-16' BETWEEN START_DATE AND END_DATE) AS A
    ON C.CAR_ID = A.CAR_ID
    ORDER BY C.CAR_ID DESC

     

    리뷰) 

    특정 날짜가 어느 날짜 사이에 있는지 알아보려면 BETWEEN이나 부등호를 써야한다.

    그리고 그것보다 더 중요했던 건

    데이터베이스는 데이터가 어떤식으로 쌓여있는지 잘 파악하여야 한다는 걸 알려준 문제였다.

    렌트 내역을 쌓아놓은 테이블이라 같은 car_id가 렌트되어진 내역이 여럿 존재할 수 있다는 것을 생각했어야했다.

     

    그래서 distinct로 중복을 제거한 C와 2022-10-16일에 대여중인 car_id만 질의하여 리턴한 테이블을 join하는데

    이때 모든 car_id에 대해 대여중인 car_id가 1:1 매칭이 안되므로 모든 car_id를 가진 C를 기준으로 left outer join하였고,

    A의 car_id가 null이면 대여가능 아니면 대여중으로 반환해준다.

    문제

    📌 MySQL로 풀이

     

    📌 문제 링크 :

     

    프로그래머스

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

    programmers.co.kr

     

     

    📌 문제 설명 :

    USED_GOODS_BOARD와 USED_GOODS_USER 테이블에서 중고 거래 게시물을 3건 이상 등록한 사용자의 사용자 ID, 닉네임, 전체주소, 전화번호를 조회하는 SQL문을 작성해주세요. 이때, 전체 주소는 시, 도로명 주소, 상세 주소가 함께 출력되도록 해주시고, 전화번호의 경우 xxx-xxxx-xxxx 같은 형태로 하이픈 문자열(-)을 삽입하여 출력해주세요. 결과는 회원 ID를 기준으로 내림차순 정렬해주세요.

     

    📌 테이블 :

    다음은 중고 거래 게시판 정보를 담은 USED_GOODS_BOARD 테이블과 중고 거래 게시판 첨부파일 정보를 담은 USED_GOODS_FILE 테이블입니다. USED_GOODS_BOARD 테이블은 다음과 같으며 BOARD_ID, WRITER_ID, TITLE, CONTENTS, PRICE, CREATED_DATE, STATUS, VIEWS는 게시글 ID, 작성자 ID, 게시글 제목, 게시글 내용, 가격, 작성일, 거래상태, 조회수를 의미합니다.

    BOARD_ID VARCHAR(5) FALSE
    WRITER_ID VARCHAR(50) FALSE
    TITLE VARCHAR(100) FALSE
    CONTENTS VARCHAR(1000) FALSE
    PRICE NUMBER FALSE
    CREATED_DATE DATE FALSE
    STATUS VARCHAR(10) FALSE
    VIEWS NUMBER FALSE

    USED_GOODS_USER 테이블은 다음과 같으며 USER_ID, NICKNAME, CITY, STREET_ADDRESS1, STREET_ADDRESS2, TLNO는 각각 회원 ID, 닉네임, 시, 도로명 주소, 상세 주소, 전화번호를 의미합니다.

    USER_ID VARCHAR(50) FALSE
    NICKANME VARCHAR(100) FALSE
    CITY VARCHAR(100) FALSE
    STREET_ADDRESS1 VARCHAR(100) FALSE
    STREET_ADDRESS2 VARCHAR(100) TRUE
    TLNO VARCHAR(20) FALSE

     


    풀이

    추측) 

    이번 문제는 데이터를 가공할 수 있는 함수를 알아야 풀 수 있었던 문제

     

    쿼리) 

    SELECT 
        USER_ID, 
        NICKNAME, 
        CONCAT(CITY, ' ' , STREET_ADDRESS1, ' ', STREET_ADDRESS2) AS '전체주소',
        CONCAT(LEFT(TLNO,3), '-', MID(TLNO, 4, 4), '-', RIGHT(TLNO,4)) AS '전화번호'
    FROM USED_GOODS_USER 
    WHERE USER_ID IN (SELECT WRITER_ID
                        FROM USED_GOODS_BOARD 
                        GROUP BY WRITER_ID
                        HAVING COUNT(WRITER_ID) >= 3)
    ORDER BY USER_ID DESC

     

    리뷰) 

    CONCAT함수는 여러 문자열 또는 컬럼 값을 합쳐서 조회할 수 있도록 하는 함수이다. 

    기본 형식은 

    CONCAT(문자열1|컬럼1 , 문자열2|컬럼2 [, 문자열3|컬럼3 ....]) AS 칼럼명

    그러니까 문자열과 문자열, 컬럼과 컬럼 뿐만 아니라

    CONCAT ('제 닉네임은 ', NICKNAME, '입니다') AS '닉네임' 

    식으로 문자열과 컬럼을 섞어 출력도 가능하다

    + Recent posts