반응형

1부에서는 LogLy가 어떤 프로젝트인지 소개해드렸죠? 이번 편에서는 좀 더 깊이 들어가서 실제로 어떻게 만들었는지 얘기해볼게요!

API 설계하면서 "아, 이렇게 하면 되겠구나!" 싶었던 것들이 많았는데, 그런 것들 위주로 공유해볼게요 😊

API 만들 때 생각한 것들

처음 API 설계할 때 이런 걸 고민했어요:

  • 직관적이어야 한다: URL만 봐도 뭐 하는 건지 알 수 있게
  • 보안은 필수: 내 노트 남이 못 보게 JWT로 잠궈놓기
  • 에러 메시지는 친절하게: 뭐가 문제인지 바로 알 수 있게
  • 일관성: 응답 형식이 통일되면 프론트 만들기 편하더라고요

그럼 이제 실제 API들을 하나씩 살펴볼까요?


1. 회원가입하고 로그인하기 (/api/auth)

아이디 중복 체크부터!

회원가입하기 전에 아이디 쓸 수 있는지 확인해야죠?

GET /api/auth/check-username?username=coolguy123

이렇게 보내면...

{
    "available": true  // 쓸 수 있어요!
}

 

회원가입 고고!

POST /api/auth/register
Content-Type: application/json

{
    "username": "coolguy123",
    "password": "mysecretpassword"
}

성공하면 이렇게 와요:

{
    "message": "회원가입이 완료되었습니다."
}

간단하죠? ㅎㅎ

로그인은 더 간단!

POST /api/auth/login
Content-Type: application/json

{
    "username": "coolguy123",
    "password": "mysecretpassword"
}

그러면 토큰을 줘요:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

이 토큰이 중요해요! 이제부터 모든 요청에 이걸 붙여서 보내야 해요.
Authorization: Bearer {토큰} 이런 식으로요!


2. 내 정보 관리하기 (/api/user)

이름 바꾸고 싶을 때

PUT /api/user/me
Authorization: Bearer {토큰}
Content-Type: application/json

{
    "username": "newcoolguy"
}

 

이름을 바꾸면 새 토큰을 줘요. 그거 다시 저장하는 거 잊지 마세요!

탈퇴하고 싶을 때 😢

DELETE /api/user/me
Authorization: Bearer {토큰}

주의! 이거 누르면 다 날아가요. 노트, 프로젝트, 템플릿 전부요. 진짜 확실할 때만 누르세요!


3. 프로젝트로 노트 정리하기 (/api/projects)

내 프로젝트 목록 보기

GET /api/projects
Authorization: Bearer {토큰}

이렇게 오죠:

[
    {
        "id": 1,
        "name": "개인 공부",
        "user": {
            "id": 1,
            "username": "coolguy123",
            "email": "cool@example.com",
            "provider": "local"
        }
    },
    {
        "id": 2,
        "name": "회사 업무",
        "user": { ... }
    }
]

새 프로젝트 만들기

POST /api/projects
Authorization: Bearer {토큰}
Content-Type: application/json

{
    "name": "사이드 프로젝트"
}

프로젝트 지우기

DELETE /api/projects/1
Authorization: Bearer {토큰}

참고: 프로젝트 지워도 노트는 안 지워져요! 노트들은 '미분류'로 이동해요. 안심하세요 😊


4. 노트 쓰기! (/api/entries)

여기가 제일 중요한 부분이에요!

노트 하나 작성하기

파일도 첨부할 수 있어서 multipart/form-data로 보내야 해요.

POST /api/entries
Authorization: Bearer {토큰}
Content-Type: multipart/form-data

entry: {
    "title": "오늘 배운 것",
    "content": "<p>Spring Boot 재미있다!</p>",
    "researcher": "나",
    "tags": ["개발", "공부"]
}
projectId: 1
file: [파일 선택]

내 노트 보기

전체 노트:

GET /api/entries?projectId=all

프로젝트별로 보기:

GET /api/entries?projectId=1

정리 안 된 노트들:

GET /api/entries?projectId=uncategorized

검색하기:

GET /api/entries?search=Spring

검색하면 제목, 내용, 작성자, 태그 전부 다 찾아줘요!

노트 자세히 보기

GET /api/entries/5
Authorization: Bearer {토큰}

노트 수정하기

PUT /api/entries/5
Authorization: Bearer {토큰}
Content-Type: multipart/form-data

entry: {
    "title": "오늘 배운 것 (수정)",
    "content": "<p>React도 재미있다!</p>",
    "researcher": "나",
    "tags": ["개발", "완료"]
}
projectId: 2
file: [새 파일]

꿀팁: 수정하면 이전 버전이 자동으로 저장돼요! 나중에 복구할 수 있어요 👍

노트 지우기

DELETE /api/entries/5
Authorization: Bearer {토큰}

에디터에 이미지 넣기

글 쓰다가 이미지 바로 넣고 싶을 때:

POST /api/entries/images
Authorization: Bearer {토큰}
Content-Type: multipart/form-data

image: [이미지 파일]

그러면 URL을 줘요:

{
    "url": "/uploads/images/abc123.jpg"
}

이걸 에디터에 넣으면 끝!


5. 실수해도 괜찮아! 버전 관리 기능

이거 만들면서 제일 뿌듯했어요 ㅎㅎ

이전 버전들 보기

GET /api/entries/5/versions
Authorization: Bearer {토큰}

이렇게 나와요:

[
    {
        "id": 1,
        "title": "첫 번째 버전",
        "content": "<p>처음 쓴 내용</p>",
        "researcher": "나",
        "tags": ["개발"],
        "versionTimestamp": "2024-01-15T10:30:00"
    },
    {
        "id": 2,
        "title": "두 번째 버전",
        "content": "<p>수정한 내용</p>",
        "researcher": "나",
        "tags": ["개발", "수정"],
        "versionTimestamp": "2024-01-16T14:20:00"
    }
]

예전 버전으로 되돌리기

POST /api/entries/5/versions/1/restore
Authorization: Bearer {토큰}

안심 포인트: 복구하기 전에 지금 상태도 버전으로 저장해요. 완전 안전!


6. 템플릿으로 편하게! (/api/templates)

똑같은 형식을 계속 쓸 때 편해요.

내 템플릿 보기

GET /api/templates
Authorization: Bearer {토큰}

템플릿 만들기

POST /api/templates
Authorization: Bearer {토큰}
Content-Type: application/json

{
    "name": "회의록",
    "content": "<h1>회의록</h1><p>날짜: </p><p>참석자: </p><p>안건: </p>"
}

템플릿 지우기

DELETE /api/templates/1
Authorization: Bearer {토큰}

만들면서 배운 것들 📚

JWT는 편한데 조심해야 해요

JWT는 서버에 저장 안 해도 돼서 좋은데, 클라이언트에서 잘 관리해야 해요. 지금은 LocalStorage에 저장했는데, 나중에 보안 강화하려면 HttpOnly 쿠키 쓰는 게 나을 것 같아요.

파일 업로드는 생각보다 간단!

처음엔 복잡할 줄 알았는데, Spring Boot의 @RequestPart 쓰니까 생각보다 쉽더라고요. JSON이랑 파일을 같이 보내는 것도 어렵지 않았어요!

버전 관리는 데이터베이스 설계가 중요!

