제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(GROUP BY)입니다.

카테고리 별 도서 판매량 집계하기

SELECT 
    B.CATEGORY,
    SUM(S.SALES)
FROM BOOK B JOIN (
    SELECT *
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
) S
ON B.BOOK_ID = S.BOOK_ID
GROUP BY B.CATEGORY
ORDER BY B.CATEGORY
  • 2022년 1월에 판매된 레코드를 조회합니다. (테이블 S)
(
    SELECT *
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
) S
  • BOOK 테이블과 BOOK_ID를 기준으로 JOIN합니다.
    (FROM BOOK B JOIN (...) S ON B.BOOK_ID = S.BOOK_ID)
  • 카테고리를 기준으로 GROUP BY 해줍니다.
    (GROUP BY B.CATEGORY)
  • 판매량의 합계를 위해 SUM 함수를 사용하고 CATEGORY를 오름차순으로 정렬합니다.

저자 별 카테고리 별 매출액 집계하기

SELECT 
    A.AUTHOR_ID, 
    A.AUTHOR_NAME, 
    O.CATEGORY, 
    O.TOTAL_SALES
FROM AUTHOR A JOIN (
    SELECT 
        B.AUTHOR_ID, 
        B.CATEGORY, 
        SUM(B.PRICE * BS.SALES) AS TOTAL_SALES
    FROM BOOK B JOIN (
        SELECT BOOK_ID, SUM(SALES) AS SALES
        FROM BOOK_SALES
        WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
        GROUP BY BOOK_ID
    )BS ON B.BOOK_ID = BS.BOOK_ID
    GROUP BY AUTHOR_ID, B.CATEGORY
) O ON A.AUTHOR_ID = O.AUTHOR_ID
ORDER BY AUTHOR_ID, CATEGORY DESC
  • 2022년 1월에 판매된 책의 BOOK_ID와 판매량의 합계를 조회합니다.(테이블 BS)
(
    SELECT BOOK_ID, SUM(SALES) AS SALES
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
    GROUP BY BOOK_ID
)BS
  • BS 테이블과 BOOK 테이블과 BOOK_ID를 기준으로 조인합니다.
    (FROM BOOK B JOIN (...) BS ON B.BOOK_ID = BS.BOOK_ID)
  • 저자별, 카테고리별 그룹화를 해줍니다.
    (GROUP BY AUTHOR_ID, B.CATEGORY)
  • 판매량과 가격을 기준으로 TOTAL_SLAES를 구합니다.
    (SUM(B.PRICE * BS.SALES) AS TOTAL_SALES)
  • 해당 결과를 구한 테이블 O와 AUTHOR 테이블을 AUTHOR_ID를 기준으로 조인합니다.
    (FROM AUTHOR A JOIN (...) O ON A.AUTHOR_ID = O.AUTHOR_ID)
  • AUTHOR_ID를 오름차순으로, 카테고리를 내림차순으로 정렬합니다.

식품분류별 가장 비싼 식품의 정보 조회하기

SELECT
    F1.CATEGORY,
    F2.MAX_PRICE,
    F1.PRODUCT_NAME
FROM FOOD_PRODUCT F1 JOIN (
    SELECT
        CATEGORY,
        MAX(PRICE) AS MAX_PRICE
    FROM FOOD_PRODUCT F2
    GROUP BY CATEGORY
    HAVING CATEGORY IN ('과자', '국', '김치', '식용유')
)F2 ON F1.PRICE = F2.MAX_PRICE AND F1.CATEGORY IN ('과자', '국', '김치', '식용유')
ORDER BY F2.MAX_PRICE DESC
  • 식품 분류를 통해 그룹화를 합니다.
    (GROUP BY CATEGORY)
  • 식품 분류에는 '과자', '국', '김치', '식용유' 만 가능하기에 그룹화에서 HAVING절을 이용합니다.
    (HAVING CATEGORY IN ('과자', '국', '김치', '식용유'))
  • 그룹화한 테이블에서 각 식품 분류 별 가장 가격이 높은 필드를 선택하고 F2라는 테이블의 별칭을 설정합니다.
(
    SELECT
        CATEGORY,
        MAX(PRICE) AS MAX_PRICE
    FROM FOOD_PRODUCT F2
    GROUP BY CATEGORY
    HAVING CATEGORY IN ('과자', '국', '김치', '식용유')
)F2
  • FOOD_PRODUCT와 F2 테이블에서 가장 비싼 가격과 일치하고 식품 분류를 기준으로 JOIN합니다.
    (FROM FOOD_PRODUCT F1 JOIN (...) F2 ON F1.PRICE = F2.MAX_PRICE AND
    F1.CATEGORY IN ('과자', '국', '김치', '식용유'))
  • 식품 가격을 기준으로 내림차순 정렬합니다.

즐겨찾기가 가장 많은 식당 정보 출력하기

SELECT
    B.FOOD_TYPE,
    A.REST_ID,
    A.REST_NAME,
    B.FAVORITES
FROM REST_INFO A JOIN (
    SELECT
        FOOD_TYPE,
        MAX(FAVORITES) AS FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)B ON A.FAVORITES = B.FAVORITES AND A.FOOD_TYPE = B.FOOD_TYPE
ORDER BY FOOD_TYPE DESC
  • 음식 종류를 기준으로 그룹화를 진행한 후 즐겨찾기가 가장 많은 음식 종류를 구한 테이블을 B라고 지정합니다.
(
    SELECT
        FOOD_TYPE,
        MAX(FAVORITES) AS FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)B
  • REST_INFO 테이블과 B 테이블의 즐겨찾기 수와 음식 종류를 기준으로 JOIN합니다.
    (FROM REST_INFO A JOIN (...)B ON A.FAVORITES = B.FAVORITES AND A.FOOD_TYPE = B.FOOD_TYPE)
  • 음식 종류를 기준으로 내림차순 정렬합니다.

자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기

SELECT
    CAR_ID,
    MAX(
            CASE WHEN '2022-10-16' BETWEEN TO_CHAR(START_DATE,'YYYY-MM-DD') AND TO_CHAR(END_DATE,'YYYY-MM-DD') THEN '대여중'
                 ELSE '대여 가능'
                END) AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC
  • CAR_ID를 기준으로 그룹화합니다.
    (GROUP BY CAR_ID)
  • 2022년 10월 16일을 기준으로 대여중인 차는 대여중, 대여중이지 않은 차는 대여 가능으로 표시하기 위해 CASE 절을 사용합니다.
    시작일자가 대여 가능보다 대여중이 우선적으로 선택하기 위해 MAX 함수를 사용합니다.
    (MAX(CASE WHEN '2022-10-16' BETWEEN TO_CHAR(START_DATE,'YYYY-MM-DD') AND TO_CHAR(END_DATE,'YYYY-MM-DD') THEN '대여중' ELSE '대여 가능' END) AS AVAILABILITY)
  • CAR_ID를 기준으로 내림차순 정렬합니다.

대여횟수가 많은 자동차들의 월별 대여 횟수 구하기

SELECT
    EXTRACT(MONTH FROM S.START_DATE) AS MONTH,  -- 월을 숫자로 바로 추출
    S.CAR_ID,
    COUNT(*) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY S
