[Semi-Project] WebIDE 프로젝트

1. 프로젝트 개요

4달 간 배운 프론트엔드, 백엔드에 대한 리뷰를 진행하고자 프로젝트 진행

 

📆개발 기간 : 2026.01.29 - 2026.02.24

👥개발 인원 : 3명 (BE 2, FE 1)

 

📌역할

  • 팀 리더: 전체 일정 조절
  • 백엔드 엔지니어 : 스프링부트 기반 API 설계 및 Docker를 이용한 코드 샌드박스 구현, CI 파이프라인 구축

🛠️기술 스택

  • AWS S3 : 소스코드를 저장하고 사용자 데이터를 관리하기 위해 도입
  • JPA: 반복적인 SQL 작성 대신 객체 중심의 설계를 통해 비즈니스 로직에 집중하고 개발 속도 향상
  • Docker : 모든 사용자가 로컬 환경에 구애받지 않고 동일한 실행환경을 가지도록 컨테이너 기술 선택
  • github actions : CI 파이프라인을 구축해 코드 통합 시 자동으로 빌드 및 검증 프로세스를 도입해 코드 안정성 확보

2. 핵심 기능과 기술적 도전

🐳[Docker 기반 실행환경]

  • 작성한 파일을 실행했을 경우 도커에 깔려 있는 언어의 버전을 통해 실행했습니다.
  • 개발 인원을 고려해 최소한의 언어(Java, JavaScript)만 선택했습니다.
  • 자바는 컴파일을 한 다음 실행되고 실행되면 만들어진 파일을 삭제하도록 했습니다.
  • 자바스크립트는 컴파일 과정을 거치지 않기 때문에 바로 실행할 수 있었습니다. 
  • EC2 서버에 파일을 생성할 수 있는 폴더를 만들어두고 그 폴더에서 생성되고 삭제되게 했습니다.

📂[프로젝트 공유 기능]

  • 우리의 큰 타이틀은 협업이었기 때문에 협업에 맞춰 프로젝트 공유 기능을 넣어 사용자가 프로젝트를 공유하면 공유받은 사용자는 자신의 프로젝트 목록해서 공유받은 프로젝트를 볼 수 있습니다.
  • 프로젝트 이름이나 파일 이름들은 길지 않기 때문에 데이터베이스에 바로 저장하고 파일 안의 내용들은 S3에 저장해 파일 선택 시 Key로 불러오는 방식을 이용했습니다.

3. 트러블슈팅👀

1. 코드 실행 시 비동기 처리

  • 문제

로컬 환경에서는 코드 실행 버튼을 누르면 결과가 잘 나왔으나, 프론트엔드와 연결하여 실제 웹 환경에서 실행할 때는 결과 화면으로 넘어가지 못하고 무한 로딩에 머무는 현상이 발생했습니다. 또한, 다량의 요청이 몰릴 때 서버 부하로 컨테이너 다운되는 문제가 있었습니다.

 

  • 원인

1. 배포 환경의 도커 부재 : 호스트 서버 내부에서 도커 컨테이너를 동적으로 제어할 수 있는 설정이 없었습니다.

2. 트랜잭션 생명주기 꼬임: 데이터베이스에 실행 요청 정보를 저장하기 전에 @Async 비동기 스레드가 먼저 실행되어, 데이터가 없는 상태에서 조회를 시도되었습니다.

3. 서버 리소스 고사: 동기식 요청 폭주 및 무거운 컨테이너 실행으로 서버가 부하를 견디지 못했습니다.

 

  • 해결

1. DooD 구조 채택: 호스트의 도커 데몬을 공유하여 사용할 수 있도록 배포 설정 시 소켓과 임시 디렉토리를 볼륨 마운트하여 권한 문제를 해결했습니다.

2. 트랜잭션-비동기 시점 정합성 및 무한 루프 방지: 데이터가 DB에 확실히 커밋된 이후 비동기 로직이 안전하게 시작되도록 제어했습니다. 특히, 사용자가 무한 루프 코드를 제출했을 때 서버 자원이 고사하는 것을 막기 위해 Process.waitFor(timeout, unit)을 도입해 타임아웃 제한 5초를 두었습니다. 지정한 시간 내에 프로세스가 끝나지 않으면 강제종료하고 타임아웃 에러를 반환하도록 설계하여 서버의 안정성을 확보했습니다.

*5초를 한 이유는 대부분의 가벼운 코드들은 3초 안에 끝난다고 판단해 3초로 먼저 제한했으나 타임아웃을 3초했을 때도 스레드가 꼬이는 현상이 발생해 5초로 늘렸다.

 

  • 배운점

인프라와 백엔드 로직이 결합할 때 발생할 수 있는 복잡한 에러를 추적하며 시야를 넓힐 수 있었습니다.

특히 무거운 연산을 처리할 때는 UX 측면에서도 동기식보다 비동기식이 필수적이라는 것을 뼈저리게 체감했습니다.

더불어 악의적인 코드나 무한 루프로부터 서버를 보호하기 위해 샌드박스 환경에서 타임아웃을 설정하고 프로세스 생명주기를 제어하는 시스템 엔지니어링 관점을 기를 수 있었습니다.

 

2. 백엔드 첫 도전 : 무작정 시작하기

  • 문제

