Today's Codekata
class Solution {
public String solution(String s) {
String answer = "";
int num = s.length() / 2;
if (s.length() % 2 == 0) {
answer = s.substring(num - 1, num + 1);
} else if (s.length() % 2 != 0) {
answer = String.valueOf(s.charAt(num));
}
return answer;
}
}
class Solution {
public String solution(int n) {
String answer = "";
String[] waterMelon = {"수", "박"};
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
answer += waterMelon[0];
} else {
answer += waterMelon[1];
}
}
return answer;
}
}
SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE YEAR(JOINED) = 2021 AND AGE BETWEEN 20 AND 29;
SELECT ANIMAL_ID, NAME,
CASE WHEN SEX_UPON_INTAKE LIKE 'Neutered%' THEN 'O'
WHEN SEX_UPON_INTAKE LIKE 'Spayed%' THEN 'O'
ELSE 'X' END AS "중성화"
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;
코드카타 미션들을 처음 마주하는 순간엔 정말 방법이 안 보이는데, 하나하나 쪼개서 생각해보고 만들어가다보면 그것들을 연결하는 작업을 통해 정답에 도달하는 것 같다. 결과는 많이 부족하다고 생각하지만 스스로 답을 찾아가는 과정이 뿌듯하다. 다른 사람들 풀이를 통해서 사고가 넓어지는 느낌이 든다.
Today I Learned
SQL로 Pivot Table 만들어보기
select restaurant_name,
max(if(hh='15', cnt_order, 0)) "15",
max(if(hh='16', cnt_order, 0)) "16",
max(if(hh='17', cnt_order, 0)) "17",
max(if(hh='18', cnt_order, 0)) "18",
max(if(hh='19', cnt_order, 0)) "19",
max(if(hh='20', cnt_order, 0)) "20"
from
(
select a.restaurant_name,
substring(b.time, 1, 2) hh,
count(1) cnt_order
from food_orders a inner join payments b on a.order_id=b.order_id
where substring(b.time, 1, 2) between 15 and 20
group by 1, 2
) a
group by 1
order by 7 desc
음식점별 시간별 주문건수 Pivot Table 뷰 만들기 (15~20시 사이, 20시 주문건수 기준 내림차순)
select age,
max(if(gender='male', order_count, 0)) male,
max(if(gender='female', order_count, 0)) female
from
(
select b.gender,
case when age between 10 and 19 then 10
when age between 20 and 29 then 20
when age between 30 and 39 then 30
when age between 40 and 49 then 40
when age between 50 and 59 then 50 end age,
count(1) order_count
from food_orders a inner join customers b on a.customer_id=b.customer_id
where b.age between 10 and 59
group by 1, 2
) t
group by 1
order by 1 desc
성별, 연령별 주문건수 Pivot Table 뷰 만들기 (나이는 10~59세 사이, 연령 순으로 내림차순)
엑셀에서는 주어진 데이터에 단축키 몇번으로 만들어왔다보니 구조를 몰랐는데, SQL에서 코드로 하나하나 만들어보니 어떤 식으로 만들어지는 지 알 수 있었다.
업무 시작을 단축시켜 주는 마법의 문법 (Window Function - RANK, SUM)
Window Function의 기본 구조
window_function(argument) over (partition by 그룹 기준 컬럼 order by 정렬 기준)
select cuisine_type,
restaurant_name,
cnt_order,
ranking
from
(
select cuisine_type,
restaurant_name,
cnt_order,
rank() over (partition by cuisine_type order by cnt_order desc) ranking
from
(
select cuisine_type,
restaurant_name,
count(1) cnt_order
from food_orders
group by 1, 2
) a
) b
where ranking<=3
select cuisine_type,
restaurant_name,
cnt_order,
sum(cnt_order) over (partition by cuisine_type) sum_cuisine,
sum(cnt_order) over (partition by cuisine_type order by cnt_order) cum_cuisine
from
(
select cuisine_type,
restaurant_name,
count(1) cnt_order
from food_orders
group by 1, 2
) a
order by cuisine_type, cnt_order
날짜 포맷과 조건까지 SQL로 한 번에 끝내기 (포맷 함수)
select date(date) date_type, -- 날짜 형식으로 변경
date_format(date(date), '%Y') "년",
date_format(date(date), '%m') "월",
date_format(date(date), '%d') "일",
date_format(date(date), '%w') "요일"
from payments
select date_format(date(date), '%Y') as "년",
date_format(date(date), '%m') as "월",
date_format(date(date), '%Y.%m') as "년월",
count(1) "주문건수"
from food_orders f inner join payments p on f.order_id = p.order_id
where date_format(date(date), '%m') = '03'
group by 1, 2, 3
order by 1 desc
SQL 마지막 과제까지 클리어
select cuisine_type,
max(if(age=10, cnt_order, 0)) "10대",
max(if(age=20, cnt_order, 0)) "20대",
max(if(age=30, cnt_order, 0)) "30대",
max(if(age=40, cnt_order, 0)) "40대",
max(if(age=50, cnt_order, 0)) "50대"
from
(
select f.cuisine_type,
case when age between 10 and 19 then 10
when age between 20 and 29 then 20
when age between 30 and 39 then 30
when age between 40 and 49 then 40
when age between 50 and 59 then 50 end age,
count(1) cnt_order
from food_orders f inner join customers c on f.customer_id=c.customer_id
where age between 10 and 59
group by 1, 2
) a
group by 1;
이번 SQL 학습을 통해 백엔드 개발에서 데이터가 어떻게 흐르고 처리되는지를 좀 더 구체적으로 이해할 수 있었다. 단순히 SELECT 문으로 값을 조회하는 것을 넘어서, 조건에 따라 데이터를 그룹화하고 분류하며 원하는 형식으로 가공하는 과정이 얼마나 중요한지 깨달았다. 특히 Pivot Table 구성, 날짜 포맷 처리, 윈도우 함수 같은 기능들을 직접 SQL로 구현해보면서 엑셀에서 감춰져 있던 로직들이 코드로 드러나는 경험이 새로웠다. 아직 자바 백엔드에서 SQL이 어떤 식으로 함께 쓰이는지에 대한 감은 없지만, 어떤 식으로 연동되는지 배울 날이 기대된다. 단순히 데이터를 “불러오는” 게 아니라, 원하는 데이터를 정확히 뽑고 가공해서 효율적으로 전달하는 작업의 핵심이 SQL이라는 걸 느낀 시간이었다.
API & ERD
API는 Application Programming Interface의 약자로 프로그램끼리 서로 정보를 주고 받을 수 있게 해주는 소통 창구 같은 것이다. 대표적인 예시로 REST API가 있다. REST는 Representational State Transfer의 약자로, 자원을 표현하고 상태를 주고받는 아주 간단하고 직관적인 웹 통신 방식이다. RESTful API 라고도 부르는데 쉽게 풀어보면 웹 브라우저와 서버가 대화하는 방식을 정해 놓은 규칙 같은 것이다. 이를 통해 개발자들이 서로 다른 시스템을 연결할 때 더 깔끔하고 일관성 있게 코드를 짤 수 있다. HTTP를 통해 소통하게 되고 get(조회) put(수정) post(등록) delete(삭제) 같은 메서드들이 있다. PathVariable({중괄호 안에 있는 값})은 자원 식별자로 쓰이는 경우가 많고, RequestParam( ?뒤에 붙는 Query String)는 검색 조건이나 필터링 옵션처럼 선택적 정보를 줄 때 활용된다. 각각 필수값과 조건값이라고도 볼 수 있다.
ERD(Entity Relationship Diagram)는 데이터베이스의 설계도이다!
Spring 기초!
네트워크
인터넷은 TCP/IP 프로토콜 기반의 전 세계 컴퓨터 네트워크 통신망이다.
컴퓨터 간 데이터는 IP 주소를 통해 대상 기기를 식별하여 Packet 단위로 전달된다.
IP: 연결 상태나 데이터 손실을 감지하지 못해 신뢰성이 낮다.
TCP: 3-way handshake 과정을 거쳐 연결을 확인하고 패킷 순서 및 수신 여부를 보장한다.
UDP: 연결 없이 빠르게 데이터를 전달하며 실시간성과 속도에 초점을 둔다. IP와 차이점으로 PORT가 존재한다.
PORT 번호는 같은 IP 내에서 다양한 프로그램을 식별하는 역할을 한다.
TCP/UDP 모두 PORT를 사용하며, 0~1023번은 예약된 포트로 일반적으로 사용을 피한다. [HTTP(80), HTTPS(443) 등]
TCP는 신뢰성 우선, UDP는 속도 우선이라는 점에서 활용 목적이 다르다.
Web 기초
DNS는 사람이 기억하기 쉬운 도메인을 실제 IP 주소로 변환해주는 시스템이다.
URI는 웹 자원을 식별하는 문자열이며, URL과 URN을 포함한다.
URL은 자원의 위치를 나타내고, 일반적으로 도메인과 프로토콜을 함께 사용한다.
URL은 위치 변경에 민감하여, 이를 보완하기 위해 URN이 등장했다. 웹에서는 대부분 URL이 URI의 형태로 사용된다.