처음엔 어떻게 만들지 고민 많이 했어요. 결국 EntryVersion 테이블을 따로 만들었는데, 나중에 보니 이게 정답이더라고요.

검색 기능, 생각보다 중요해요

노트가 많아지니까 검색이 진짜 필요하더라고요. 지금은 데이터베이스에서 바로 검색하는데, 나중에 Elasticsearch 같은 거 써보고 싶어요.


이제 뭘 만들까요? 🚀

LogLy 만들면서 정말 많이 배웠어요. 이제 추가하고 싶은 기능들:

  • 🔍 더 강력한 검색: Elasticsearch 도입해보기
  • 📱 모바일 최적화: 핸드폰에서도 편하게
  • 🤝 공유 기능: 친구들이랑 노트 같이 보기
  • 🎨 다크모드: 눈 편하게!
  • 📊 대시보드: 내가 얼마나 열심히 쓰는지 보기
  • 🔔 알림 기능: 중요한 노트 놓치지 않게

혹시 "이런 기능도 있으면 좋겠어요!" 하는 게 있으면 댓글로 알려주세요! 🙏


마무리하며

긴 글 읽어주셔서 정말 감사해요! 😊

처음에는 "그냥 메모장 하나 만들자" 했는데, 하다 보니까 이것저것 넣고 싶어져서 여기까지 왔네요 ㅎㅎ

코드가 궁금하신 분들은 댓글 남겨주세요. GitHub에 올릴지 고민 중이에요!

다음에는 프론트엔드 개발기도 한번 써볼게요. React로 UI 만드는 것도 재미있더라고요!

그럼 다음에 또 만나요! 👋

반응형
반응형

안녕하세요! 👋

요즘 메모장 앱이 너무 많아서 어떤 걸 써야 할지 모르겠더라고요. 그래서 생각했습니다. "내가 직접 만들면 되지 않을까?" 😅

이렇게 시작된 프로젝트가 바로 LogLy입니다!

개인적으로 쓰려고 만들었는데, 생각보다 재미있어서 이렇게 개발 과정을 공유해보려고 해요.


LogLy가 뭐냐면요?

간단히 말하면 나만의 똑똑한 노트 앱이에요. 그냥 메모만 쓰는 게 아니라 이런 것들이 가능합니다:

  • 📝 노트 쓰고, 수정하고, 삭제하고 (기본 중의 기본!)
  • 📁 프로젝트별로 노트 정리하기
  • 📎 파일도 첨부할 수 있어요 (이미지, 문서 등등)
  • 🎨 자주 쓰는 형식은 템플릿으로 저장
  • ⏱️ 실수로 지워도 괜찮아요! 버전 관리 기능이 있거든요
  • 🔍 검색도 당연히 됩니다

처음엔 간단하게 만들려고 했는데... 하나하나 추가하다 보니까 이렇게 됐네요 ㅎㅎ


어떤 기술로 만들었나요?

백엔드는 Spring Boot로!

사실 처음엔 Node.js도 고민했는데, Spring Boot를 선택한 이유가 있어요:

  • 안정적이에요: 이미 많은 기업에서 쓰고 있으니까 믿을 수 있죠
  • 개발이 빨라요: Spring Boot가 알아서 설정을 많이 해줘서 편해요
  • 자료가 많아요: 막히면 구글링하면 다 나와요 👍

주요 기술 스택:

  • 언어: Java (역시 자바는 안정적이에요)
  • 빌드 도구: Gradle (Maven보다 빠르고 좋더라고요)
  • 데이터베이스: MariaDB (무료고 MySQL이랑 호환돼서 선택!)
  • 인증: JWT (요즘 대세죠)
  • 소셜 로그인: Google OAuth2 (구글 계정으로 로그인!)

프론트엔드는 React.js로!

요즘 프론트엔드는 React 아니면 안 되죠! (물론 다른 것도 좋지만...)

  • 언어: JavaScript (TypeScript는 나중에...)
  • 패키지 매니저: npm
  • 스타일링: CSS + Bootstrap (디자이너가 아니라서... 😅)

React 쓰니까 컴포넌트 재활용하기 좋고, 화면 업데이트도 빠르고 좋더라고요!

로그인은 어떻게 하나요?

귀찮은 거 싫어하는 분들 많잖아요? 그래서 두 가지 방법을 준비했어요:

1. 그냥 일반 로그인

  • 아이디랑 비밀번호로 가입하면 끝!
  • JWT 토큰으로 보안도 챙겼어요

2. 구글 계정으로 간편 로그인

  • 구글 계정 있으시면 클릭 한 번이면 끝
  • 귀찮은 회원가입 과정 생략!

개인적으로는 구글 로그인이 편해서 저도 그걸로 쓰고 있어요 ㅋㅋ

JWT 쓰니까 서버 부담도 줄고, API 만들기도 편하더라고요. 나중에 모바일 앱 만들 때도 같은 API 쓸 수 있을 것 같아요!

파일도 올릴 수 있어요!

노트 쓰다 보면 이미지나 파일 첨부하고 싶을 때 있잖아요? 그래서 이것도 만들었어요:

  • 노트에 파일 첨부: 각 노트당 파일 하나씩 첨부 가능
  • 에디터에 이미지 넣기: 글 쓰면서 이미지 바로바로 넣을 수 있어요
  • 서버에 안전하게 저장: 파일 잃어버릴 걱정 없어요!

특히 에디터에서 이미지 바로 넣는 기능이 편해요. 복사-붙여넣기처럼 간단하게!

다음 편 예고 🎬

이번 편에서는 LogLy가 어떤 프로젝트인지 소개해드렸어요!

다음 편에서는 좀 더 기술적인 얘기를 해볼게요:

  • API는 어떻게 설계했는지
  • 회원가입/로그인은 어떻게 구현했는지
  • 노트 CRUD는 어떻게 만들었는지
  • 버전 관리 기능은 어떻게 동작하는지

코드 예제랑 함께 자세히 설명해드릴 예정이니까 기대해주세요! 😊

반응형
반응형

📁 파일 및 디렉토리 관련 명령어

기본 탐색 명령어

# 현재 디렉토리 확인
pwd

# 디렉토리 내용 보기
ls              # 기본 목록
ls -l           # 상세 정보 포함
ls -la          # 숨김 파일까지 포함
ls -lh          # 파일 크기를 사람이 읽기 쉬운 형태로

# 디렉토리 이동
cd /path/to/dir # 절대 경로로 이동
cd ..           # 상위 디렉토리로
cd ~            # 홈 디렉토리로
cd -            # 이전 디렉토리로

파일/디렉토리 생성 및 삭제

# 디렉토리 생성
mkdir dirname           # 단일 디렉토리 생성
mkdir -p path/to/dir    # 중간 경로까지 모두 생성

# 파일 생성
touch filename          # 빈 파일 생성
touch file1 file2 file3 # 여러 파일 동시 생성

# 복사
cp source dest          # 파일 복사
cp -r source dest       # 디렉토리 복사 (재귀적)
cp -p source dest       # 권한과 시간 정보 유지

# 이동/이름 변경
mv oldname newname      # 파일명 변경
mv file /path/to/dest   # 파일 이동

# 삭제
rm filename             # 파일 삭제
rm -r dirname           # 디렉토리 삭제 (재귀적)
rm -f filename          # 강제 삭제
rm -rf dirname          # 디렉토리 강제 삭제 (주의!)

📄 파일 내용 확인 명령어