JOIN (
    SELECT 
        CAR_ID
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE TO_CHAR(START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
    GROUP BY CAR_ID
    HAVING COUNT(*) >= 5
) R ON S.CAR_ID = R.CAR_ID
WHERE TO_CHAR(S.START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
GROUP BY EXTRACT(MONTH FROM S.START_DATE), S.CAR_ID
ORDER BY EXTRACT(MONTH FROM S.START_DATE) ASC, S.CAR_ID DESC;
  • 2022년 8월부터 10월까지 대여횟수가 5회 이상인 자동차를 구하기 위해 CAR_ID를 기준으로 그룹화 한 후 HAVING 절을 통해 조건을 걸어 서브 테이블 R을 생성합니다.
(
    SELECT 
        CAR_ID
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE TO_CHAR(START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
    GROUP BY CAR_ID
    HAVING COUNT(*) >= 5
) R
  • CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 CAR_ID를 기준으로 R과 JOIN합니다.
    (FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY S JOIN (...) R ON S.CAR_ID = R.CAR_ID)
  • JOIN 조건에는 맞지만 START_DATE의 조건을 위해 한번 더 걸어줍니다.
    (WHERE TO_CHAR(S.START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10')
  • 대여 월과 CAR_ID를 기준으로 그룹화합니다.
    월을 구하는 방법에는 EXTRACT(MONTH FROM S.START_DATE)를 이용합니다. => 숫자만 추출하기 위함입니다.
    (GROUP BY EXTRACT(MONTH FROM S.START_DATE), S.CAR_ID)
  • 월을 기준으로 오름차순 정렬하고 자동차 ID를 기준으로 내림차순 정렬합니다.

자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기

SELECT
    CAR_TYPE,
    COUNT(*) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%통풍시트%' 
   OR OPTIONS LIKE '%열선시트%' 
   OR OPTIONS LIKE '%가죽시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE ASC;
  • OPTION이 '통풍시트', '열선시트', '가죽시트'를 구하기 위해 like절을 이용합니다. (OPTIONS가 VARCHAR로 이루어져있기 때문에 like 절을 통해 조회합니다)
    (WHERE OPTIONS LIKE '%통풍시트%' 
       OR OPTIONS LIKE '%열선시트%' 
       OR OPTIONS LIKE '%가죽시트%')
  • 자동차 종류 별로 묶기 위해 그룹화합니다.
    (GROUP BY CAR_TYPE)
  • 자동차 종류를 기준으로 오름차순 정렬합니다.

성분으로 구분한 아이스크림 총 주문량

SELECT
    I.INGREDIENT_TYPE,
    SUM(F.TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF F JOIN ICECREAM_INFO I
ON F.FLAVOR = I.FLAVOR
GROUP BY I.INGREDIENT_TYPE
ORDER BY TOTAL_ORDER ASC;
  • 상반기 주문정보와 아이스크림 정보를 FLAVOR를 통해 JOIN합니다.
    (FROM FIRST_HALF F JOIN ICECREAM_INFO I ON F.FLAVOR = I.FLAVOR)
  • 아이스크림 맛을 기준으로 그룹화합니다.
    (GROUP BY I.INGREDIENT_TYPE)
  • 상반기 아이스크림 총 주문량의 합을 위해 SUM 함수를 사용하고 총 주문량를 기준으로 오름차순 정렬합니다.

진료과별 총 예약 횟수 출력하기

SELECT
    MCDP_CD AS "진료과 코드", 
    COUNT(*) AS "5월예약건수"
FROM APPOINTMENT
WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05'
GROUP BY MCDP_CD
ORDER BY "5월예약건수", "진료과 코드"
  • 2022년 05월에 예약한 환자를 위해 테이블에 조건을 걸어줍니다.
    (WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05')
  • 진료과 별로 그룹화하기 위해 MCDP_CD를 기준으로 그룹화합니다.
    (GROUP BY MCDP_CD)
  • 예약 수를 구하기 위해 COUNT 함수를 사용하고 예약 수와 진료과 코드를 기준으로 오름차순 정렬합니다.

조건에 맞는 사용자와 총 거래금액 조회하기

SELECT
    U.USER_ID,
    U.NICKNAME,
    R.TOTAL_SALES
FROM USED_GOODS_USER U JOIN (
    SELECT
        WRITER_ID,
        SUM(PRICE) AS TOTAL_SALES
    FROM USED_GOODS_BOARD B
    WHERE B.STATUS = 'DONE'
    GROUP BY WRITER_ID
    HAVING SUM(PRICE) >= 700000
)R ON U.USER_ID = R.WRITER_ID
ORDER BY R.TOTAL_SALES
  • 완료된 중고거래에서 회원별 중고 물품을 판매한 총 금액이 70만원이 넘는 레코드를 조회하기 위해 서브 테이블 R을 생성합니다.
(
    SELECT
        WRITER_ID,
        SUM(PRICE) AS TOTAL_SALES
    FROM USED_GOODS_BOARD B
    WHERE B.STATUS = 'DONE'
    GROUP BY WRITER_ID
    HAVING SUM(PRICE) >= 700000
)R
  • USED_GOODS_BOARD B와 R에 회원 아이디를 기준으로 JOIN합니다.
    (FROM USED_GOODS_USER U JOIN (...)R ON U.USER_ID = R.WRITER_ID)
  • 총 판매액을 기준으로 오름차순 정렬합니다.
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(SUM, MAX, MIN)입니다.

가장 비싼 상품 구하기

SELECT
    MAX(PRICE) AS MAX_PRICE
FROM PRODUCT
  • MAX 함수를 사용하여 PRODUCT 테이블의 PRICE 중 가장 값이 비싼 가격을 조회합니다.

가격이 제일 비싼 식품의 정보 출력하기

-- 첫번째 방법
SELECT
    A.PRODUCT_ID,
    A.PRODUCT_NAME,
    A.PRODUCT_CD,
    A.CATEGORY,
    A.PRICE
FROM FOOD_PRODUCT A, (
    SELECT MAX(PRICE) AS MAX_PRICE
    FROM FOOD_PRODUCT
) B
WHERE A.PRICE = B.MAX_PRICE;

-- 두번째 방법
SELECT *
FROM FOOD_PRODUCT
ORDER BY PRICE DESC
FETCH NEXT 1 ROWS ONLY
  • 첫번째 방법
    • 가장 비싼 값을 구하여 natural join 합니다.
      (FROM FOOD_PRODUCT A, (
          SELECT MAX(PRICE) AS MAX_PRICE
          FROM FOOD_PRODUCT) B)
    • 이후 WHERE 절을 통해 비교하여 가장 비싼 가격을 가진 상품의 정보를 출력합니다.
      (WHERE A.PRICE = B.MAX_PRICE;)

  • 두번째 방법
    • PRICE를 기준으로 내림차순 정렬합니다.
      (ORDER BY PRICE DESC)
    • FETCH NEXT N ROWS 절을 이용하여 첫번째 레코드를 조회합니다.
      (FETCH NEXT 1 ROWS ONLY)

최대값 구하기

SELECT
    MAX(DATETIME) AS "시간"
FROM ANIMAL_INS;
  • DATETIME도 MAX를 사용할 수 있습니다.
    가장 최근에 들어온 동물이 가장 큰 값이므로 MAX함수를 사용합니다.
    (MAX(DATETIME) AS "시간")

최솟값 구하기

SELECT
    MIN(DATETIME) AS "시간"
FROM ANIMAL_INS;
  • DATETIME도 MIN를 사용할 수 있습니다.
    가장 먼저 들어온 동물이 가장 작은 값이므로 MIN함수를 사용합니다.
    (MIN(DATETIME) AS "시간")

동물 수 구하기

SELECT
    COUNT(*)
FROM ANIMAL_INS
  • 동물 보호소에 들어온 동물의 수를 조회하기 위해 COUNT함수를 사용합니다.
    (SELECT COUNT(*))

중복 제거하기

SELECT
    COUNT(DISTINCT NAME)
FROM ANIMAL_INS
  • 동물 보호소에 들어온 동물의 이름을 조회하기 위해 COUNT함수를 사용합니다.
    또 중복된 이름은 하나로 쳐야하므로 DISTINCT 키워드를 사용합니다.
    (SELECT COUNT(DISTINCT NAME))
  • DISTINCT는 NULL을 세지 않습니다.

조건에 맞는 아이템들의 가격의 총합 구하기

SELECT
    SUM(PRICE) AS TOTAL_PRICE
FROM ITEM_INFO
WHERE RARITY = 'LEGEND'
  • 희귀도가 LEGEND인 ITEM을 조회합니다.
    (WHERE RARITY = 'LEGEND')
  • 해당 아이템의 가격의 총합을 구합니다.
    (SELECT SUM(PRICE) AS TOTAL_PRICE)

물고기 종류 별 대어찾기

SELECT 
    F1.ID,
    FNI.FISH_NAME,
    F1.LENGTH
FROM 
    FISH_INFO F1
JOIN 
    FISH_NAME_INFO FNI ON F1.FISH_TYPE = FNI.FISH_TYPE
JOIN 
    (SELECT FISH_TYPE, MAX(LENGTH) AS MAX_LENGTH
     FROM FISH_INFO
     WHERE LENGTH IS NOT NULL
     GROUP BY FISH_TYPE) AS F2
     ON F1.FISH_TYPE = F2.FISH_TYPE AND F1.LENGTH = F2.MAX_LENGTH
ORDER BY 
    F1.ID ASC;
  • FISH_INFO와 FISH_NAME_INFO를 FISH_TYPE을 기준으로 조인합니다.
    (FROM FISH_INFO F1 JOIN FISH_NAME_INFO FNI ON F1.FISH_TYPE = FNI.FISH_TYPE)
  • 물고기 종류 별로 묶어야 하기에 GROUP BY를 FISH_TYPE으로 지정한 후, FISH_TYPE에 따라 가장 큰 LENGTH를 조회합니다.
    이후 FISH_TYPE과 LENGTH를 통해 조인합니다.
JOIN (
    SELECT FISH_TYPE, MAX(LENGTH) AS MAX_LENGTH
     FROM FISH_INFO
     WHERE LENGTH IS NOT NULL
     GROUP BY FISH_TYPE
    ) AS F2 ON F1.FISH_TYPE = F2.FISH_TYPE AND F1.LENGTH = F2.MAX_LENGTH
  • 물고기의 ID를 통해 오름차순 정렬합니다.

잡은 물고기 중 가장 큰 물고기의 길이 구하기

SELECT
    CONCAT(MAX(LENGTH), "cm") AS MAX_LENGTH
FROM FISH_INFO;
  • 가장 큰 물고기의 길이를 구하기 위해 MAX 함수를 사용하고 문자열의 더하기를 위한 CONCAT 함수를 사용합니다.
    (SELECT CONCAT(MAX(LENGTH), "cm") AS MAX_LENGTH)

연도별 대장균 크기의 편차 구하기

SELECT
    Year(E.DIFFERENTIATION_DATE) AS YEAR,
    ABS(E.SIZE_OF_COLONY - R.MAX_SIZE) AS YEAR_DEV,
    E.ID
FROM
    ECOLI_DATA E
JOIN (
    SELECT
        Year(DIFFERENTIATION_DATE) AS YEAR,
        MAX(SIZE_OF_COLONY) AS MAX_SIZE
    FROM ECOLI_DATA
    GROUP BY YEAR
) R ON R.YEAR = Year(E.DIFFERENTIATION_DATE)
ORDER BY
    R.YEAR ASC,
    ABS(E.SIZE_OF_COLONY - R.MAX_SIZE) ASC;
  • 연도를 구하기 위해 YEAR 함수를 사용하고 연도에 따른 가장 큰 대장균 크기를 구하기 위한 테이블 R을 구합니다.
(
    SELECT
        Year(DIFFERENTIATION_DATE) AS YEAR,
        MAX(SIZE_OF_COLONY) AS MAX_SIZE
    FROM ECOLI_DATA
    GROUP BY YEAR
) R
  • 해당 년도의 가장 큰 대장균과의 편차를 구하기 위해 YEAR을 통해 JOIN을 합니다.
    (FROM ECOLI_DATA E JOIN (...) ON R.YEAR = Year(E.DIFFERENTIATION_DATE))
  • 편차의 절댓값을 위해 ABS 함수를 사용합니다.
    (ABS(E.SIZE_OF_COLONY - R.MAX_SIZE) AS YEAR_DEV)
  • 연도에 대해 오름차순 정렬하고 크기 편차에 대해 오름차순으로 정렬합니다.
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit입니다.

업그레이드 된 아이템 구하기

SELECT
    E.ITEM_ID,
    E.ITEM_NAME,
    E.RARITY
FROM ITEM_INFO E JOIN (
    SELECT 
        T.ITEM_ID
    FROM ITEM_TREE T JOIN (
            SELECT
                *
            FROM ITEM_INFO
            WHERE RARITY = 'RARE'
        ) I
    ON T.PARENT_ITEM_ID = I.ITEM_ID
) R
ON E.ITEM_ID = R.ITEM_ID
ORDER BY R.ITEM_ID DESC
  • ITEM_INFO 테이블에서 ITEM이 RARE인 ITEM의 ITEM_ID와 ITEM_TREE에서 PARRENT_ITEM_ID를 기준으로 조인합니다.
FROM ITEM_TREE T JOIN (
        SELECT
            *
        FROM ITEM_INFO
        WHERE RARITY = 'RARE'
    ) I
ON T.PARENT_ITEM_ID = I.ITEM_ID
  • 다시 ITEM_INFO와 ITEM_ID를 기준으로 조인합니다. 자식 아이템의 RARITY를 확인하기 위함입니다.
FROM ITEM_INFO E JOIN (
    SELECT 
        T.ITEM_ID
    FROM ITEM_TREE T JOIN (
            SELECT
                *
            FROM ITEM_INFO
            WHERE RARITY = 'RARE'
        ) I
    ON T.PARENT_ITEM_ID = I.ITEM_ID
) R
ON E.ITEM_ID = R.ITEM_ID
  • ITEM_ID를 기준으로 내림차순 정렬합니다.

Python 개발자 찾기

SELECT
    ID,
    EMAIL,
    FIRST_NAME,
    LAST_NAME
FROM DEVELOPER_INFOS
WHERE SKILL_1 = 'Python' OR SKILL_2 = 'Python' OR SKILL_3 = 'Python'
ORDER BY ID ASC
  • SKILL이 Python인 개발자를 찾고 ID를 기준으로 오름차순 정렬합니다.
    (WHERE SKILL_1 = 'Python' OR SKILL_2 = 'Python' OR SKILL_3 = 'Python')

조건에 맞는 개발자 찾기

SELECT 
    DISTINCT D.ID, 
    D.EMAIL, 
    D.FIRST_NAME, 
    D.LAST_NAME
FROM DEVELOPERS D
JOIN SKILLCODES S ON (D.SKILL_CODE & S.CODE) > 0
WHERE S.NAME IN ('Python', 'C#')
ORDER BY D.ID ASC;
  • SKILLCODES에 NAME이 Python과 C#인 레코드를 조회합니다.
    (WHERE S.NAME IN ('Python', 'C#'))
  • DEVELOPERS의 SKILL_CODE와 S의 CODE를 비트연산(&)을 통해 공통된 비트가 있는 레코드를 조인합니다.
    (FROM DEVELOPERS D JOIN SKILLCODES S ON (D.SKILL_CODE & S.CODE) > 0)
  • ID를 기준으로 오름차순 정렬합니다.

잔챙이 잡은 수 구하기

SELECT 
    COUNT(*) AS FISH_COUNT
FROM FISH_INFO
WHERE LENGTH is null;
  • 10 cm 이하인 물고기를 조회합니다.
    (WHERE LENGTH is null;)

가장 큰 물고기 10마리 구하기

SELECT 
    ID, 
    IFNULL(LENGTH, 10) AS LENGTH
FROM (
    SELECT 
        ID, 
        LENGTH, 
        ROW_NUMBER() OVER (ORDER BY LENGTH DESC, ID ASC) AS ROWNUM
    FROM FISH_INFO
) AS temp
WHERE ROWNUM <= 10
ORDER BY LENGTH DESC, ID ASC;
  • 생선의 길이와 아이디를 기준으로 ROW_NUMBER를 조회합니다.
SELECT 
        ID, 
        LENGTH, 
        ROW_NUMBER() OVER (ORDER BY LENGTH DESC, ID ASC) AS ROWNUM
    FROM FISH_INFO
  • ROWNUM이 10보다 작은 레코드를 조회합니다.
    (WHERE ROWNUM <= 10)
  • LENGTH가 null이면 10으로 치환합니다.
    (IFNULL(LENGTH, 10) AS LENGTH)
  • 생선 길이(내림차순)와 아이디(오름차순)를 기준으로 정렬합니다.

특정 물고기를 잡은 총 수 구하기

SELECT
    COUNT(*) AS FISH_COUNT
FROM FISH_INFO AS I JOIN FISH_NAME_INFO AS N
ON I.FISH_TYPE = N.FISH_TYPE
WHERE N.FISH_NAME = 'BASS' OR N.FISH_NAME = 'SNAPPER';
  • FISH_TYPE을 기준으로 조인합니다.
    (FROM FISH_INFO AS I JOIN FISH_NAME_INFO AS N ON I.FISH_TYPE = N.FISH_TYPE)
  • 이름이 BASS 또는 SNAPPER인 생선을 조회합니다.
    (WHERE N.FISH_NAME = 'BASS' OR N.FISH_NAME = 'SNAPPER';)

대장균들의 자식의 수 구하기

SELECT 
    E1.ID, 
    IFNULL(COUNT(E2.PARENT_ID), 0) AS CHILD_COUNT
FROM ECOLI_DATA E1 LEFT JOIN ECOLI_DATA E2 
ON E1.ID = E2.PARENT_ID
GROUP BY E1.ID
ORDER BY E1.ID ASC;
  • E1의 ID와 E2의 PARENT_ID를 기준으로 LEFT JOIN합니다.
    (FROM ECOLI_DATA E1 LEFT JOIN ECOLI_DATA E2 ON E1.ID = E2.PARENT_ID)
  • E1.ID를 기준으로 GROUP BY합니다.
    (GROUP BY E1.ID)
  • 만약 PARENT_ID가 없으면 0으로 처리합니다.
    (IFNULL(COUNT(E2.PARENT_ID), 0) AS CHILD_COUNT)
  • ID를 기준으로 오름차순 정렬합니다.

대장균의 크기에 따라 분류하기 1

SELECT
    ID,
    CASE
        WHEN SIZE_OF_COLONY <= 100 THEN 'LOW'
        WHEN SIZE_OF_COLONY <= 1000 THEN 'MEDIUM'
        ELSE 'HIGH'
    END AS SIZE
FROM ECOLI_DATA
ORDER BY ID asc
  • CASE WHEN 절을 이용하여 사이즈에 따라 분류합니다.
  • ID를 기준으로 오름차순 정렬합니다.

특정 형질을 가지는 대장균 찾기

SELECT
    COUNT(*) AS COUNT
FROM ECOLI_DATA
WHERE GENOTYPE & 2 = 0 AND (GENOTYPE & 4 > 0 OR GENOTYPE & 1 > 0)
  • 2번 형질을 보유하지 않으면서 1, 3번 형질을 보듀하고 있는 대장균의 갯수를 조회합니다.
    (WHERE GENOTYPE & 2 = 0 AND (GENOTYPE & 4 > 0 OR GENOTYPE & 1 > 0))

부모의 형질을 모두 가지는 대장균 찾기

SELECT 
    E1.ID,
    E1.GENOTYPE AS GENOTYPE,
    E2.GENOTYPE AS PARENT_GENOTYPE
FROM ECOLI_DATA E1 JOIN ECOLI_DATA E2 
ON E1.PARENT_ID = E2.ID
WHERE (E1.GENOTYPE & E2.GENOTYPE) = E2.GENOTYPE
ORDER BY E1.ID ASC;
  • 자식과 부모를 연결합니다.
    (FROM ECOLI_DATA E1 JOIN ECOLI_DATA E2 ON E1.PARENT_ID = E2.ID)
  • 자식의 유전자형이 부모의 유전자형을 포함하고 있는지 확인합니다.
    (WHERE (E1.GENOTYPE & E2.GENOTYPE) = E2.GENOTYPE)
  • 자식의 ID를 기준으로 오름차순으로 정렬됩니다.
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(SELECT)입니다.

재구매가 일어난 상품과 회원 리스트 구하기

SELECT 
    USER_ID, 
    PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) >= 2
ORDER BY USER_ID ASC, PRODUCT_ID DESC
  • 동일한 회원, 동일한 상품을 조회하기 위해 USER_ID와 PRODUCT_ID를 기준으로 GROUP BY 해줍니다.
    (GROUP BY USER_ID, PRODUCT_ID)
  • 그 중에서 두번 이상의 데이터가 있다는 것은 재구매가 일어났다는 것이니 HAVING을 걸어줍니다.
    (HAVING COUNT(*) >= 2)
  • USER_ID의 오름차순, PRODUCT_ID를 내림차순으로 정렬해줍니다.
    (ORDER BY USER_ID ASC, PRODUCT_ID DESC)

모든 레코드 조회하기

SELECT * 
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
  • ANIMAL_INS 테이블에서 ANIMAL_ID를 기준으로 오름차순 정렬한
    (ORDER BY ANIMAL_ID)
    데이터의 모든 레코드를 조회합니다.
    (SELECT *)

역순 정렬하기

SELECT
    NAME, 
    DATETIME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID DESC
  • ANIMAL_INS 테이블에서 ANIMAL_ID를 기준으로 내림차순 정렬한
    (ORDER BY ANIMAL_ID DESC)
    데이터의 NAME과 DATETIME을 조회합니다.

오프라인/온라인 판매 데이터 통합하기

SELECT 
    A.SALES_DATE,
    A.PRODUCT_ID,
    A.USER_ID,
    A.SALES_AMOUNT
FROM    (
    SELECT 
        TO_CHAR(SALES_DATE, 'YYYY-MM-DD') AS SALES_DATE,
        PRODUCT_ID,
        USER_ID,
        SALES_AMOUNT
    FROM ONLINE_SALE
    
    UNION
    
    SELECT 
        TO_CHAR(SALES_DATE, 'YYYY-MM-DD') AS SALES_DATE,
        PRODUCT_ID,
        NULL as USER_ID,
        SALES_AMOUNT
    FROM OFFLINE_SALE
) A
WHERE A.SALES_DATE like '2022-03%'
ORDER BY 
    A.SALES_DATE ASC, 
    A.PRODUCT_ID ASC, 
    A.USER_ID ASC
  • 온라인 데이터 테이블(ONLINE_SALE)과 오프라인 데이터 테이블(OFFLINE_SALE)의 필드를 하나로 합치기 위해 필드를 합쳐주고 UNION 을 이용합니다.
  • 오프라인에서 USER_ID가 없을 때에는 NULL처리합니다.
    (NULL as USER_ID)
  • 그 중 판매일이 2022년 03월인 데이터만 출력합니다.
    (WHERE A.SALES_DATE like '2022-03%')
  • 판매일을 기준으로 오름차순, 상품 ID 오름차순, 유저 ID를 오름차순으로 정렬합니다.
    (ORDER BY A.SALES_DATE ASC, A.PRODUCT_ID ASC, A.USER_ID ASC)

아픈 동물 찾기

SELECT 
    ANIMAL_ID,
    NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION = 'Sick'
ORDER BY ANIMAL_ID;
  • 보호 시작시 상태가 Sick인 동물을 조회합니다.
    (WHERE INTAKE_CONDITION = 'Sick')
  • ANIMAL_ID를 오름차순으로 정렬합니다.

어린 동물 찾기

SELECT 
    ANIMAL_ID,
    NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION != 'Aged'
ORDER BY ANIMAL_ID;
  • 보호 시작시 상태가 Aged가 아닌 동물을 조회합니다.
    (INTAKE_CONDITION != 'Aged')
  • ANIMAL_ID를 오름차순으로 정렬합니다.

동물의 아이디와 이름

SELECT 
    ANIMAL_ID,
    NAME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;
  • 동물의 아이디와 이름을 아이디를 기준으로 오름차순 정렬합니다.

여러 기준으로 정렬하기

SELECT
    ANIMAL_ID,
    NAME,
    DATETIME
FROM ANIMAL_INS
ORDER BY NAME, DATETIME DESC
  • 이름을 기준으로 오름차순, 동물 보호 시작일을 내림차순으로 정렬합니다.

상위 N개 레코드

SELECT
    NAME
FROM (
        SELECT
            NAME
        FROM ANIMAL_INS
        ORDER BY DATETIME asc
    )
WHERE ROWNUM = 1;
  • 보호 시작일을 기준으로 오름차순으로 정렬하고 ROWNUM이 1인(가장 먼저 들어온) 데이터를 조회합니다.
    (WHERE ROWNUM = 1;)

조건에 맞는 회원수 구하기

SELECT
    COUNT(*)
FROM USER_INFO
WHERE TO_CHAR(JOINED, 'YYYY') = '2021' AND AGE BETWEEN 20 AND 29
  • 2021년에 가입한 회원과 나이가 20세 이상 29세 이하인 회원을 조회하기 위해 BETWEEN을 사용합니다.
    (WHERE TO_CHAR(JOINED, 'YYYY') = '2021' AND AGE BETWEEN 20 AND 29)
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(SELECT)입니다.

평균 일일 대여 요금 구하기

SELECT ROUND(AVG(DAILY_FEE), 0) AS AVERAGE_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE = 'SUV';
  • DAILY_FEE의 평균을 계산한 후 소수점 첫째 자리에서 반올림하여 정수로 반환합니다.
    (ROUND(AVG(DAILY_FEE), 0))
  • CAR_TYPE이 'SUV'인 레코드만 필터링하여 평균을 계산합니다.
    (WHERE CAR_TYPE = 'SUV)

과일로 만든 아이스크림 고르기

SELECT 
    A.FLAVOR
FROM FIRST_HALF A JOIN ICECREAM_INFO B ON A.FLAVOR = B.FLAVOR
WHERE
    A.TOTAL_ORDER >= 3000 AND
    B.INGREDIENT_TYPE = 'fruit_based'
ORDER BY 
    A.TOTAL_ORDER DESC
  • FIRST_HALF 테이블과 ICECREAM_INFO 테이블을 FLAVOR를 기준으로 조인합니다.
    (FROM FIRST_HALF A JOIN ICECREAM_INFO B ON A.FLAVOR = B.FLAVOR)
  • TOTAL_ORDER가 3000이 넘고 아이스크림의 주 성분이 과일인 맛을 조회합니다.
    (WHERE A.TOTAL_ORDER >= 3000 AND B.INGREDIENT_TYPE = 'fruit_based')
  • 총 주문량이 큰 순서대로 정렬합니다.
    (ORDER BY A.TOTAL_ORDER DESC)

3월에 태어난 여성 회원 목록 출력하기

SELECT 
	MEMBER_ID, 
    MEMBER_NAME, 
    GENDER, 
    TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD')
FROM MEMBER_PROFILE
WHERE TLNO IS NOT NULL AND TO_CHAR(DATE_OF_BIRTH, 'MM') = '03' AND GENDER = 'W'
ORDER BY MEMBER_ID;
  • 타입을 맞춰주기 위해 TO_CHAR를 사용합니다.
    (TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD'))
  • TLNO가 NULL이 아니며 생월이 3월이며 여성인 멤버를 조회합니다.
    (WHERE TLNO IS NOT NULL AND TO_CHAR(DATE_OF_BIRTH, 'MM') = '03' AND GENDER = 'W')
  • 멤버 아이디를 기준으로 오름차순 정렬합니다.
    (ORDER BY MEMBER_ID;)

서울에 위치한 식당 목록 출력하기

SELECT
    I.REST_ID,
    I.REST_NAME,
    I.FOOD_TYPE,
    I.FAVORITES,
    I.ADDRESS,
    R.SCORE
FROM REST_INFO I JOIN (
    SELECT REST_ID, ROUND(AVG(REVIEW_SCORE), 2) AS SCORE
    FROM REST_REVIEW
    GROUP BY REST_ID
)R
ON I.REST_ID = R.REST_ID
WHERE I.ADDRESS LIKE '서울%'
ORDER BY score desc, I.FAVORITES DESC
  • REST_REVIEW 테이블에서 REST_ID를 기준으로 GROUP BY를 하여 리뷰 평균점수를 구한 테이블을 R이라고합니다.
  • REST_INFO 테이블과 위에서 구한 테이블 R과 REST_ID를 기준으로 조인합니다.
    (REST_INFO I JOIN (...)R ON I.REST_ID = R.REST_ID)
  • 식당은 서울에 위치해야하므로 LIKE를 이용합니다.
    (WHERE I.ADDRESS LIKE '서울%')
  • SCORE가 높은 순서대로, 즐겨찾기가 높은 순서대로 정렬해줍니다.
    (ORDER BY score desc, I.FAVORITES DESC)

흉부외과 또는 일반외과 의사 목록 출력하기

SELECT 
	DR_NAME, 
    DR_ID, 
    MCDP_CD, 
    TO_CHAR(HIRE_YMD, 'YYYY-MM-DD') AS HIRE_YMD
FROM DOCTOR
WHERE MCDP_CD = 'CS' or MCDP_CD = 'GS'
ORDER BY HIRE_YMD DESC, DR_NAME ASC;
  • 흉부외과(CS), 일반외과(GS)인 의사의 정보를 조회합니다.
    (WHERE MCDP_CD = 'CS' or MCDP_CD = 'GS')
  • 고용일자를 내림차순, 의사의 이름을 기준으로 오름차순으로 정렬합니다.
    (ORDER BY HIRE_YMD DESC, DR_NAME ASC;)

조건에 부합하는 중고거래 댓글 조회하기

SELECT 
    B.TITLE,
    B.BOARD_ID,
    R.REPLY_ID,
    R.WRITER_ID,
    R.CONTENTS,
    TO_CHAR(R.CREATED_DATE, 'YYYY-MM-DD')
FROM USED_GOODS_BOARD B JOIN USED_GOODS_REPLY R
ON B.BOARD_ID = R.BOARD_ID
WHERE TO_CHAR(B.CREATED_DATE, 'YYYY-MM') = '2022-10'
ORDER BY R.CREATED_DATE ASC, B.TITLE ASC
  • USED_GOODS_BOARD 테이블과 USED_GOODS_REPLY를 BOARD_ID를 통해 조인합니다
    (USED_GOODS_BOARD B JOIN USED_GOODS_REPLY R ON B.BOARD_ID = R.BOARD_ID)
  • 그 중 2022년 10월에 작성된 게시물을 찾기 위해 TO_CHAR를 통해 조건을 걸어줍니다.
    (WHERE TO_CHAR(B.CREATED_DATE, 'YYYY-MM') = '2022-10')
  • 댓글 작성일을 기준으로 오름차순, 게시물 제목을 기준으로 오름차순 정렬해줍니다.
    (ORDER BY R.CREATED_DATE ASC, B.TITLE ASC)

인기있는 아이스크림

SELECT FLAVOR
FROM FIRST_HALF
ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC;
  • 아이스크림의 맛을 총 주문량을 기준으로 내림차순 정렬하고 출하 번호를 기준으로 오름차순 정렬합니다.
    (ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC;)

강원도에 위치한 생산공장 목록 출력하기

SELECT
    FACTORY_ID,
    FACTORY_NAME,
    ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS Like '강원%'
ORDER BY FACTORY_ID ASC
  • FOOD_FACTORY 테이블에서 주소가 강원도인 데이터를 LIKE를 통해 조회합니다.
    (WHERE ADDRESS Like '강원%')
  • FACTORY_ID를 기준으로 오름차순 정렬합니다.
    (ORDER BY FACTORY_ID ASC)

12세 이하인 여자 환자 목록 출력하기

SELECT 
    PT_NAME,
    PT_NO,
    GEND_CD,
    AGE,
    NVL(TLNO, 'NONE')
FROM PATIENT
WHERE GEND_CD = 'W' AND AGE <= 12
ORDER BY AGE DESC, PT_NAME ASC;
  • PATIENT 테이블에서 12세 이하 여자 환자 데이터를 조회하기 위해 조건을 걸어줍니다.
    (WHERE GEND_CD = 'W' AND AGE <= 12)
  • TLNO가 없을 때는 NONE으로 출력하기 위해 NVL을 사용합니다.
    (NVL(TLNO, 'NONE'))
  • 나이가 많은 순, 이름을 기준으로 오름차순으로 정렬합니다.
    (ORDER BY AGE DESC, PT_NAME ASC;)

조건에 맞는 도서 리스트 출력하기

SELECT
    BOOK_ID,
    TO_CHAR(PUBLISHED_DATE, 'YYYY-MM-DD')
FROM BOOK
WHERE CATEGORY = '인문' AND TO_CHAR(PUBLISHED_DATE, 'YYYY') = '2021'
ORDER BY PUBLISHED_DATE ASC
  • BOOK 테이블에서 카테고리가 인문이고 2021년에 출판된 책의 데이터를 조회합니다.
    (WHERE CATEGORY = '인문' AND TO_CHAR(PUBLISHED_DATE, 'YYYY') = '2021')
  • 출판일을 기준으로 오름차순 정렬해줍니다.
    (ORDER BY PUBLISHED_DATE ASC)
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
접은 글을 통해 먼저 답변을 해보시고 제가 정리한 답을 확인해보시기 바라겠습니다!!

면접 리스트

객체지향이란 무엇인가요?

더보기

역할과 책임을 갖는 객체들의 결합을 통해 프로그래밍하는 것을 의미합니다. 객체지향의 특징으로는 추상화, 캡슐화, 상속, 다형성이 있습니다. 이를 통해서 변경에 유연한 코드를 작성할 수 있습니다.

객체지향적인 프로그래밍을 개발하기 위해 가장 중요한 것은 무엇이라 생각하나요?

더보기

객체의 분석하여 상태화 행동을 적절히 추상화 및 캡슐화 하는 것이 중요하다고 생각합니다.

 

추상화는 복잡한 시스템을 간단하게 표현하기 위해 불필요한 세부 사항을 제거하고 핵심적인 특성만을 강조하는 과정으로, 이를 통해 개발자는 현실 세계의 개념을 모델링할 때 필요한 요소만을 선택하여 클래스를 설계할 수 있습니다.

 

소프트웨어의 복잡성을 줄이고 시스템을 더욱 직관적으로 이해할 수 있도록 도와주며, 유지보수성과 확장성을 향상시키는 데 필수적인 역할을 합니다.

추상화란 무엇인가요?

더보기

추상화는 각 도메인에 대해 불필요한 정보를 제거하고, 문제 해결에 필수적인 정보만 남기는 작업이라고 생각합니다.

다형성이란 무엇인가요?

더보기

다형성이란 동일한 메서드나 연산자가 다양한 객체에서 다른 방식으로 동작할 수 있도록 하는 객체지향 프로그래밍의 특성이라고 생각합니다. 

하나의 인터페이스를 구현하는 클래스들에 따라 각 메소드를 다른 방식으로 구현할 수 있습니다.

예를 들어 각 애플리케이션의 특성에 맞게 사용되는 데이터베이스가 있을 때 어떠한 이유로 데이터베이스 엔진이 교체될 때에 JDBC API를 의존하는 클라이언트는 소스코드를 수정하지 않는 것을 의미합니다.

캡슐화란 무엇인가요?

더보기

캡슐화객체의 상태화 행동을 객체 내부로 숨기는 것입니다. 이로 인해 결합도는 낮춰지고 응집도는 높아집니다.

결합도와 응집도가 무엇이며 좋은 코드를 위한 개발방법은 무엇인가요?

더보기

결합도모듈 간의 상호 의존성을 나타내며, 낮은 결합도가 좋은 설계로 여겨지는 반면, 응집도하나의 모듈이 얼마나 관련된 기능을 수행하는지를 나타내며 높은 응집도가 바람직하다고 생각합니다.

 

좋은 코드를 위한 개발 방법으로는 모듈 간의 결합도를 최소화하고, 각 모듈이 독립적으로 기능을 수행할 수 있도록 설계하며, 동시에 각 모듈이 명확한 목적과 관련성을 갖도록 하는 것이 중요합니다.

상속이란 무엇인가요? 장점과 단점도 설명해 주세요

더보기

상속객체지향 프로그래밍에서 기존 클래스(부모 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스)가 물려받아 재사용할 수 있게 하는 것입니다.

상속의 장점은 코드의 재사용성을 높이고, 공통적인 기능을 부모 클래스에 정의함으로써 중복 코드를 줄일 수 있다는 점이며, 이를 통해 유지보수와 확장성을 향상시킬 수 있습니다.

반면에 단점으로는 잘못된 상속 관계가 복잡한 계층 구조를 초래할 수 있으며, 부모 클래스의 변경이 자식 클래스에 영향을 미칠 수 있어 시스템의 유연성을 저하시킬 수 있다는 점이 있습니다.

 

 

제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
접은 글을 통해 먼저 답변을 해보시고 제가 정리한 답을 확인해보시기 바라겠습니다!!

면접을 위한 CS 전공지식 노트(주홍철 저)을 통해 정리한 포스팅입니다.

면접 리스트

옵저버 패턴은 어떻게 구현하나요?

더보기

옵저버 패턴은 객체 간의 일대다 관계를 정의하여, 특정 객체의 상태 변화가 있을 때 그 변화를 다른 객체들에게 자동으로 통지하는 디자인 패턴입니다. 이 패턴은 프록시 객체를 주로 사용합니다. 프록시 객체를 통해 객체의 속성이나 메소드 변화 등을 감지하고 미리 설정해놓은 옵저버들에게 전달하는 방식으로 구현합니다.

 

구현 방법은 주체가 되는 객체를 Subject라고 하고, 이 객체는 구독자들을 리스트 형태로 관리합니다. 상태에 변화가 생기면 notifyObservers() 메서드를 호출하여 모든 구독자에게 변경 사항을 알립니다. 각 구독자는 Observer 인터페이스를 구현하여 update() 메서드를 정의함으로써 통지를 받고 처리하게 됩니다.

 

장점으로는 확장성이 뛰어나 새로운 옵저버를 추가해도 주체의 코드에 큰 변경이 필요 없다는 점이 있습니다. 또한, 주체와 옵저버 사이의 결합도가 낮아 객체 간의 독립성을 유지할 수 있는 것이 큰 장점입니다.

 

단점으로는 옵저버가 많아질 경우 성능 문제가 발생할 수 있으며, 예기치 않은 상태 변화가 복잡하게 일어날 가능성도 있습니다. 또한, 특정 옵저버의 동작이 느릴 경우 전체 알림 체계의 성능에 영향을 미칠 수 있습니다.

 

이러한 이유로 옵저버 패턴은 유연한 이벤트 기반 시스템에서는 매우 유용하지만, 성능과 관리 측면에서는 주의가 필요합니다.

팩토리 메소드 패턴은 무엇이며 어떠한 장점이 있는가요?

더보기

팩토리 메소드 패턴객체 생성의 책임을 서브클래스에 위임하는 디자인 패턴입니다. 객체를 생성하는 코드를 캡슐화하여 상위 클래스에서는 객체 생성의 구체적인 클래스를 지정하지 않고, 서브클래스에서 필요한 객체를 생성하도록 하는 것이 특징입니다. 주로 객체 생성의 코드 중복을 줄이고, 코드의 확장성을 높이기 위해 사용됩니다.

 

장점으로는 새로운 객체 유형을 추가할 때 기존 코드를 거의 변경하지 않고도 새로운 서브클래스를 추가하여 확장성을 높이고 객체 생성 로직을 캡슐화하여 클라이언트 코드의 복잡도를 줄이고 유지 보수성을 높일 수 있습니다. 또한 구체적인 클래스에 의존하지 않으므로 느슨한 결합을 통해 코드 유연성과 재사용성이 증가합니다.

 

단점으로는 클래스의 수가 많아질 수 있고, 코드 구조가 복잡해질 수 있다는 점이 있습니다. 서브클래스에서 객체 생성을 구현해야 하므로 코드의 가독성이 떨어질 수도 있습니다.

 

팩토리 메소드 패턴은 특히 다양한 객체를 생성해야 하되, 객체 생성 로직이 복잡하거나 자주 변경되는 경우에 적합한 패턴입니다.

컴포넌트 패턴은 무엇이며 어떠한 장점이 있는가요?

더보기

컴포넌트 패턴객체를 트리 구조로 구성하여 부분-전체 계층을 표현할 수 있도록 하는 구조적 디자인 패턴입니다. 이 패턴은 개별 객체와 객체 그룹을 동일한 방식으로 다룰 수 있게 하여, 클라이언트가 단일 객체와 복합 객체를 구분하지 않고 일관된 방식으로 처리할 수 있도록 합니다.

 

장점으로는 단일 객체와 복합 객체를 동일한 인터페이스로 다룰 수 있어 클라이언트 코드가 단순해지며 새로운 타입을 쉽게 추가하여 확장성이 용이합니다. 또 재귀적으로 복합 객체를 구성할 수 있습니다.

 

단점으로는 복합 구조의 설계가 복잡해질 수 있다는 점입니다. 특히, 트리 구조에서 객체 간의 관계를 잘못 설계하면 객체들이 지나치게 얽혀서 코드의 가독성과 유지보수성이 떨어질 수 있습니다. 또한, 일부 경우에는 단일 객체와 복합 객체의 구분이 모호해질 수 있어 설계 시 주의가 필요합니다.

 

컴포넌트 패턴은 주로 파일 시스템(파일과 폴더), 그래픽 애플리케이션의 UI 구성 요소, 문서 편집기 등 부분-전체 관계를 나타내야 하는 상황에서 유용합니다.

프록시 서버를 설명하고 사용사례에 대해 설명해보세요

더보기

프록시 서버란 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 서버입니다. 주로 애플리케이션 앞단에서 클라이언트의 요청을 처리하여 캐싱, 로깅, 데이터 분석을 하는 서버로 사용합니다. 이를 통해 포트번호를 바꾸어서 실제 서버에 접근하지 못하게 하여 DDOS공격을 차단하며 nginx를 이용해 Node.js로 이루어진 서버의 앞단에 두어 버퍼 오버플로우를 해결할 수 있습니다.

MVC 패턴을 설명하고 MVVM 패턴과 무슨 차이가 있는지 설명해보세요

더보기

MVC 패턴은 모델(M), 뷰(V), 컨트롤러(C)로 이루어진 디자인 패턴으로 애플리케이션의 구성요소를 세가지 역할로 구분하여 각각의 요소에 맞는 역할을 분리하여 집중해서 개발할 수 있는 디자인 패턴입니다. MVC 패턴은 재사용성과 확장성이 용이하다는 장점이 있지만, 애플리케이션이 복잡해질 수록 모델과 뷰의 관계 또한 복잡해지는 단점이 있습니다.

 

MVVM 패턴은 MVC의 C에 해당하는 컨트롤러가 뷰 모델로 바뀐 패턴을 의미합니다. 여기서 뷰모델은 뷰를 더 추상화한 계층이며 MVC 패턴과 다르게 커맨드와 데이터 바인딩을 가지는 것이 특징입니다. 뷰와 뷰모델 사이의 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정없이 재사용할 수 있고 단위 테스팅하기 쉽다는 장점이 있습니다. 

TDD는 무엇이며 어떠한 장점이 있는가요?

더보기

TDD(Test-Driven Development)는 소프트웨어 개발 방법론 중 하나로, 테스트를 먼저 작성한 후 실제 코드를 구현하는 방식을 의미합니다. 개발자가 특정 기능을 구현하기 전에 해당 기능에 대한 테스트 코드를 작성하고, 이 테스트를 통과할 수 있는 최소한의 코드를 구현한 후 점진적으로 개선해 나가는 반복적인 프로세스를 따릅니다.

 

TDD는 "Red-Green-Refactor" 사이클을 통해 진행됩니다. 먼저 실패하는 테스트를 작성하여 (Red 단계), 코드가 현재 상태에서 원하는 기능을 충족하지 못함을 확인합니다. 이후, 테스트를 통과하기 위한 최소한의 코드를 작성하여 (Green 단계) 테스트가 성공하도록 만듭니다. 마지막으로 코드를 개선하고 정리하는 리팩토링 단계 (Refactor)를 통해 코드를 최적화하면서도 테스트를 통과할 수 있도록 유지합니다.

 

TDD는 코드의 품질 보장과 유지보수성 향상에 도움을 주며, 빠른 피드백과 코드 안정성을 높이는 데 기여합니다. 그러나 초기 개발 속도가 느려질 수 있고, 복잡한 로직의 테스트 작성이 어려울 수 있다는 단점도 있습니다.

DDD는 무엇이며 어떠한 장점이 있는가요?

더보기

DDD(Domain-Driven Design)는 복잡한 소프트웨어 프로젝트를 개발할 때 비즈니스 도메인, 즉 특정 업무 영역을 깊이 이해하고 이를 중심으로 소프트웨어를 설계하고 개발하는 접근 방식입니다. 도메인은 비즈니스의 문제 영역을 나타내며, DDD는 이 도메인을 철저히 모델링하여 개발자와 도메인 전문가 간의 원활한 소통을 가능하게 하고, 비즈니스 로직을 충실히 반영한 소프트웨어를 구축하는 데 중점을 둡니다.

 

DDD의 장점으로는 복잡한 비즈니스 로직을 보다 효과적으로 다룰 수 있다는 점이 있습니다. 시스템을 도메인별로 나누어 설계함으로써 모듈성과 확장성이 강화되고, 유지보수와 확장이 용이해집니다. 도메인 경계를 명확히 설정해 모듈 간 의존성을 줄여 결합도를 낮추고, 전체적인 코드의 유지보수성을 높일 수 있습니다.

 

하지만 DDD는 높은 초기 학습 곡선이 필요하다는 단점이 있습니다. 도메인에 대한 깊이 있는 이해와 설계 패턴에 대한 지식이 요구되며, 이를 완전히 익히고 적용하는 데는 시간이 걸릴 수 있습니다. 또한, 단순한 시스템보다는 복잡한 도메인에 적합하기 때문에, 프로젝트의 규모가 작거나 비즈니스 로직이 단순한 경우에는 오히려 불필요하게 복잡해질 수 있습니다. 도메인을 심도 있게 분석하고 설계하는 과정은 시간과 비용이 많이 들며, 초기 개발 속도가 느려질 가능성도 있습니다.

 

결론적으로 DDD는 복잡한 비즈니스 로직을 다루는 대규모 시스템 개발에서 매우 유용하며, 도메인 이해와 코드의 유지보수성을 높이는 데 큰 장점을 제공합니다.

객체지향 프로그래밍은 무엇인가요?

더보기

객체지향 프로그래밍(OOP, Object-Oriented Programming)은 프로그램을 단순히 함수나 코드의 순서대로 작성하는 것이 아니라, 현실 세계의 객체를 추상화하여 프로그래밍하는 방법입니다. 객체지향 프로그래밍에서는 데이터를 하나의 객체로 묶고, 그 객체가 가진 속성(데이터)과 행위(메서드)를 중심으로 프로그램을 구성합니다. 이를 통해 코드의 재사용성과 확장성을 높이고, 프로그램의 구조를 더 직관적이고 유지보수하기 쉽게 만듭니다.

 

객체지향 프로그래밍의 핵심 개념에는 클래스와 객체, 캡슐화, 상속, 다형성 등이 있습니다. 클래스는 객체를 생성하기 위한 설계도이며, 객체는 클래스에 의해 생성된 구체적인 실체입니다.

 

캡슐화는 객체의 속성과 행위를 하나로 묶고, 외부로부터 이를 숨김으로써 데이터의 무결성을 유지하는 개념입니다. 예를 들어, 객체의 내부 상태를 보호하기 위해 외부에서는 객체의 속성에 직접 접근할 수 없고, 메서드를 통해서만 간접적으로 접근하도록 설계할 수 있습니다.

 

상속은 새로운 클래스가 기존 클래스의 속성과 메서드를 물려받아 재사용하거나 확장할 수 있도록 하는 개념입니다. 이를 통해 코드의 중복을 줄이고, 계층적인 설계를 통해 관리와 유지보수를 쉽게 합니다.

 

다형성은 같은 메서드나 연산자가 다양한 객체에서 다른 방식으로 동작할 수 있도록 하는 특성입니다.

 

결론적으로, 객체지향 프로그래밍은 프로그램을 현실 세계의 개념을 반영하여 구성함으로써 구조적이고 이해하기 쉬운 코드를 작성할 수 있게 해주는 강력한 프로그래밍 패러다임입니다.

정리[디자인패턴]

더보기

디자인 패턴

💡 라이브러리 VS 프레임워크
라이브러리
: 공통으로 사용될 수 있는 특정한 기능을 모듈화 한 것. 코드의 제어권이 라이브러리에 있음.
프레임워크: 공통으로 사용될 수 있는 특정한 기능을 모듈화 한 것. 코드의 제어권이 개발자에 있음. 

디자인 패턴

프로그램을 설계할 때 발생했던 문제점들을 객체간의 상호관계 등을 이용하여 해결할 수 있도록 하나의 규약 형태로 만들어 놓은것.

 

싱글톤 패턴(더 자세한 건 여기로)

하나의 클래스오직 하나의 인스턴스만 가지는 패턴. 데이터 베이스 연결 모듈에 많이 사용.(datasource)

  • 장점
    • 하나의 인스턴스만 있을 때 다른 모듈들이 공유하며 사용하기 때문에 인스턴스 비용이 줄어듦.
  • 단점
    • 의존성이 높아짐.

Java에서의 싱글톤 패턴

public class HelloSingleton {
    static class Singleton {
        private static class singleInstanceHolder {
            private static final Singleton INSTANCE = new Singleton();
        }

        public static Singleton getInstance() {
            return singleInstanceHolder.INSTANCE;
        }
    }
    public static void main(String[] args) {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        System.out.println("a.hashCode() = " + a.hashCode());
        System.out.println("b.hashCode( = " + b.hashCode());
        System.out.println("a.equals(b) = " + a.equals(b));
    }
}

/*
 * a.hashCode() = 1577213552
 * b.hashCode( = 1577213552
 * a.equals(b) = true
 */

싱글톤 패턴의 단점

  • TDD(Test Driven Development)에서의 문제점 발생
    • TDD할 때는 단위 테스트 위주.
    • 단위 테스트는 테스트를 하는 클래스가 서로 독립적이여야함. => 싱글톤으로의 개발의 복잡성

의존성 주입

  • 사용하기 쉽고 실용적이지만 모듈 간의 결합을 강하게 만들 수 있음.
  • 의존성 주입(DI, Dependency Injection)을 통해 모듈 간의 결합을 느슨하게 만들 수 있음.
  • 의존성 주입자를 통해 메인 모듈이 간접적으로 의존성을 주입하는 방법
  • 장점
    • 모듈들을 쉽게 교체할 수 있는 구조가 되어 테스팅하기 쉽고 마이그레이션 하기 수월 => 객체지향의 장점
    • 구현할 때 추상화 레이어를 통해 구현체를 넣어주기 때문에 의존성 방향이 일관적이고 애플리케이션을 쉽게 추론할 수 있으며 모듈 간의 관계들이 명확
  • 단점
    • 복잡성 증가
  • 원칙
    • 상위 모듈은 하위 모듈에서 어떠한 것도 가져오면 안됨.
    • 모두 추상화에 의존해야하며 추상화는 세부사항에 의존하면 안됨.

팩토리 패턴(더 자세한 건 여기로)

객체의 생성 부분을 제거하고 추상화한 패턴. 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴

  • 클래스가 분리되기 때문에 느슨한 결합을 가지며 더 많은 유연성을 얻게 됨.
  • 객체 생성 로직이 따로 있기 때문에 코드를 리팩토링 할 때 한 곳만 고치면 되기에 유지 보수성이 증가함.
  • 전달받은 값에 따라 다른 객체를 생성하며 인스턴스의 타입 지정 가능.
enum CoffeeType {
    LATTE(0),
    ESPRESSO(1),
    TEA(2);

    private int type;

    CoffeeType(int type) {
        this.type = type;
    }

    public int getType() {
        return type;
    }
}

abstract class Coffee {
    protected String name;

    public String getName() {
        return name;
    }
}

class Latte extends Coffee {
    public Latte() {
        super.name = "Latte";
    }
}

class Espresso extends Coffee {
    public Espresso() {
        super.name = "Espresso";
    }
}


public class FactoryPattern {
    static class CoffeeFactory {
        public static Coffee createCoffee(CoffeeType type) {
            switch (type) {
                case LATTE -> {
                    return new Latte();
                }
                case ESPRESSO -> {
                    return new Espresso();
                }
                default -> {
                    throw new IllegalArgumentException("Invalid coffee type: " + type);
                }
            }
        }
    }
    public static void main(String[] args) {
        Coffee brianCoffee = CoffeeFactory.createCoffee(CoffeeType.LATTE);
        Coffee jackCoffee = CoffeeFactory.createCoffee(CoffeeType.ESPRESSO);
//        Coffee mikeCoffee = CoffeeFactory.createCoffee(CoffeeType.TEA);

        System.out.println("brianCoffee = " + brianCoffee.getName());
        System.out.println("jackCoffee = " + jackCoffee.getName());
//        System.out.println("mikeCoffee = " + mikeCoffee.getName()); // IllegalArgumentException

    }

}

/*
 * brianCoffee = Latte
 * jackCoffee = Espresso
 */
  • 의존성 주입이라고 할 수 도 있음. CoffeeFactory에서 LatteFacotry의 인스턴스를 생성하는 것이 아닌 주입하기 때문
  • 정적 메소드(static으로 설정한 함수)의 경우 클래스를 기반으로 객체를 만들지 않고 호출이 가능하며, 해당 메소드에 대한 메모리 할당을 한번만 할 수 있다는 장점이 있음.

전략 패턴(더 자세한 건 여기로)

객체의 행위를 바꾸고 싶은 경우 코드의 수정없이 캡슐화된 알고리즘을 컨텍스트 안에서 바꿔주면서 상호 교체하는 패턴

import java.util.ArrayList;
import java.util.List;

interface PaymentStrategy {
    public void pay(int amount);
}

class KAKAOCardStrategy implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public KAKAOCardStrategy(String name, String cardNumber, String cvv, String dateOfExpiry) {
        this.name = name;
        this.cardNumber = cardNumber;
        this.cvv = cvv;
        this.dateOfExpiry = dateOfExpiry;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using KAKAOCard.");
    }
}

class LUNACardStrategy implements PaymentStrategy {
    private String emailId;
    private String password;

    public LUNACardStrategy(String emailId, String password) {
        this.emailId = emailId;
        this.password = password;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using LUNACard.");
    }
}

class Item {
    private String name;
    private int price;

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}

class ShoppingCart {
    List<Item> items;

    public ShoppingCart() {
        this.items = new ArrayList<>();
    }

    public void addItem(Item item) {
        this.items.add(item);
    }

    public void removeItem(Item item) {
        this.items.remove(item);
    }

    public int calculateTotal() {
        int sum = 0;
        for (Item item : items) {
            sum += item.getPrice();
        }
        return sum;
    }

    public void pay(PaymentStrategy paymentStrategy) {
        int amount = calculateTotal();
        paymentStrategy.pay(amount);
    }
}

public class StrategyPattern {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item A = new Item("hiroA", 100);
        Item B = new Item("hiroB", 300);

        cart.addItem(A);
        cart.addItem(B);

        // pay by luna card
        cart.pay(new LUNACardStrategy("hiro@example.com", "TESt123!@#"));

        // pay by kakao card
        cart.pay(new KAKAOCardStrategy("Ipjagum", "123123123", "123", "12/10"));
    }
}

/*
 * 400 paid using LUNACard.
 * 400 paid using KAKAOCard.
 */

 

옵저버 패턴(더 자세한 건 여기로)

주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메소드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴

  • 주체
    • 객체의 상태 변화를 관찰하고 있는 객체
  • 옵저버
    • 객체의 상태 변화에 따라 전달되는 메소드 등을 기반으로 추가 변화 상항이 생기는 객체
  • 이벤트 기반 시스템에서 주로 사용되며 MVC(Model-View-Controller) 패턴에도 사용가능
import java.util.ArrayList;
import java.util.List;

interface Observer {
    public void update();
}

interface Subject {
    public void register(Observer obj);
    public void unregister(Observer obj);
    public void notifyObservers();
    public String getUpdate(Observer obj);
}

class Topic implements Subject {
    private List<Observer> observers;
    private String message;

    public Topic() {
        this.observers = new ArrayList<>();
        this.message = "";
    }

    @Override
    public void register(Observer obj) {
        if (!observers.contains(obj)) {
            observers.add(obj);
        }
    }

    @Override
    public void unregister(Observer obj) {
        if (observers.contains(obj)) {
            observers.remove(obj);
        }
    }

    @Override
    public void notifyObservers() {
        this.observers.forEach(Observer::update);
    }

    @Override
    public String getUpdate(Observer obj) {
        return this.message;
    }

    public void postMessage(String msg) {
        System.out.println("Message sent to Topic: " + msg);
        this.message = msg;
        notifyObservers();
    }
}

class TopicSubscriber implements Observer {
    private String name;
    private Subject topic;

    public TopicSubscriber(String name, Subject topic) {
        this.name = name;
        this.topic = topic;
    }

    @Override
    public void update() {
        String msg = topic.getUpdate(this);
        System.out.println(name + ":: got message >> " + msg);
    }
}

public class ObserverPattern {
    public static void main(String[] args) {
        Topic topic = new Topic();
        Observer o1 = new TopicSubscriber("A", topic);
        Observer o2 = new TopicSubscriber("B", topic);
        Observer o3 = new TopicSubscriber("C", topic);

        topic.register(o1); topic.register(o2); topic.register(o3);

        topic.postMessage("amumu is op champion!");

    }
}

/*
Message sent to Topic: amumu is op champion!
A:: got message >> amumu is op champion!
B:: got message >> amumu is op champion!
C:: got message >> amumu is op champion!
 */
  • topic은 주체이자 객체

상속과 구현

  • 상속
    • 자식 클래스가 부모 클래스의 메소드 등을 상속받아 사용하여 자식 클래스에서 추가 및 확장을 할 수 있는 것.
    • 재사용성, 중복의 최소화
    • 일반 클래스, abstract 클래스를 기반
  • 구현
    • 부모 인터페이스를 자식 클래스에서 재정의하여 구현하는 것.
    • 반드시 부모 클래스의 메소드를 재정의하여 구현
    • 인터페이스 기반

프록시 패턴과 프록시 서버(더 자세한 건 여기로)

대상 객체(subject)에 접근하기 전 그 접근에 대한 흐름을 가로채 해당 접근을 필터링 하거나 수정하는 등의 역할을 하는 계층

  • 객체의 속성, 변환 등을 보완. 데이터 검증, 캐싱 로깅에 사용.

프록시 서버

서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램을 가리킴

  • 프록시 서버로 사용되는 nginx
    • nginx는 비동기 이벤트 기반의 구조와 다수의 연결을 효과적으로 처리 가능한 웹서버이며, 주로 node.js 서버 앞단의 프록시 서버로 사용.

이터레이터 페턴(더 자세한 건 여기로)

이터레이터를 사용하여 컬렉션의 요소들에 접근하는 디자인 패턴 이를 통해 순회할 수 있는 여러가지 자료형의 구조와 상관없이 이터레이터라는 인터페이스를 통해 순회 가능.

  • 자바에서는 Collection Framework를 상속하는 자료구조에서 사용 가능

MVC 패턴

모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴

애플리케이션의 구성 요소를 세가지로 나누어 개발 프로세스에서 각각의 구성요소에만 집중해서 개발할 수 있도록 만든 디자인 패턴.

  • 재사용성과 확장성에 용이
  • 모델과 뷰의 관계가 복잡해진다는 단점
  • 모델
    • 애플리케이션의 데이터인 데이터베이스, 상수, 변수를 의미
    • 사용자 인터페이스 요소를 표현.
    • 변경이 일어나면 컨트롤러에게 이를 전달해야함.
  • 컨트롤러
    • 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할.
    • 이벤트 등 메인 로직 담당. 모델과 뷰의 생명주기도 관리하며 모델이나 뷰의 변경 통지를 받으면 이를 해석해서 각각의 구성요소에게 해당 내용을 전달.

MVP 패턴

MVC 패턴으로부터 파생. MVC에 해당하는 C가 Presenter로 교체된 패턴

뷰와 프레젠터는 1:1이라 더 강한 결합

 

MVVM 패턴

C가 View Model로 바뀐 패턴

  • 뷰모델은 뷰를 더 추상화한 계층. MVVM 패턴은 MVC 패턴과 다르게 커맨드와 데이터 바인등을 가지는 것이 특징.
  • 뷰와 뷰모델 사이의 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정없이 재사용할 수 있고 단위 테스팅 하기 쉽다는 장점.

 

정리[프로그래밍]

더보기

프로그래밍 패러다임

프로개르밍의 관점을 갖게 해주는 역할을 하는 개발 방법론

  • 객체 지향 프로그래밍
    • 프로그래머들이 프로그램을 상호작용하는 객체들의 집합으로 볼 수 있게 하는 방법론
  • 함수형 프로그래밍
    • 상태 값을 지니지 않는 함수 값들의 연속으로 생각하는 방법론
    • 자바8부터 함수형을 지원하기 위해 람다, 생성자 레퍼런스, 메소드 레퍼런스를 도입하였음.
      선언형을 지원하기 위해서는 스트림과 같은 표준 API 도입

프로그래밍 패러다임은 크게 선언형과 명령형으로 나뉨

  • 선언형
    • 함수형
  • 명령형
    • 객체 지향형
    • 절차 지향형

선언형과 함수형 프로그래밍

무엇을 풀어내는가가 중요한 패러다임

  • 순수함수
    • 출력이 입력에만 의존하는 코드
    • const pure = (a, b) => { return a + b; }
    • pure 함수는 a, b에만 영향을 받음
  • 고차함수
    • 함수가 함수를 값처럼 매개변수로 받아 로직을 생성할 수 있는 것.
    • 일급객체
      • 변수나 메소드에 변수를 할당할 수 있음.
      • 함수 안에 함수를 매개변수로 담을 수 있음.
      • 함수가 함수를 반환할 수 있음.

객체 지향 프로그래밍

객체들의 집합으로 프로그램의 상호작용을 표현하며 데이터를 객체로 취급하여 객체 내부에 선언된 메소드를 활용하는 방식

  • 설계에 많은 시간이 소요되며 처리속도가 다른 프로그래밍에 비해 느림
  • 특징
    • 추상화
      • 복잡한 시스템으로부터 핵심적인 개념과 기능을 간추려내는 속성
    • 캡슐화
      • 객체의 속성과 메소드를 하나로 묶고 일부를 외부에 감추어 은닉하는 것
    • 상속성
      • 상위 클래스의 특성을 하위 클래스가 이어받아 재사용하거나 추가 및 확장하는 속성
      • 유지 보수성 증가
    • 다형성
      • 하나의 메소드나 클래스가 다양한 방법으로 동작하는 것을 의미.
      • 오버로딩, 오버라이딩
  • 설계 원칙
    • SOLID
    • 단일 책임 원칙
      • 모든 클래스는 하나의 책임만을 가져야하는 원칙
    • 개방-폐쇄 원칙
      • 확장에는 열려있고 수정에는 닫혀있는 원칙
      • 기존 코드는 변경하지 않으면서 추가하는 원칙
    • 리스코프 치환 원칙
      • 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 하는 것.
    • 인터페이스 분리 원칙
      • 하나의 일반적인 인터페이스보다 구체적인 여러개의 인터페이스를 만드는 원칙
    • 의존성 역전 원칙
      • 자신보다 변하기 쉬운것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향을 받지 않게 하는 원칙

절차형 프로그래밍

로직이 수행되어야할 연속적인 계산과정

  • 코드의 가독성이 좋으면 실행속도가 빠름
  • 계산이 많은 작업에 사용(머신러닝 등)

 

 

 

 

 

 

참조

더보기
  • 면접을 위한 CS 전공지식 노트(주홍철 저) -길벗
  •  

'기술면접 > 전산기초' 카테고리의 다른 글

[기술면접] 객체지향  (3) 2024.11.04
해당 포스팅은 AWS 강의실(https://www.youtube.com/@AWSClassroom)를 보고 공부한 내용을 정리한 블로그입니다.

아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
네 자신의 불행을 생각하지 않게 되는 가장 좋은 방법은 일에 몰두하는 것이다.
Ludwig van Beethoven

Static VS Dynamic Contents


Static Contents

  • 서버에 저장된 파일이 모든 사용자에게 동일하게 전달되는 컨텐츠
  • 매번 서버에 요청할 필요없이 캐싱 가능
  • HTML/Javascript 등으로 구성
  • 예: 이미지, 글, 뉴스 등

Dynamic Contents

  • 시간, 사용자, 입력 등에 따라 내용이 변경되는 컨텐츠
  • 매번 서버에 요청하여 내용을 구성하고 전달받아야함.
  • PHP, JSP, ASP.net 등으로 서버 처리
  • 예: 로그인이 필요한 내용, 게시판, 댓글 등

Amazon S3 Static Hosting


  • S3를 사용해서 정적(Static) 웹 컨텐츠를 호스팅하는 기능
  • 별도의 서버 없이 웹사이트 호스팅 가능
  • 고가용성/장애 내구성을 확보
  • 사용 사례: 대규모 접속이 예상되는 사전 예약 페이지, 홍보 페이지, 회사 웹 사이트 등

권한

  • 정적 웹 호스팅을 public으로 공개할 경우: 불특정 다수에게 허용되는 권한 부여 필요
  • 불특정 다수가 접속할 수 있는 권한을 확보하려면
    • S3 Block Public Access 해제 필요
    • Bucket Policy에서 정책 허용 필요

활용

  • route 53에서 보유한 도메인으로 연결 가능
    • 버킷명 = 호스팅 주소여야 가능
    • test.example.com으로 호스팅하고 싶다면, 버킷명도 ‘test.example.com’ 필요
  • 실전에서 CloudFront와 연동
    • HTTPS 프로토콜 구현을 위해서 CloudFront와 연동 필요.
      • ACM을 통한 SSL 키 관리가 가장 편함
      • 보통 Public Hosting의 활성화 대신 그대로 Private 모드로 두고 OAI/OAC 등을 활용해서 보안 강화

아키텍처

정적 호스팅 아키텍처

실습


1. 버킷 만들기

  1. S3 버킷의 정적 호스팅 기능 활성화하기

버킷 생성

2. 속성 -> 정적 웹사이트 호스팅 편집

정적 웹 사이트 호스팅 편집

3. 퍼블릭에 공개할 수 있는 권한 및 설정 적용

 

퍼블릭 액세스 가능

4. S3 버킷에 샘플 static 웹 사이트 파일을 작성해서 업로드하기

  1. S3 정적 호스팅 웹 주소를 사용해 웹 사이트 동작 확인하기 

  2. 파일 업로드 후 퍼블릭 도메인에 접근

테스트 페이지

5. 도메인 이름을 바꾸고 싶으면 Route 53을 변경해야함.

'CICD > AWS' 카테고리의 다른 글

[AWS] S3 암호화  (0) 2024.07.26
[AWS] S3 버전 관리 및 객체 잠금  (1) 2024.07.26
[AWS] S3 권한 관리  (0) 2024.07.26
[AWS] S3 스토리지 클래스  (1) 2024.07.25
[AWS] Amazon S3 기초  (0) 2024.07.25

+ Recent posts