용어 모음집
| 용어 | 설명 |
| snake_case | 언더바(_)로 단어 연결, Python과 DB에서 자주 사용됨 |
| camelCase | 첫 단어는 소문자, 이후 단어는 대문자로 시작. 변수 및 함수명에 사용됨 |
| PascalCase | 모든 단어 첫 글자 대문자. 클래스 명명에 주로 사용됨 |
| kebab-case | 하이픈(-)으로 단어 연결. 소문자 사용. 주로 URL이나 설정 파일에 사용 |
| JSON | 클라이언트-서버 간 통신을 위한 데이터 포맷. 가볍고 언어 독립적임 (key-value 형태) |
| MSA | 마이크로서비스 아키텍처. 서비스 단위를 작게 나눠 유연하게 통신 |
| Scale Up | 단일 서버 성능 향상 (CPU, 메모리 등). 수직적 확장으로 처리 속도 증가 |
| Scale Out | 서버 수를 늘림. 수평적 확장으로 동시 처리량 증가 |
| Stateful | 클라이언트 상태를 서버가 기억함. 같은 서버가 유지되어야 하며 리소스를 많이 소비함 |
| Stateless | 클라이언트 상태를 서버가 기억하지 않음. 서버 확장에 유리하고 요청 시 필요한 정보만 전달 |
| Connection | 클라이언트와 지속적인 연결 유지. 응답 속도 빠르지만 자원 소모 많음 |
| Connectionless | 요청이 있을 때만 연결. 자원 효율적 사용, 응답 속도는 상대적으로 느릴 수 있음 |
| HTTP 지속 연결 | 여러 요청이 끝날 때까지 연결 유지. 연결 횟수 줄여 속도를 개선함 |
HTTP
HTTP(HyperText Transfer Protocol)란 텍스트, 이미지, JSON 등 다양한 데이터를 주고받는 인터넷 통신 규약이다. 기본적으로 Stateless(무상태), Connectionless(비연결) 방식으로 작동한다. 주로 사용하는 버전은 HTTP/1.1 (TCP 기반), 최근엔 HTTP/2, 3도 증가하는 추세다. 클라이언트-서버 구조로 UI는 클라이언트가, 비즈니스 로직은 서버가 담당함으로 독립적 개발이 가능하다.
Stateless(무상태): 서버가 클라이언트의 이전 상태를 기억하지 않음 → 확장에 유리하지만, 매 요청에 상태 정보가 포함되어야 함.
Connectionless(비연결): 요청마다 연결을 새로 맺음 → 자원 효율적이지만 속도 저하 가능성 존재
Persistent Connection(HTTP 지속 연결): 하나의 연결로 여러 요청 처리 → 성능 향상 (HTML + CSS + JS + 이미지 등)
HTTP Message 구조
# 요청 메시지(Request)
Start Line: Method + Path + Version
Headers: 요청 정보 (Host, User-Agent, 등)
Empty Line: 필수로 한 줄 공백
Message Body: 요청 데이터 (POST의 경우 JSON 등)
# 응답 메시지(Response)
Start Line: Version + Status Code + Status Text
Headers: 응답 정보 (Content-Type, Set-Cookie, 등)
Empty Line
Message Body: 서버가 보내는 실제 데이터
HTTP 메서드
GET: 데이터 조회, Query String 사용 가능
POST: 데이터 생성, Body에 데이터 포함 가능
PUT: 전체 리소스 덮어쓰기, 존재 여부와 관계 없이 처리
PATCH: 리소스 일부 수정
DELETE: 리소스 삭제
기타 메서드: HEAD, OPTIONS, CONNECT, TRACE 등도 있다.
HTTP Method 속성
HTTP Method는 안전성(Safe), 멱등성(Idempotent), 캐시가능성(Cacheable) 속성을 가지고 있다.