파일 내용 보기

# 전체 내용 보기
cat filename            # 파일 전체 출력
less filename           # 페이지 단위로 보기
more filename           # 페이지 단위로 보기 (less보다 기능 제한적)

# 일부 내용 보기
head filename           # 앞부분 10줄 출력
head -n 20 filename     # 앞부분 20줄 출력
tail filename           # 뒷부분 10줄 출력
tail -n 20 filename     # 뒷부분 20줄 출력
tail -f filename        # 실시간으로 추가되는 내용 확인 (로그 모니터링)

파일 검색

# 파일 찾기
find /path -name "*.txt"        # 특정 확장자 파일 찾기
find /path -type f -name "file" # 파일만 찾기
find /path -type d -name "dir"  # 디렉토리만 찾기
find /path -size +10M           # 10MB보다 큰 파일 찾기

# 명령어 위치 찾기
which command           # 명령어 실행 파일 위치
whereis command         # 명령어, 소스, 매뉴얼 위치

# 파일 내용에서 검색
grep "pattern" filename         # 패턴과 일치하는 줄 찾기
grep -i "pattern" filename      # 대소문자 구분 없이 찾기
grep -r "pattern" /path         # 디렉토리 내 모든 파일에서 재귀 검색
grep -n "pattern" filename      # 줄 번호와 함께 출력

🔒 권한 및 소유권 관리

권한 변경

# chmod: 파일 권한 변경
chmod 755 filename      # rwxr-xr-x 권한 설정
chmod u+x filename      # 소유자에게 실행 권한 추가
chmod g-w filename      # 그룹에서 쓰기 권한 제거
chmod o=r filename      # 기타 사용자를 읽기 전용으로 설정

# 권한 번호 의미
# 4: 읽기(r), 2: 쓰기(w), 1: 실행(x)
# 755 = 소유자(7=4+2+1), 그룹(5=4+1), 기타(5=4+1)

소유권 변경

# chown: 소유자 변경
chown user filename             # 소유자만 변경
chown user:group filename       # 소유자와 그룹 변경
chown -R user:group dirname     # 디렉토리와 하위 모든 파일의 소유권 변경

# chgrp: 그룹만 변경
chgrp group filename

⚙️ 시스템 관리 명령어

프로세스 관리

# 프로세스 확인
ps                      # 현재 터미널의 프로세스
ps aux                  # 모든 프로세스 상세 정보
ps -ef                  # 모든 프로세스 (다른 형식)

# 실시간 프로세스 모니터링
top                     # 실시간 프로세스 정보
htop                    # top의 향상된 버전 (설치 필요)

# 프로세스 종료
kill PID                # 프로세스 ID로 종료
kill -9 PID             # 강제 종료
killall process_name    # 프로세스 이름으로 모두 종료

시스템 정보

 
# 시스템 기본 정보
uname -a                # 시스템 정보 전체
uname -r                # 커널 버전
hostname                # 호스트명

# 디스크 사용량
df -h                   # 파일시스템 사용량 (사람이 읽기 쉬운 형태)
du -h dirname           # 디렉토리 크기
du -sh dirname          # 디렉토리 총 크기만

# 메모리 정보
free -h                 # 메모리 사용량
cat /proc/meminfo       # 상세 메모리 정보

네트워크 관련

# 네트워크 연결 확인
ping hostname           # 연결성 테스트
ping -c 4 hostname      # 4번만 ping

# 네트워크 정보
ifconfig               # 네트워크 인터페이스 정보
ip addr show           # 네트워크 인터페이스 정보 (최신)
netstat -tuln          # 열린 포트 확인

🗂️ 아카이브 및 압축

tar 명령어

# 압축하기
tar -czf archive.tar.gz files/      # gzip으로 압축
tar -cjf archive.tar.bz2 files/     # bzip2로 압축
tar -cJf archive.tar.xz files/      # xz로 압축

# 압축 풀기
tar -xzf archive.tar.gz             # gzip 압축 해제
tar -xjf archive.tar.bz2            # bzip2 압축 해제
tar -xJf archive.tar.xz             # xz 압축 해제

# 내용 확인
tar -tzf archive.tar.gz             # 압축 파일 내용 목록 확인

기타 압축 도구

 
# gzip/gunzip
gzip filename           # 파일 gzip 압축
gunzip filename.gz      # gzip 압축 해제

# zip/unzip
zip -r archive.zip files/           # zip 압축
unzip archive.zip                   # zip 압축 해제
unzip -l archive.zip                # zip 파일 내용 목록

📝 텍스트 처리 명령어

정렬 및 중복 제거

# 정렬
sort filename           # 알파벳 순 정렬
sort -n filename        # 숫자 순 정렬
sort -r filename        # 역순 정렬

# 중복 제거
uniq filename           # 인접한 중복 줄 제거
sort filename | uniq    # 정렬 후 중복 제거

텍스트 조작

# cut: 열 추출
cut -d':' -f1 /etc/passwd           # ':' 구분자로 첫 번째 필드 추출
cut -c1-10 filename                 # 1-10번째 문자 추출

# sed: 스트림 편집기
sed 's/old/new/' filename           # 첫 번째 매치만 치환
sed 's/old/new/g' filename          # 모든 매치 치환
sed '5d' filename                   # 5번째 줄 삭제

# awk: 패턴 스캐닝 및 처리
awk '{print $1}' filename           # 첫 번째 필드만 출력
awk -F':' '{print $1}' /etc/passwd  # ':' 구분자로 첫 번째 필드 출력

🔧 유용한 조합 명령어

파이프와 리다이렉션

# 파이프 (|): 명령어 결과를 다음 명령어의 입력으로
ls -l | grep "^d"                   # 디렉토리만 필터링
ps aux | grep python                # python 프로세스만 검색
cat /var/log/syslog | tail -20      # 로그 파일의 마지막 20줄

# 리다이렉션
command > file          # 출력을 파일에 저장 (덮어쓰기)
command >> file         # 출력을 파일에 추가
command < file          # 파일을 입력으로 사용
command 2> error.log    # 오류만 파일에 저장

실무에서 자주 사용하는 조합

# 가장 큰 파일 찾기
find /path -type f -exec ls -lh {} + | sort -k5 -hr | head -10

# 특정 확장자 파일에서 문자열 검색
find . -name "*.txt" -exec grep -l "search_term" {} \;

# 디렉토리별 용량 확인 (크기 순 정렬)
du -sh */ | sort -hr

# 로그 파일에서 특정 시간대 에러 찾기
grep "ERROR" /var/log/app.log | grep "2024-01-15"

자주 나오는 옵션들

  • ls -la: 숨김 파일 포함 상세 정보
  • rm -rf: 디렉토리 강제 삭제
  • cp -r: 디렉토리 재귀 복사
  • grep -r: 재귀 검색
  • find -name: 파일명으로 찾기
  • chmod 755: 권한 설정
  • tar -czf: gzip 압축으로 묶기

헷갈리기 쉬운 부분

  • mv는 이동과 이름 변경 모두 가능
  • less와 more의 차이 (less가 더 많은 기능)
  • head와 tail의 기본값은 10줄
  • find에서 -name은 파일명, -type은 파일 유형
  • 권한 숫자: 4(읽기) + 2(쓰기) + 1(실행)
반응형
반응형

🧩 들어가며

