PJT
개발 트러블슈팅 및 지식 정리 위키
1. Git & 버전 관리
Q. Merge된 PR(Pull Request)을 취소하고 싶습니다.
A. git revert를 사용하여 안전하게 취소합니다.
reset은 협업 중인 브랜치의 역사를 지우므로 위험합니다. revert는 “취소했다는 기록”을 남기는 새로운 커밋을 생성합니다.
# 1. Merge Commit Hash 확인
git log --oneline
# 2. Revert 실행 (-m 1 옵션 필수: 메인라인 유지)
git revert -m 1 <Merge_Commit_Hash>
# 3. 원격 저장소 반영
git push origin main
Q. Revert 했던 브랜치를 수정해서 다시 Merge 하려는데, 변경 사항이 없다고 뜹니다.
A. “Revert 커밋”을 다시 Revert (Revert of Revert) 해야 합니다. Git은 이미 한 번 합쳐졌다가 취소된 코드라고 인식하므로, “취소했던 행위” 자체를 취소해야 코드가 되살아납니다.
main브랜치 최신화 (git pull)- 이전에 수행했던 Revert 커밋의 Hash 찾기
- 다시 Revert 수행
git revert <이전의_Revert_커밋_Hash>
Q. 원격 저장소(Remote)에서 삭제된 브랜치를 살리고 싶습니다.
A. 상황에 따라 3가지 방법이 있습니다.
- 로컬에 브랜치가 남아있는 경우:
git push origin <브랜치명> - 로컬에서도 삭제한 경우 (Reflog 활용):
git reflog | grep <브랜치명> # 삭제 전 마지막 커밋 Hash 확인 git checkout -b <브랜치명> <커밋_Hash> - PR 페이지 활용: GitHub/GitLab의 Closed PR 페이지 하단
Restore branch버튼 클릭.
Q. 삭제된 브랜치를 복구해서 MR/PR을 올렸는데 “No changes”가 뜹니다.
A. 기존 커밋 ID가 역사에 남아있어 Git이 무시하는 상황입니다. 새로운 커밋 ID를 생성해야 합니다.
- 방법 1 (정석): 작업했던 커밋만
cherry-pick하여 새 브랜치로 이동. - 방법 2 (간편): 해당 시점의 파일 내용을 강제로 가져와서 덮어쓰기.
# 특정 커밋 시점의 모든 파일을 현재 브랜치로 가져옴 (뒤에 점 '.' 필수)
git checkout <되돌릴_커밋_ID> -- .
# 이후 커밋 & 푸시
git commit -m "Force restore files"
git push origin <브랜치명>
Q. .gitignore에 .idea나 .vscode를 넣었는데도 적용이 안 되거나, 하위 폴더가 무시되지 않습니다.
A. 폴더명 뒤에 슬래시(/)를 붙여야 하며, 루트 .gitignore에서 관리하는 것이 좋습니다.
올바른 작성법:
# 모든 경로의 .idea 폴더 무시
.idea/
# 모든 경로의 .vscode 폴더 무시
.vscode/
이미 커밋된 파일이 있다면 캐시 삭제 필요:
git rm -r --cached .
git add .
git commit -m "Refresh gitignore"
2. 네트워크 & 서버 구조
Q. 웹 소켓 서버에 클라이언트가 계속 붙으면, 서버 포트를 계속 새로 여나요?
A. 아니요, 서버 포트는 단 하나(예: 8080)만 사용합니다. TCP 연결은 5-tuple에 의해 유일하게 식별되므로, 서버 포트가 같아도 클라이언트의 IP와 Port가 다르면 서로 다른 연결로 구분됩니다.
연결 식별 요소 (5-tuple):
{ 프로토콜, 서버 IP, 서버 Port, 클라이언트 IP, 클라이언트 Port }
따라서 포트 고갈(Port Exhaustion)은 서버가 아닌 클라이언트 측에서 주로 발생하거나, 서버의 파일 디스크립터(File Descriptor) 제한에 걸리는 경우가 더 많습니다.
3. Java 개발
Q. ThreadLocalRandom.current()는 랜덤 숫자를 반환하나요?
A. 아니요, 현재 쓰레드 전용의 “랜덤 생성기 객체(Instance)”를 반환합니다. 실제 값을 얻으려면 객체를 얻은 후 메서드를 호출해야 합니다.
올바른 사용법:
// 객체를 얻고 -> 값을 뽑는다
int randomValue = ThreadLocalRandom.current().nextInt(0, 10);
사용 이유: 멀티 쓰레드 환경에서 java.util.Random은 경합(Contention)으로 인해 성능 저하가 발생하지만, ThreadLocalRandom은 쓰레드별로 격리되어 있어 성능이 훨씬 우수합니다.