HTTP Status Code
1xx (정보) - 사용 빈도 낮음
2xx (성공)
3xx (리다이렉션)
4xx (클라이언트 에러)
5xx (서버 에러)
HTTP API 설계 원칙
잘못된 예시 : /create/board, /read/board-list, /update/board/1 등 → 동사 사용 X
올바른 설계 예시
게시글 생성: POST /boards
게시글 1개 조회: GET /boards/{id}
게시글 목록 조회: GET /boards
게시글 수정: PUT,PATCH /boards/{id}
게시글 삭제 DELETE /boards/{id}
HTTP Header
클라이언트와 서버 간 요청/응답 시 부가 정보를 전달하는 텍스트 기반의 메타데이터이다.
구조: field-name: field-value (줄 단위, 대소문자 구분 없음)
개발자 도구 → Network 탭 → 요청 항목 → Headers 탭에서 실제 전송된 헤더를 확인 가능하다.
대표 헤더 유형과 예시
| 분류 | 주요 헤더 | 설명 |
| 표현 헤더 | Content-Type, Content-Encoding, Content-Language | 응답/요청의 데이터 타입, 압축, 언어, 길이 등 |
| 콘텐츠 협상 | Accept, Accept-Encoding, Accept-Charset | 클라이언트가 어떤 형식/언어로 응답을 받고 싶은지 표현 |
| 일반 정보 | User-Agent, Referer, From, Server, Date | 브라우저, 이전 URL, 요청시간 등 통신 환경 파악 가능 |
| 특별 정보 | Host, Location, Allow, Retry-After | 도메인, 리다이렉트 주소, 허용된 HTTP Method 등 |
| 인증 관련 | Authorization, WWW-Authenticate | 인증 요청/응답에 사용됨 |
| 쿠키 관리 | Set-Cookie, Cookie, Secure, HttpOnly, SameSite | 상태 유지를 위한 세션 식별, 보안 옵션 설정 |
| 캐시 관리 | Cache-Control, Last-Modified, Etag, If-Modified-Since | 응답 데이터를 캐시하거나 조건부 요청을 가능하게 함 |
RESTful API
REST를 잘 준수하는 API로 HTTP 프로토콜을 사용하여 클라이언트와 서버 간의 통신을 통해 자원(Resource)을 관리한다. 자원은 고유한 URI로 식별되며, HTTP 메서드(GET, POST, PUT, DELETE 등)를 통해 다양한 작업을 수행하며 요청과 응답은 일반적으로 JSON 또는 XML 형식으로 이루어진다.
자원(Resource): 서버에서 관리되는 객체 (사용자, 상품 등)
URI: 자원의 주소로 명사 형태 사용 /users, /products/1
URI 설계 원칙
명사, 복수형, 소문자 사용 → users, members
계층 구조 표현 → /users/{userId}/items/{itemId}
파일 확장자 포함 X
언더바(_) 대신 하이픈(-) 사용
정렬/필터/페이징은 Query Parameter 활용 → /users?page=2&sort=desc
Maturity Model (성숙도 모델)
Level 0: 단일 URL로 모든 요청 처리
Level 1: 의미 있는 리소스 URI 사용
Level 2: HTTP Method에 따라 동작 구분
Level 3: HATEOAS (응답에 다음 행동 정보 포함)
RESTful API 설계 고려사항
Consumer first: API 사용자의 입장에서 설계
HTTP 활용 극대화: 메서드, 상태코드, 헤더 등 적극 사용
상태코드 활용: 성공/실패 이유를 상태코드와 함께 설명
보안 주의: URI에 사용자 정보 포함 X
명사형 URI + 복수형 사용 → 직관적인 엔드포인트 설계
예외 처리: 일관된 방식으로 정의
마치며
SPRING 기초 내용을 학습하며 아직 모든 개념이 명확하게 잡히진 않았지만, 배워가는 과정이라 생각하고 앞으로 활용해나갈 것들이 기대가 된다. 처음 접하는 용어나 구조들이 생소하지만, 하나하나 정리해 나가며 이런 흐름이구나 느끼는 순간들이 있었다. 앞으로 백 엔드 개발을 더 깊이 배우면서, 지금 배운 기초 지식들을 토대로 스스로 구조를 설계하고 만들어나갈 수 있는 개발자가 되는 걸 목표로 삼고 있다. 지금은 시작에 불과하지만 이 작은 물음표들이 하나둘 쌓여서 내 개발 여정의 로그가 되길 바란다.