현대의 자바 기반 애플리케이션에서 데이터 접근 계층은 단순한 SQL 실행 그 이상을 요구받고 있습니다.
객체 지향 언어인 Java와 관계형 데이터베이스(RDB) 사이의 간극을 효율적으로 연결해주는 기술이 바로 JPA(Java Persistence API) 입니다.

이번 글에서는 실무 관점에서 JPA가 왜 필요한지, 어떤 구조로 동작하는지, 그리고 실질적으로 우리가 어떻게 다뤄야 하는지에 대해 깊이 있는 시선으로 정리해보려 합니다.


🔍 JPA란 무엇인가?

JPA는 Java 진영의 ORM(Object Relational Mapping) 표준 명세입니다.
즉, 자바 객체 ↔ 관계형 데이터베이스 사이의 매핑을 선언적으로 처리할 수 있도록 도와주는 인터페이스 모음이죠.

💡 Hibernate, EclipseLink, OpenJPA는 JPA의 구현체입니다.
스프링부트에서 주로 사용하는 건 Hibernate이며, JPA를 추상 레이어로 사용합니다.


📐 왜 JPA인가?

1. SQL 중심 개발의 한계

  • 중복되는 SQL
  • 비즈니스 로직에 쿼리 로직이 섞임
  • 테이블 구조 변경 시 코드 유지보수 어려움
  • 객체와 테이블 간의 불일치

2. 객체 지향적으로 설계된 애플리케이션의 요구

  • 컬렉션 기반의 연관 관계 관리
  • 캡슐화된 비즈니스 메서드
  • 영속성 생명주기와 트랜잭션 추적

👉 이를 해결하기 위해 JPA는 다음과 같은 추상화를 제공합니다.


🧱 핵심 개념 정리

🗃️ Entity

@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @Column(unique = true)
    private String email;
}

 

  • 클래스 자체가 데이터베이스 테이블과 매핑됩니다.
  • @Id, @Column, @Table 등은 모두 매핑 메타데이터입니다.

🔄 EntityManager

JPA의 핵심 동작을 담당하는 인터페이스.
Hibernate의 Session과 유사한 개념으로, 영속성 컨텍스트를 관리합니다.

EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();

User user = em.find(User.class, 1L);
user.setName("변경된 이름");

em.getTransaction().commit();

 

📌 주의: Spring Data JPA에서는 직접 EntityManager를 다룰 일은 거의 없습니다. 대신, Repository가 이를 추상화합니다.


📦 영속성 컨텍스트 (Persistence Context)

  • 엔티티 객체를 1차 캐시에 보관
  • 같은 트랜잭션 내 동일 객체 반환 (== 동일성 보장)
  • 변경 감지(Dirty Checking) → flush 시 자동 update
User user = em.find(User.class, 1L);  
user.setName("홍길동"); // 별도 update 쿼리 없이도 자동 감지됨

🧠 Dirty Checking & Flush

  • Dirty Checking: 엔티티 객체의 변경 여부 추적
  • Flush: 변경된 내용을 SQL로 동기화 (트랜잭션 커밋 시 자동 수행)
em.flush(); // DB에 SQL 전송

🏗️ Spring Data JPA와의 관계

Spring Data JPA는 JPA의 Repository 패턴을 자동화한 구현체입니다.
즉, JpaRepository 인터페이스만 상속받으면 기본적인 CRUD는 따로 SQL 없이 구현됩니다.

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}


🚀 커스텀 쿼리는 @Query 어노테이션으로 처리하거나, QueryDSL, Specification으로 확장 가능


🧬 연관관계 매핑

예시: 회원과 주문 (1:N)

@Entity
public class Member {

    @Id
    private Long id;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}

@Entity
public class Order {

    @Id
    private Long id;

    @ManyToOne
    private Member member;
}

 

  • 양방향 매핑 시 mappedBy 설정 필수
  • 지연 로딩(LAZY)이 기본값이므로 주의

⚠️ 실무에서 자주 하는 실수

항목 설명
양방향 매핑 남용 단방향으로도 충분한 경우가 많음
즉시 로딩(EAGER) 사용 성능 저하, N+1 문제 발생 가능
식별자 전략 잘못 사용 GenerationType.IDENTITY는 제약이 있음
트랜잭션 없이 EntityManager 사용 변경 감지 미동작

 


🎯 마무리

JPA는 단순히 SQL을 안 쓰기 위한 도구가 아닙니다.
도메인 모델을 중심으로 한 객체 지향 아키텍처를 구현하기 위한 전략이며,
이는 결국 유지보수성과 생산성을 극대화합니다.

Spring Boot 3와 함께 JPA를 적절히 활용하면,
비즈니스 로직에 집중할 수 있는 유연하고 강력한 백엔드 아키텍처를 구성할 수 있습니다.

 

반응형

'Spring Boot' 카테고리의 다른 글

Spring Boot 3의 Repository, Service, Controller 흐름  (3) 2025.07.19
JWT  (0) 2024.01.26
스프링 시큐리티  (0) 2024.01.26
front + backend 게시판 CRUD 구현 (1)  (0) 2023.10.19
반응형

안녕하세요, 오늘은 스프링부트(Spring Boot) 3에서 가장 기본이자 핵심!
바로 Repository → Service → Controller 구조에 대해
재미있고 직관적으로 설명해보겠습니다 😎


🧭 흐름 먼저 보고 가자

Controller (API 입구)
   ↓
Service (비즈니스 로직)
   ↓
Repository (DB 연결)

 

  • Controller: "누가 요청했어? 무슨 데이터가 필요해?" → API 요청을 받는 문지기
  • Service: "오케이, 이 요청 처리해줄게!" → 핵심 로직 처리 담당
  • Repository: "데이터 줘! 저장도 해줘!" → DB와 소통하는 영업사원

🧱 각각 뭐하는 앤데?

1. 🎮 Controller — API의 입구이자 전면 배너

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public UserDto getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

 

  • 클라이언트가 /api/users/1 호출하면 여기로 들어옴.
  • 요청 파라미터 확인하고, 서비스에 “요거 처리 좀” 요청함.

Tip: @RestController = JSON 응답을 반환하는 컨트롤러


2. 🧠 Service — 진짜 ‘일’하는 핵심 로직 덩어리

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserDto getUserById(Long id) {
        User user = userRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("유저 없음!"));
        return new UserDto(user);
    }
}
  • DB에 직접 접근은 안 해요! Repository한테 시켜요~
  • 예외 처리, 데이터 가공, 트랜잭션 처리 등 실질적인 비즈니스 로직 담당!

Tip: @Service 붙이면 스프링이 빈으로 관리해줌 (IoC/DI)


3. 🗃️ Repository — 진짜 DB랑 통신하는 데이터 엔지니어

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // 커스텀 쿼리도 만들 수 있어요
    Optional<User> findByEmail(String email);
}
  • JPA를 통해 CRUD 메서드를 자동으로 제공받음
  • DB에게 “user 테이블에서 이거 가져와!”라고 요청하는 역할

Tip: JpaRepository 덕분에 findAll(), save(), delete() 같은 메서드는 이미 다 있음.

스프링부트는 복잡한 설정 없이도 효율적인 구조로 개발할 수 있게 도와줘요.
하지만 구조의 의도를 정확히 이해하고 써야 실무에서도 "개발자 맛집" 되는 거죠 🍜

반응형

'Spring Boot' 카테고리의 다른 글