첫 백엔드 도전이다 보니 기획이 끝나자마자 API 명세서, ERD 등의 문서를 작성했음에도 프론트엔드와 API를 연결할 때 데이터 형식이 맞지 않는 문제가 발생했습니다. 또한, 요구사항이 미세하게 바뀔 때마다 데이터베이스 구조를 수정해야하는 비효율을 겪었습니다.

  • 원인

설계 문서의 필요성은 인지하고 있었으나, "이렇게 작성하는 것이 맞는가?"에 대한 확신이 부족했습니다.

각 문서에 구체적으로 어떤 명세와 제약조건이 들어가야 프론트엔드 및 데이터베이스와 완벽히 싱크가 맞는지 깊이 있게 알지 못했습니다.

  • 해결

문제를 해결하기 위해 팀원 간 교차 검증과 집단 지성을 활용했습니다.

제가 API 명세서의 초안을 작성하고, 다른 백엔드 팀원이 ERD 초안을 작성한 뒤 함께 모여 회의를 진행했습니다. 서로의 문서를 비교하며 누락된 데이터나 비논리적인 구조를 찾아내어 발전시켰고, 최종 합의된 ERD를 바탕으로 데이터베이스를 구축했습니다.

*만들어진 API명세서, ERD는 진행된 멘토링에서 멘토님에게 한 번 더 검증받았다.

이렇게 기초 설계 인프라를 탄탄히 잡고 나니, 이후 개발과정에서는 데이터 구조나 API 형식을 변경해야 하는 일이 극적으로 줄었습니다.

  • 배운점

무작정 코드를 치는 것보다 개발 전 설계와 문서화에 시간을 투자하는 것이 전체 개발 리소스를 줄이고 팀원 간의 소통 비용을 아끼는 가장 확실한 방법임을 배웠습니다.

또한, 완벽하지 않더라도 초안을 만들고 팀원과 적극적으로 소통하며 싱크를 맞춰가는 협업 프로세스의 가치를 깨달았습니다.

 

3. 통일된 환경을 제공하기 위한 도커 사용

  • 문제

로컬 환경과 상관없이 동일한 실행 환경을 만들기 위해 도커를 도입했으나, 테스트를 반복할수록 EC2 서버의 디스크 용량이 부족해 서버가 다운되는 문제가 발생했습니다.

  • 원인

자바 코드를 실행하기 위해 컨테이너 내부에서 컴파일을 진행했는데, 실행이 끝난 후에도 임시 파일과 컨테이너 잔재가 삭제되지 않고 호스트 서버에 누적되었기 때문입니다.

  • 해결

Docker 컨테이너를 실행할 때 종료 후 자동 삭제 옵션(--rm)을 추가했고 호스트 서버에 마운트되어 임시 파일들은 실행 완료 시점에 자바의 파일 삭제 로직을 통해 명시적으로 지워지도록 프로세스 생명주기를 관리했습니다.

 

*실제 프로젝트에 적용한 Docker 실행 ProcessBuilder 코드*

ProcessBuilder pb = new ProcessBuilder(
                    "docker", "run", "--rm",
                    "--stop-timeout", "5",
                    "-v", exeuctionPath.toAbsolutePath() + ":/app",
                    "-w", "/app",
                    imageName,
                    "sh", "-c", command
            );
  • 배운점

인프라 환경을 구축할 때는 기능을 띄우는 것 뿐만 아니라 , 유한한 자원을 안전하게 회수하는 Clean-up과정이 필수적이라는 것을 배웠습니다.

4. 협업 및 프로젝트 관리

  • 디스코드: 코어 타임 상주, 일정 관리, 각자 할 일 및 공유사항 전달 등 메신저로 활용
  • 노션: 마일스톤, API, ERD 등 문서화된 자료 공유

5. 잘한 점과 아쉬운 점

  • 적은 인원이었지만 WebIDE라는 큰 틀에 맞춰 성공적으로 마무리하였습니다.
  • 실시간 협업을 진행하지 못한 것이 아쉬웠는데 지금 생각해보면 새로고침 기반으로 하는 것이 맞는 것 같습니다. 아니면 프로젝트 멤버들 간의 코드가 꼬일 수도 있을 것 같습니다.
    *기회가 된다면 웹소켓이나 CRDT 알고리즘을 이용해 실시간 동시편집도 도전해보고 싶다.
  • API 명세서를 Swagger로 만들어야하는데 만들지 않은게 아쉽습니다. 원래 프론트엔드 개발자에게 전달할 때 스키마를 작성해서 넘겨주면 그걸로 성공적이게 나오는지 확인까지해야하는데 초기에 설정하지 않아서 그냥 넘어가게 되었습니다.
  • git 작성법을 너무 몰랐습니다. 전략 없이 브랜치만 파면서 하면 되는 줄 알았는데 그게 아니라 브랜치를 팔 때 브랜치의 이름에 해당 기능의 특성을 넣었어야 했었습니다.
    *현재는 feat/기능명, fix/버그수정과 같은 Git Flow 전략을 지키며 개발하고 있다.

🌐6. 프로젝트 결과물

aws 비용이 많이나와서 서버를 닫은 상태라 사진으로 대체

로그인 및 회원가입
대시보드
에디터 화면