JPA 제대로 이해하기 — 객체 지향 개발자의 데이터 접근 전략  (4) 2025.07.19
JWT  (0) 2024.01.26
스프링 시큐리티  (0) 2024.01.26
front + backend 게시판 CRUD 구현 (1)  (0) 2023.10.19
반응형

안녕하세요, 이번 SQLD 57회 시험을 응시하고 합격한 후기를 작성하도록 하겠습니다~!

저는 이제 1년차 풀스텍 개발자로 일하고 있습니다! 자기개발과 개발 역량 강화를 목표로, SQL 실력을 높이고 싶어

SQLD 시험에 도전했습니다.

 

1. 공부 자료 & 방식

SQLD 시험을 준비하기 위해선 여러 후기들을 살펴보면 노랭이 책을 가장 많이 추천합니다.

노랭이 책이 SQLD 시험 주관 기간에서 발행한 책이라 수험자 분들이 많이 이 책으로 시험에 대비한다고 합니다.

저는 노랭이 책 대신 SQLD의 모든 것이라는 책을 가지고 시험 공부를 했습니다.

우선 노랭이 책보다 개념설명도 잘되어있기도 하고 기출문제 및 시험대비 문제 해설 유튜브 영상도 있어서 어려운 노랭이 책으로 공부하는 것 보다 쉽게 대비할 수 있었습니다.

유튜브 강의는 여기를 보고 2~3회 반복하였습니다.

https://www.youtube.com/watch?v=TN4syS7dyEk&list=PLDI0745yTBjXFuIFYqq3vzcQYuVyajFpC

 

🗓 스터디 루틴

  • 주 3회, 챕터별 공부 및 실습
  • 주말에 반드시 ‘모의고사 1회 이상’ 풀기
  • 틀린 문제 모아 ‘오답 노트’로 핵심 체크

우선 SQLD를 공부하기 위해선 반복적인 학습이 중요하다고 생각합니다. 함수에 대한 개념을 한번만으로 기억하기 어렵기도 하였고 

DB 툴 (DBeaver 나 기타 DB 툴..)을 이용하여 직접 쿼리를 쳐보고 결과를 보는 것이 많은 도움이 되었습니다.

또한 회사에서 SQL 쿼리를 자주 작성하고 테스트 해보기 때문에 시험에 많은 도움이 되었습니다.

매일 조금씩, 꾸준히 하면, DB 실력 + 자격증이라는 두 마리 토끼도 잡을 수 있습니다!

반응형
반응형

Source : Apple

안녕하세요, 여러분! 👋

오늘은 애플이 야심 차게 내놓은 새로운 인터페이스 디자인, 바로 리퀴드 글래스(Liquid Glass)에 대해 이야기를 나눠보려 해요. iOS 26, iPadOS 26, macOS 26 등 모든 애플 OS에 공통으로 적용되며, 진짜 유리판처럼 보이고 반응하는 UI 디자인인데요. 그냥 예쁘기만 한 게 아니라 기술적으로도 꽤 놀라운 요소들이 많답니다. 개발자 입장에서 리퀴드 글래스를 어떻게 바라봐야 할지, 그리고 사용자 경험에는 어떤 영향을 미치는지 자세히 파헤쳐볼게요! 🔍


리퀴드 글래스가 뭐야?

한 마디로 말하면, "유리처럼 보이는 UI"입니다. 그냥 투명한 게 아니라 반투명하고, 배경을 흐리게 비추고, 빛에 따라 반짝이기도 하죠. 아이폰이나 아이패드에서 앱을 열었을 때, 메뉴나 버튼 같은 요소들이 마치 얇은 유리판처럼 보여요. 특히 이번 디자인은 기기마다 일관되면서도 상황에 따라 반응하는 역동적인 UI를 강조하고 있어요.

이전 세대 플랫 디자인과는 다르게, 이번엔 다시 유리 질감을 소프트웨어로 불러온 셈이에요. 스큐어모피즘(옛날 가죽 질감 UI 같은 거)처럼 아날로그를 그대로 모방하진 않지만, 현실 세계의 유리를 재해석해서 현대적인 감각으로 풀어낸 게 핵심이죠.

 

Source : Apple

 


기술적으로 뭐가 새로워?

아무래도 개발자라면 이런 게 궁금하죠. 겉보기만 번지르르한 게 아니라, 내부적으로도 꽤 진지한 기술이 들어가 있어요. 몇 가지 핵심 포인트만 콕 집어볼게요:

✅ 반투명 + 실시간 블러

UI 요소마다 가우시안 블러 효과가 들어가서 배경을 흐릿하게 비춥니다. 단순히 불투명도 조절이 아니라 실시간으로 배경 픽셀을 샘플링해서 흐림 효과를 적용해요. 예전 iOS 7에도 있긴 했지만, 이번엔 퀄리티가 훨씬 높아졌어요.

✅ 빛 반사 + 하이라이트 애니메이션

아이콘이나 버튼 위에 광택이 반사되는 느낌, 보셨나요? 이건 자이로센서와 연동된 실시간 쉐이더 덕분이에요. 기기를 기울이면 반짝이는 위치도 미묘하게 변해서, 물리적인 유리를 만지는 듯한 생동감을 줍니다.

✅ 굴절 효과 (Refraction)

UI 뒤에 있는 콘텐츠가 유리를 통해 보이는 것처럼 살짝 휘어져 보여요. 완전 고급 기술! 진짜 유리를 통해 배경을 보면 약간 왜곡되듯이, 그걸 소프트웨어로 구현해낸 거죠.

✅ 물방울 애니메이션

예를 들어 시계 앱 하단 탭을 누르면, 물방울 같은 포인터가 탭 사이를 굴러다녀요. 이건 그냥 UI가 아니라, 인터랙션 자체를 유동적인 액체처럼 표현한 케이스입니다. 시각적 피드백이 대단해요.

Source : Apple

사용자 경험은 어떨까?

시각적으로도 멋지지만, 진짜 중요한 건 UX죠. 몇 가지 포인트를 정리해볼게요:

  • 콘텐츠 집중: 메뉴나 알림이 화면을 완전히 가리지 않고 반투명하게 나타나니까, 사용자가 콘텐츠 흐름을 잃지 않아요.
  • 몰입감 + 감성 자극: 홈 화면에서 아이콘들이 배경을 살짝 비추면 그 자체로 아름다움 + 생동감이 살아나요.
  • UI 이해도 상승: 움직임이 실제 물체처럼 반응하니, 기능이 어떻게 작동할지 직관적으로 알 수 있어요.

물론 단점도 있어요. 밝은 배경에 밝은 텍스트가 뜨면 가독성이 떨어질 수 있고, 너무 많은 블러나 반짝임이 시각적 과부하로 이어질 수도 있죠. 다행히 접근성 옵션에서 투명도를 줄일 수 있게 배려한 것도 좋아요.

Source : Apple

기기별로 다른 점은?

📱 아이폰(iOS)

손 안의 작은 화면에서도 리퀴드 글래스가 빛나요. 알림 배너, 잠금 화면 시계, 앱 아이콘 전부 유리처럼 표현돼요. 특히 아이콘 테마를 "클리어"로 바꾸면 전체가 투명 유리 같아서 엄청 미래지향적인 느낌!

💻 맥(Mac)

맥에선 조금 절제된 방식으로 적용됐어요. 메뉴 바, 파인더 사이드바 등에서 유리 질감이 은은하게 표현되고, 아이콘 틴트 기능으로 통일감 있는 인터페이스도 구현할 수 있어요. 하지만 역시 데스크탑 특성상, 생산성 저하 없도록 많이 조절했더라고요.

📱 아이패드

멀티태스킹에 강한 아이패드에선 리퀴드 글래스가 더 실감나게 작동해요. 여러 앱을 스플릿 뷰로 띄워도 사이드바나 도구 패널이 반투명하게 표현돼서 화면이 넓고 쾌적해 보이죠. Apple Pencil 쓰는 앱에서도 UI가 안 가리고 잘 보이게 디자인되어 있어요.

Source : Apple


마무리하며 ✨

애플의 리퀴드 글래스 디자인은 단순한 UI 변경이 아니라, 하드웨어의 발전을 등에 업은 인터페이스의 진화라고 봐도 무방해요. 특히 개발자 입장에선 새로운 디자인 트렌드에 맞춰 앱 UI를 어떻게 재구성할지 고민할 필요가 있는 시점입니다.

앞으로 애플이 AR 기기, Vision Pro 같은 차세대 플랫폼으로 확장해 나갈 때도 이 리퀴드 글래스 디자인 언어는 계속 이어질 가능성이 높아요. 지금 적응해두면, 미래에 훨씬 유리(!)할 수도 있겠죠? 😉

그럼 다음에 또 기술적으로 재밌는 주제로 찾아올게요! 블로그 구독과 댓글은 언제나 환영입니다 👨‍💻💬

반응형
반응형
SQL 자주 발생하는 오류 총정리

💥 SQL에서 자주 나타나는 오류 총정리! (실무 & 시험 대비)

SQL 초보부터 중급자까지 꼭 알아야 할 SQL 오류 케이스 TOP 8을 실전 예제와 함께 정리했습니다!

ORA-00904: invalid identifier

원인: 존재하지 않는 컬럼명을 조회하려 할 때

SELECT empnmae FROM employees;

해결: 컬럼명 오타 확인 (예: empname)

ORA-00936: missing expression

원인: SELECT, WHERE 등에서 표현식이 빠짐

SELECT FROM employees;

해결: SELECT 다음에는 반드시 컬럼명이 와야 함

ORA-00933: SQL command not properly ended

원인: SQL 문이 올바르게 끝나지 않음

UPDATE employees SET salary = 5000
WHERE employee_id = 100
-- 세미콜론 빠짐
    

해결: SQL 문 끝에 ; 확인!

ORA-00911: invalid character

원인: 허용되지 않는 문자 포함

SELECT * FROM employees WHERE last_name = 'O'Brien';

해결: 작은따옴표는 두 번 사용 'O''Brien'

ORA-01722: invalid number

원인: 숫자로 변환 불가능한 값을 숫자형 컬럼에 비교

SELECT * FROM employees WHERE salary = 'abc';

해결: 숫자형 컬럼에는 숫자만, 문자열은 CAST 사용

ORA-00937: not a single-group group function

원인: GROUP BY 없이 집계함수와 일반 컬럼을 같이 사용

SELECT department_id, AVG(salary)
FROM employees;
    

해결:

SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id;
    

ORA-00001: unique constraint violated

원인: PK 또는 UNIQUE 컬럼에 중복 값 입력

INSERT INTO departments (department_id, department_name)
VALUES (10, 'Sales'); -- 이미 존재하는 ID
    

해결: 중복되지 않는 값 입력

ORA-02291: integrity constraint violated - parent key not found

원인: 자식 테이블에서 참조하는 부모 키가 없음

INSERT INTO employees (employee_id, manager_id)
VALUES (300, 9999); -- manager_id 9999가 없음
    

해결: 부모 테이블에 해당 키가 있는지 먼저 확인

🧠 시험 꿀팁 요약 테이블

오류 코드 기억 포인트
ORA-00904오타? 컬럼명 확인
ORA-00936SELECT 절 점검
ORA-00933세미콜론 확인
ORA-00911문자열 escape
ORA-01722숫자형 확인
ORA-00937GROUP BY 추가
ORA-00001중복 입력 방지
ORA-02291FK 참조 키 확인

✨ 마무리

SQL은 작은 오타 하나로도 오류가 날 수 있어요. 에러 메시지를 잘 읽고 원인을 유추하는 연습이 중요합니다! 😊

반응형

'SQL > SQL_이론' 카테고리의 다른 글

SQL문의 실행순서  (0) 2024.09.19
트랜잭션(Transaction)  (0) 2024.09.19
SQL의 종류  (1) 2024.09.19
관계형 데이터베이스와 테이블  (0) 2024.09.19
SELECT 문  (0) 2024.06.25
반응형

🧠 SQL 정규화(Normalization) 완전 정복: 제1정규형 ~ 제3정규형까지!

안녕하세요! 오늘은 SQLD 시험과 실무에서 모두 중요한 데이터베이스 정규화(Normalization) 개념에 대해 다뤄보겠습니다.

정규화란? 👉 데이터 중복을 제거하고 이상(anomaly)을 방지하여 데이터베이스 구조를 논리적으로 정리하는 과정입니다.

이번 글에서는 제1정규형부터 제3정규형까지 예제와 함께 아주 자세히 설명드릴게요. 📚✨


✅ 정규화가 필요한 이유

정규화가 되지 않은 테이블은 아래와 같은 문제를 일으킬 수 있습니다:

  • 삽입 이상: 일부 속성만 입력할 수 없음
  • 삭제 이상: 일부 데이터를 삭제하면 관련 정보도 같이 사라짐
  • 갱신 이상: 데이터를 일부 수정할 때 여러 군데 수정을 해야 함 → 무결성 깨질 수 있음

🧩 예제 테이블 (비정규형)

학번 이름 연락처 수강과목
1001 홍길동 010-1234-5678 DB, 운영체제
1002 김영희 010-2345-6789 자료구조
1003 이철수 010-3456-7890 DB, 자료구조, 통계학

위 테이블은 비정규형(unnormalized form)입니다. 왜냐하면 하나의 셀(수강과목)에 여러 개의 값이 들어있기 때문입니다. 그럼 정규화를 단계별로 진행해볼게요!


🔹 제1정규형 (1NF: First Normal Form)

정의: 모든 속성의 값이 원자값(Atomic Value)을 가져야 한다.

하나의 셀에는 하나의 값만 존재해야 함

📌 변환 후 테이블

학번 이름 연락처 수강과목
1001 홍길동 010-1234-5678 DB
1001 홍길동 010-1234-5678 운영체제
1002 김영희 010-2345-6789 자료구조
1003 이철수 010-3456-7890 DB
1003 이철수 010-3456-7890 자료구조
1003 이철수 010-3456-7890 통계학

✅ 효과

  • 원자값만 남기므로 검색이 쉬워짐
  • 하지만 여전히 중복된 정보(이름, 연락처 등)가 존재함

🔹 제2정규형 (2NF: Second Normal Form)

정의: 제1정규형을 만족하면서, 기본키의 부분집합이 결정자가 되는 종속성이 없어야 함 (부분함수 종속 제거)

즉, 복합키인 경우 부분키에만 종속된 속성 제거

📌 예시 분석

  • 기본키: (학번, 수강과목)
  • 이름, 연락처는 학번에만 종속되어 있음 → 부분함수 종속 → 2NF 위반!

📌 2NF로 분해된 테이블

학생 테이블

학번 이름 연락처
1001 홍길동 010-1234-5678
1002 김영희 010-2345-6789
1003 이철수 010-3456-7890

수강 테이블

학번 수강과목
1001 DB
1001 운영체제
1002 자료구조
1003 DB
1003 자료구조
1003 통계학

✅ 효과

  • 부분함수 종속 제거
  • 중복 데이터가 줄어듦

🔹 제3정규형 (3NF: Third Normal Form)

정의: 제2정규형을 만족하면서, 이행적 함수 종속이 없어야 함

A → B, B → C 이면 A → C는 이행적 종속. 이걸 제거해야 3NF!

📌 예시 테이블 (추가된 속성)

학번 수강과목 교수명
1001 DB 김교수
1002 자료구조 이교수
1003 통계학 박교수
  • 교수명은 수강과목에 따라 결정됨 → 학번 → 수강과목 → 교수명 → 이행적 종속!

📌 3NF로 분해된 테이블

수강 테이블

학번 수강과목
1001 DB
1002 자료구조
1003 통계학

과목 테이블

수강과목 교수명
DB 김교수
자료구조 이교수
통계학 박교수

✅ 효과

  • 이행적 종속 제거 → 유지보수 편해짐
  • 데이터 무결성 보장

📝 마무리 정리

정규형 정의 목적 제거대상
1NF 모든 속성이 원자값 셀마다 하나의 값 반복 속성 (다중값)
2NF 부분함수 종속 제거 키에 완전 종속된 속성만 유지 부분 종속
3NF 이행적 함수 종속 제거 비속성 간 종속 제거 이행 종속

정규화는 단순히 암기하는 게 아니라, 데이터를 얼마나 구조적으로 잘 관리할 수 있느냐를 보여주는 지표입니다.

반응형
반응형

📘 SQL 관리 구문 완벽 정리: DDL, DML, DCL, TCL 한눈에 이해하기!

SQLD, 실무, 면접에서도 자주 나오는 핵심 개념 바로 SQL의 관리 구문들입니다. 오늘은 SQL에서 명령어들을 기능별로 분류한 DDL, DML, DCL, TCL에 대해 아주 자세하게 정리해드릴게요. 이 글 하나로 완벽 정리 끝내세요! 💪


🧱 1. DDL (Data Definition Language)

데이터 정의어: 데이터베이스의 구조(스키마)를 정의하거나 수정할 때 사용하는 명령어입니다.

📌 주요 명령어

명령어 설명
CREATE 테이블, 인덱스, 뷰 등 객체 생성
ALTER 테이블 구조 수정 (컬럼 추가/삭제 등)
DROP 객체 삭제 (테이블, 인덱스 등)
TRUNCATE 테이블의 모든 데이터를 빠르게 삭제 (롤백 불가!)

✅ 특징

  • 자동 커밋이 발생함 (ROLLBACK 불가)
  • 객체 자체를 다루므로 주의해서 사용해야 함

🧾 2. DML (Data Manipulation Language)

데이터 조작어: 테이블에 저장된 데이터를 조회하거나 조작할 때 사용하는 구문입니다.

📌 주요 명령어

명령어 설명
SELECT 데이터 조회 (읽기 전용)
INSERT 새로운 데이터 삽입
UPDATE 기존 데이터 수정
DELETE 기존 데이터 삭제

✅ 특징

  • 트랜잭션 처리 대상 → COMMIT / ROLLBACK 가능
  • 실무에서 가장 많이 사용되는 SQL 구문

🛡️ 3. DCL (Data Control Language)

데이터 제어어: 데이터베이스 사용자나 권한을 관리/통제할 때 사용하는 구문입니다.

📌 주요 명령어

명령어 설명
GRANT 사용자에게 권한 부여
REVOKE 부여한 권한 회수

✅ 특징

  • 보안/접근 제어에 중요함
  • 사용자마다 데이터 접근을 제한할 수 있음

🔁 4. TCL (Transaction Control Language)

트랜잭션 제어어: DML 작업의 실행 결과를 확정 또는 취소할 때 사용하는 구문입니다.

📌 주요 명령어

명령어 설명
COMMIT 변경 사항을 DB에 영구 반영
ROLLBACK 변경 사항 취소, 이전 상태로 복원
SAVEPOINT 트랜잭션 내 중간 지점 설정 → 이후 해당 지점까지 ROLLBACK 가능

✅ 특징

  • 오직 DML과 함께 사용
  • DDL은 COMMIT이 자동으로 발생하므로 TCL의 대상이 아님

💡 예제 시나리오로 이해하기

-- 테이블 생성 (DDL)
CREATE TABLE member (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(50)
);

-- 데이터 입력 (DML)
INSERT INTO member VALUES (1, '홍길동');

-- 변경 사항 저장 (TCL)
COMMIT;

-- 권한 부여 (DCL)
GRANT SELECT ON member TO user1;

📚 한눈에 정리 

분류 이름 주요 명령어 대상 특징
DDL 데이터 정의어 CREATE, ALTER, DROP, TRUNCATE 객체 자동 COMMIT 발생
DML 데이터 조작어 SELECT, INSERT, UPDATE, DELETE 데이터 트랜잭션 처리 가능
DCL 데이터 제어어 GRANT, REVOKE 사용자/권한 보안/접근 제어
TCL 트랜잭션 제어어 COMMIT, ROLLBACK, SAVEPOINT 트랜잭션 DML 작업 제어용

📝 SQLD 시험 대비 꿀팁!

  • TRUNCATE는 DDL이다! (DELETE와 다르게 ROLLBACK 안됨)
  • DCL은 사용자의 권한을 조정한다는 포인트 꼭 기억
  • TCL은 DML과 세트처럼 외우기 → COMMIT은 INSERT/UPDATE/DELETE 후 저장용

 

반응형
반응형

🔍 정규표현식(Regular Expression) 완벽 가이드

안녕하세요,  오늘은 SQLD 과목 중에서도 헷갈릴 수 있는 정규표현식(Regex)에 대해 정리해보겠습니다. 


✅ 정규표현식이란?

  • 정규표현식(Regular Expression)은 문자열에서 특정한 규칙(패턴)을 가진 문자열을 찾거나 비교할 때 사용하는 표현식입니다.
  • 문자열 검색 / 추출 / 유효성 검증 등에 활용
  • DB에서 REGEXP, REGEXP_LIKE와 함께 출제될 수 있음

🧱 기본 기호 및 의미 정리

기호 의미 상세설명 예시
. 임의의 한 문자 어떤 문자든 상관없이 1개 a.b → “acb”, “a1b” 등
* 0개 이상 반복 앞 문자가 0번 이상 나올 수 있음 bo* → “b”, “bo”, “boo” 등
+ 1개 이상 반복 앞 문자가 1번 이상 반복 bo+ → “bo”, “boo” 등 (“b”는 불일치)
? 0개 또는 1개 앞 문자가 0번 또는 1번 나타남 colou?r → “color”, “colour” 모두 매칭
[] 문자 집합 대괄호 안의 문자 중 하나를 의미 [abc] → “a”, “b”, “c” 중 하나
[^] 부정 문자 집합 대괄호 안에 있는 문자를 제외한 문자 [^abc] → a, b, c 제외한 문자
` ` OR 조건 두 패턴 중 하나
() 그룹핑 괄호 안 패턴을 하나의 단위로 묶음 (ab)+ → “ab”, “abab” 등 반복 가능

📍 위치 지정자 (Anchors)

기호 의미 상세 설명 예시
^ 문자열 시작 해당 문자/패턴이 문자열의 시작에 있어야 함 ^abc → “abc123”은 매칭, “123abc”는 불일치
$ 문자열 끝 해당 문자/패턴이 문자열의 끝에 있어야 함 xyz$ → “endxyz”는 매칭, “xyzend”는 불일치

🔢 반복 수량자 (Quantifiers)

표현식 의미 상세 설명
{n} n번 반복 앞 문자가 정확히 n번 반복됨
{n,} n번 이상 반복 앞 문자가 최소 n번 이상 반복됨
{n,m} n ~ m번 반복 앞 문자가 n번 이상 m번 이하 반복됨

예시: a{2,4} → “aa”, “aaa”, “aaaa”는 매칭, “a”나 “aaaaa”는 불일치


🧠 실무에서는 어떻게 쓰일까?

1. 다음 중 이메일 형식에 가장 적절한 정규표현식

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$
    •   1개 이상 반복, \. : 점(.) 문자, ^, $는 시작과 끝 의미

2. 010 또는 011로 시작하는 핸드폰 번호 정규식

^01[0-9]-?[0-9]{3,4}-?[0-9]{4}$
  • ?는 하이픈이 있어도 되고 없어도 되는 선택 옵션

📚 SQL에서 정규표현식 관련 함수 (REGEXP / REGEXP_LIKE / REGEXP_SUBSTR)

📌 1. REGEXP

  • MySQL 등에서 사용하며, 문자열이 정규표현식과 일치하면 TRUE 반환
SELECT *
FROM users
WHERE email REGEXP '^[a-z0-9]+@[a-z]+\\\\.[a-z]{2,3}$';

📌 2. REGEXP_LIKE

  • Oracle에서 주로 사용, LIKE보다 정교한 문자열 매칭 가능
SELECT *
FROM users
WHERE REGEXP_LIKE(email, '^[a-z0-9._%+-]+@[a-z0-9.-]+\\\\.[a-z]{2,}$');

📌 3. REGEXP_SUBSTR

  • 문자열 중 정규표현식에 일치하는 부분 문자열만 추출할 때 사용

📘 문법

REGEXP_SUBSTR(문자열, 정규표현식 [, 시작위치 [, 발생순서 [, 일치방식 [, 플래그]]]])

✔ 예시

SELECT REGEXP_SUBSTR('My phone: 010-1234-5678', '\\d{3}-\\d{4}-\\d{4}') AS phone
FROM dual;
  • 결과: 010-1234-5678
  • 숫자와 하이픈으로 구성된 전화번호를 추출

또는 이메일 주소 중 도메인만 추출할 때:

SELECT REGEXP_SUBSTR('user@example.com', '@[a-z.]+') AS domain
FROM dual;
  • 결과: @example.com

📝 SQLD 암기 포인트 정리표

포인트 설명
. 아무 문자 1개 (도트 = 점 하나!)
* 0번 이상 반복 (없어도 되고 많아도 됨)
+ 1번 이상 반복 (하나는 꼭 있어야 함)
? 0개 또는 1개 (있거나 없거나)
^, $ 문자열의 시작과 끝 위치 지정
[] 괄호 안 문자 중 하나 선택 (선택박스 느낌)
() 그룹핑 (묶어서 하나의 단위로 처리)
{} 반복 횟수 제어용 수량자
REGEXP_LIKE 오라클에서 정규표현식 조건 검사할 때 사용
REGEXP_SUBSTR 일치하는 문자열을 추출할 때 사용

🎯 마무리 정리

  • 정규표현식은 기호의 의미, 패턴의 구성 방식, 간단한 검증 정규식 관련 문제로 출제됩니다.
  • REGEXP, REGEXP_LIKE, REGEXP_SUBSTR 함수는 문자열 패턴을 조건으로 주거나 추출할 때 핵심입니다.
  • 복잡한 정규식보다는 각 기호의 기능을 정확히 알고 적용하는 것이 핵심입니다.

 

반응형
반응형

📊 SQL PIVOT / UNPIVOT 완전 정복! 실무 & 시험에 모두 나오는 핵심 개념

안녕하세요, 오늘은 데이터 집계와 변환에서 자주 활용되는 PIVOTUNPIVOT 절에 대해 알아보겠습니다. 실무에서 리포트를 만들거나, 시험에서 형태 변환 관련 문제가 나올 때 정말 유용한 기능이니 꼭 숙지해두세요!


🔄 PIVOT 절이란?

PIVOT은 행(row) 데이터를 열(column)로 바꾸는 기능입니다. 즉, 세로 데이터를 가로로 펼쳐서 보기 쉽게 만들어 줍니다.

✅ 기본 문법 (Oracle 기준)

SELECT *
FROM (
  SELECT 부서, 직급, 급여 FROM employee
)
PIVOT (
  SUM(급여) FOR 직급 IN ('사원' AS staff, '대리' AS assistant, '과장' AS manager)
);

💡 해석:

  • 내부 서브쿼리에서 부서, 직급, 급여를 뽑고
  • 직급을 기준으로 열로 변환하며,
  • 각 직급의 급여 합계를 컬럼별로 보여줍니다.

📌 결과 예시:

부서 staff assistant manager
총무부 3000 4000 5000
영업부 2800 NULL 5200

🔃 UNPIVOT 절이란?

UNPIVOT은 열(column) 데이터를 행(row)으로 바꾸는 기능입니다. 즉, 가로로 되어 있는 데이터를 세로로 펼쳐서 상세하게 분석할 수 있게 합니다.

✅ 기본 문법

SELECT *
FROM (
  SELECT 부서, staff, assistant, manager FROM pivoted_data
)
UNPIVOT (
  급여 FOR 직급 IN (staff AS '사원', assistant AS '대리', manager AS '과장')
);

💡 해석:

  • staff, assistant, manager라는 열을
  • 직급과 급여라는 두 개의 열로 변환합니다.

📌 결과 예시:

부서 직급 급여
총무부 사원 3000
총무부 대리 4000
총무부 과장 5000
영업부 사원 2800
영업부 과장 5200

💡 NULL 값은 UNPIVOT시 자동으로 제거되는 경우가 많습니다. 필요 시 INCLUDE NULLS 옵션도 사용 가능합니다.


📝 실무 사용 팁

  • PIVOT은 집계 함수(SUM, AVG 등)와 함께 사용하면 요약표 만들기에 좋습니다.
  • UNPIVOT은 다양한 지표를 한 컬럼에 모아 비교 분석할 때 유용합니다.

📚 시험 대비 암기 팁

기능 암기법
PIVOT Pivot → “열로 회전!” (P자로 Pivot 회전 상상)
UNPIVOT Unpivot → “행으로 다시 풀어!”
FOR 절 무엇을 기준으로 바꿀지!
IN 절 어떤 항목들로 열/행을 만들지!

✅ 마무리 정리

  • PIVOT: 행 데이터를 열로 변환 → 요약표, 리포트에 딱!
  • UNPIVOT: 열 데이터를 행으로 변환 → 정규화, 비교 분석에 유리!

 

반응형

+ Recent posts