쪽지발송 성공
Click here
재능넷 이용방법
재능넷 이용방법 동영상편
가입인사 이벤트
판매 수수료 안내
안전거래 TIP
재능인 인증서 발급안내

🌲 지식인의 숲 🌲

🌳 디자인
🌳 음악/영상
🌳 문서작성
🌳 번역/외국어
🌳 프로그램개발
🌳 마케팅/비즈니스
🌳 생활서비스
🌳 철학
🌳 과학
🌳 수학
🌳 역사
해당 지식과 관련있는 인기재능

개인용도의 프로그램이나 소규모 프로그램을 합리적인 가격으로 제작해드립니다.개발 아이디어가 있으시다면 부담 갖지 마시고 문의해주세요. ...

프로그래밍 15년이상 개발자입니다.(이학사, 공학 석사) ※ 판매자와 상담 후에 구매해주세요. 학습을 위한 코드, 게임, 엑셀 자동화, 업...

30년간 직장 생활을 하고 정년 퇴직을 하였습니다.퇴직 후 재능넷 수행 내용은 쇼핑몰/학원/판매점 등 관리 프로그램 및 데이터 ...

* 프로그램에 대한 분석과 설계 구현.(OA,FA 등)* 업무 프로세스에 의한 구현.(C/C++, C#​) * 기존의 C/C++, C#, MFC, VB로 이루어진 프로그...

JavaScript WebRTC: P2P 커뮤니케이션 구현하기

2024-11-17 10:18:49

재능넷
조회수 75 댓글수 0

JavaScript WebRTC: P2P 커뮤니케이션 구현하기 🚀

 

 

안녕하세요, 여러분! 오늘은 정말 핫한 주제로 찾아왔어요. 바로 JavaScript WebRTC를 이용한 P2P 커뮤니케이션 구현에 대해 알아볼 거예요. 이거 진짜 대박이에요! 😎

요즘 시대에 실시간 커뮤니케이션이 얼마나 중요한지 다들 아시죠? 화상 통화, 음성 채팅, 파일 공유... 이 모든 게 WebRTC 기술로 가능해요. 그것도 브라우저에서 바로! 어마어마하지 않나요? 🤯

그럼 이제부터 WebRTC의 세계로 빠져볼까요? 준비되셨나요? 자, 출발~! 🏁

1. WebRTC란 뭐야? 🤔

WebRTC... 이름부터 좀 있어 보이죠? ㅋㅋㅋ 근데 걱정 마세요. 생각보다 어렵지 않아요!

WebRTC는 Web Real-Time Communication의 약자예요. 쉽게 말해서, 웹에서 실시간으로 소통할 수 있게 해주는 기술이에요. 브라우저끼리 직접 연결해서 데이터를 주고받을 수 있게 해주는 거죠.

예를 들어볼까요? 여러분이 친구와 화상 통화를 하고 싶다고 해봐요. 예전에는 특별한 앱을 깔아야 했죠. 근데 WebRTC를 사용하면? 그냥 브라우저만 있으면 돼요! 진짜 편하지 않나요? 😆

WebRTC의 주요 특징:

  • 브라우저 간 직접 통신 (P2P)
  • 별도의 플러그인이나 앱 설치 불필요
  • 오디오, 비디오, 데이터 전송 가능
  • 보안 통신 지원 (암호화)

이렇게 멋진 기술이 있다니, 정말 대단하지 않나요? 근데 잠깐, 여기서 궁금증! 🧐

"그럼 WebRTC는 언제부터 있었던 거예요?"

좋은 질문이에요! WebRTC는 2011년에 구글이 처음 발표했어요. 그 이후로 계속 발전해왔죠. 지금은 거의 모든 주요 브라우저에서 지원하고 있어요. 크롬, 파이어폭스, 사파리, 엣지... 다 된다고요! 👍

재능넷 같은 플랫폼에서도 WebRTC를 활용하면 정말 좋을 것 같아요. 예를 들어, 재능 판매자와 구매자가 실시간으로 화상 상담을 할 수 있다면? 와, 상상만 해도 멋지지 않나요? 😍

WebRTC 개념도 WebRTC Peer A Peer B P2P 직접 통신

이 그림을 보세요. WebRTC가 어떻게 작동하는지 한눈에 들어오지 않나요? Peer A와 Peer B가 중간 서버 없이 직접 연결되는 거예요. 이게 바로 P2P(Peer-to-Peer) 통신의 핵심이에요!

자, 이제 WebRTC가 뭔지 대충 감이 오시나요? 근데 이거 알면 뭐해요, 실제로 써먹을 줄 알아야죠! 그래서 다음 섹션에서는 JavaScript로 WebRTC를 어떻게 구현하는지 자세히 알아볼 거예요. 기대되지 않나요? 😁

그럼 잠깐 쉬었다가 다음으로 넘어가볼까요? 커피 한잔 하고 오세요! ☕ (근데 저는 아메리카노파인데, 여러분은 어떤 커피 좋아하세요? ㅎㅎ)

2. WebRTC의 핵심 컴포넌트 🧩

자, 이제 본격적으로 WebRTC의 핵심 컴포넌트들을 알아볼 차례예요. 이 부분은 좀 기술적일 수 있지만, 최대한 쉽게 설명해드릴게요. 준비되셨나요? 가즈아~! 🚀

WebRTC는 크게 세 가지 주요 API로 구성되어 있어요:

  1. MediaStream (getUserMedia)
  2. RTCPeerConnection
  3. RTCDataChannel

이 세 가지만 알면 여러분도 WebRTC 마스터! 😎 하나씩 자세히 살펴볼까요?

2.1 MediaStream (getUserMedia) 📹

MediaStream API는 사용자의 카메라와 마이크에 접근할 수 있게 해줘요. 쉽게 말해서, 여러분의 얼굴과 목소리를 캡처하는 거죠!

코드로 보면 이렇게 생겼어요:

navigator.mediaDevices.getUserMedia({video: true, audio: true})
  .then(stream => {
    // 스트림을 비디오 엘리먼트에 연결
    videoElement.srcObject = stream;
  })
  .catch(error => {
    console.error('카메라 접근 실패:', error);
  });

이 코드를 실행하면 브라우저가 사용자에게 카메라와 마이크 사용 권한을 요청해요. 허용하면? 짜잔~ 여러분의 모습이 화면에 나타나죠! 😄

🚨 주의사항: 사용자의 프라이버시를 존중해야 해요! 항상 카메라나 마이크 사용 전에 동의를 구하고, 왜 필요한지 설명해주세요.

2.2 RTCPeerConnection 🤝

RTCPeerConnection은 WebRTC의 심장이에요! 이 API가 두 피어(Peer) 간의 연결을 관리해주죠.

연결 과정은 대략 이런 느낌이에요:

  1. 각 피어가 RTCPeerConnection 객체를 생성해요.
  2. 서로의 네트워크 정보(ICE candidate)를 교환해요.
  3. 미디어 스트림 정보(SDP)를 주고받아요.
  4. 연결 성공! 🎉

코드로 보면 이렇게 생겼어요:

const peerConnection = new RTCPeerConnection();

peerConnection.onicecandidate = event => {
  if (event.candidate) {
    // ICE candidate를 상대방에게 전송
    sendToOtherPeer(event.candidate);
  }
};

peerConnection.ontrack = event => {
  // 상대방의 스트림을 받아서 비디오 엘리먼트에 연결
  remoteVideo.srcObject = event.streams[0];
};

// 로컬 스트림 추가
localStream.getTracks().forEach(track => {
  peerConnection.addTrack(track, localStream);
});

어때요? 생각보다 복잡하지 않죠? 😉

2.3 RTCDataChannel 💬

RTCDataChannel은 피어 간에 임의의 데이터를 주고받을 수 있게 해줘요. 텍스트, 파일, 게임 데이터... 뭐든 가능해요!

사용법은 이렇게 생겼어요:

const dataChannel = peerConnection.createDataChannel("myChannel");

dataChannel.onopen = () => {
  console.log("데이터 채널이 열렸어요!");
};

dataChannel.onmessage = event => {
  console.log("받은 메시지:", event.data);
};

// 메시지 보내기
dataChannel.send("안녕하세요!");

이렇게 하면 실시간 채팅, 파일 공유 등을 구현할 수 있어요. 재능넷에서 재능 판매자와 구매자가 실시간으로 대화를 나누거나 파일을 주고받을 때 유용하겠죠? 👍

WebRTC 핵심 컴포넌트 WebRTC MediaStream RTCPeerConnection RTCDataChannel

이 그림을 보세요. WebRTC의 세 가지 핵심 컴포넌트가 어떻게 연결되어 있는지 한눈에 볼 수 있죠? 이 세 가지가 조화롭게 작동해서 우리가 원하는 실시간 통신을 가능하게 만드는 거예요! 👏

자, 이제 WebRTC의 핵심 컴포넌트들을 알아봤어요. 어때요? 생각보다 어렵지 않죠? 😊

다음 섹션에서는 이 컴포넌트들을 실제로 어떻게 사용하는지, 그리고 P2P 연결을 어떻게 구현하는지 자세히 알아볼 거예요. 기대되지 않나요? 🤩

그럼 잠깐 스트레칭 한번 하고 올까요? 🧘‍♀️ (아, 그리고 물 한잔 마시는 것도 잊지 마세요! 💧 코딩할 때 수분 보충 중요해요~)

3. JavaScript로 WebRTC 구현하기 💻

자, 이제 본격적으로 JavaScript를 사용해서 WebRTC를 구현해볼 거예요. 긴장되나요? 걱정 마세요! 천천히, 하나씩 해볼 거예요. 😉

우리가 만들 예제는 간단한 1:1 화상 채팅 앱이에요. 재능넷에서 재능 판매자와 구매자가 직접 얼굴을 보며 대화할 수 있는 그런 앱이죠! 멋지지 않나요? 🤩

3.1 HTML 구조 만들기 🏗️

먼저 기본적인 HTML 구조부터 만들어볼게요. 이게 우리 앱의 뼈대가 될 거예요.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>재능넷 WebRTC 화상 채팅</title>
    <style>
        /* 여기에 CSS 스타일을 추가할 거예요 */
    </style>
</head>
<body>
    <h1>재능넷 WebRTC 화상 채팅</h1>
    <div id="videos">
        <video id="localVideo" autoplay muted></video>
        <video id="remoteVideo" autoplay></video>
    </div>
    <button id="startButton">시작</button>
    <button id="callButton">연결</button>
    <button id="hangupButton">종료</button>

    <script src="app.js"></script>
</body>
</html>

어때요? 별거 없죠? ㅎㅎ 그냥 비디오 태그 두 개와 버튼 세 개예요. 로컬 비디오(자기 얼굴)와 리모트 비디오(상대방 얼굴)를 보여줄 거예요. 버튼들은 각각 시작, 연결, 종료 기능을 할 거구요. 😊

3.2 JavaScript 코드 작성하기 ✍️

이제 진짜 중요한 부분이에요. JavaScript로 WebRTC 기능을 구현할 거예요. 천천히 따라와 주세요!

// 전역 변수 설정
let localStream;
let remoteStream;
let peerConnection;

const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]};

// DOM 요소 가져오기
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const startButton = document.getElementById('startButton');
const callButton = document.getElementById('callButton');
const hangupButton = document.getElementById('hangupButton');

// 버튼 이벤트 리스너 추가
startButton.addEventListener('click', startStream);
callButton.addEventListener('click', startCall);
hangupButton.addEventListener('click', hangup);

// 스트림 시작 함수
async function startStream() {
    try {
        const stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
        localVideo.srcObject = stream;
        localStream = stream;
        startButton.disabled = true;
        callButton.disabled = false;
    } catch (error) {
        console.error('미디어 스트림 생성 실패:', error);
    }
}

// 연결 시작 함수
async function startCall() {
    callButton.disabled = true;
    hangupButton.disabled = false;

    peerConnection = new RTCPeerConnection(configuration);

    localStream.getTracks().forEach(track => {
        peerConnection.addTrack(track, localStream);
    });

    peerConnection.ontrack = event => {
        remoteVideo.srcObject = event.streams[0];
        remoteStream = event.streams[0];
    };

    peerConnection.onicecandidate = event => {
        if (event.candidate) {
            // 여기서 ICE candidate를 시그널링 서버를 통해 상대방에게 전송해야 해요
            console.log('새로운 ICE candidate:', event.candidate);
        }
    };

    try {
        const offer = await peerConnection.createOffer();
        await peerConnection.setLocalDescription(offer);
        // 여기서 offer를 시그널링 서버를 통해 상대방에게 전송해야 해요
        console.log('Offer 생성:', offer);
    } catch (error) {
        console.error('Offer 생성 실패:', error);
    }
}

// 연결 종료 함수
function hangup() {
    if (peerConnection) {
        peerConnection.close();
        peerConnection = null;
    }
    localStream.getTracks().forEach(track => track.stop());
    remoteStream.getTracks().forEach(track => track.stop());
    localStream = null;
    remoteStream = null;
    localVideo.srcObject = null;
    remoteVideo.srcObject = null;
    startButton.disabled = false;
    callButton.disabled = true;
    hangupButton.disabled = true;
}

우와~ 코드가 좀 길죠? 😅 하나씩 설명해드릴게요!

  1. 전역 변수 설정: 우리가 사용할 주요 변수들을 미리 선언해요.
  2. DOM 요소 가져오기: HTML에서 만든 비디오와 버튼 요소들을 JavaScript로 가져와요.
  3. 버튼 이벤트 리스너 추가: 각 버튼에 클릭 이벤트를 연결해요.
  4. startStream 함수: 사용자의 카메라와 마이크에 접근해서 로컬 비디오를 시작해요.
  5. startCall 함수: WebRTC 연결을 시작하고 offer를 생성해요.
  6. hangup 함수: 연결을 종료하고 모든 것을 초기화해요.

이 코드에서 주목할 점은 RTCPeerConnection을 사용하는 부분이에요. 이게 바로 WebRTC의 핵심이죠! 🎯

🚨 주의사항: 이 코드는 완전한 P2P 연결을 구현하지 않았어요. 실제로는 시그널링 서버가 필요하고, ICE candidate와 SDP를 교환하는 과정이 더 필요해요. 이건 다음 섹션에서 자세히 다룰 거예요!

3.3 스타일 추가하기 💅

마지막으로 우리 앱을 좀 더 예쁘게 만들어볼까요? CSS를 추가해봐요!

<style>
    body {
        font-family: Arial, sans-serif;
        display: flex;
        flex-direction: column;
        align-items: center;
        background-color: #f0f0f0;
    }
    h1 {
        color: #4CAF50;
    }
    #videos {
        display: flex;
        justify-content: center;
        margin-bottom: 20px;
    }
    video {
        width: 300px;
        height: 225px;
        margin: 0 10px;
        background-color: #ddd;
        border: 1px solid #999;
    }
    button {
        margin: 0 10px;
        padding: 10px 20px;
        font-size: 16px;
        color: white;
        background-color: #4CAF50;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
    button:disabled {
        background-color: #ddd;
        cursor: not-allowed;
    }
</style>

짜잔~ 이제 우리 앱이 훨씬 더 멋져 보이죠? 😎

WebRTC 화상 채팅 앱 UI 재능넷 WebRTC 화상 채팅 시작 연결 종료

이 그림처럼 우리 앱의 UI가 구성될 거예요. 심플하면서도 사용하기 편한 디자인이죠? 👍

자, 여기까지 해서 우리는 기본적인 WebRTC 화상 채팅 앱을 만들어봤어요. 어때요? 생각보다 어렵지 않죠? 😄

하지만 아직 끝이 아니에요! 이 앱은 아직 완전한 P2P 연결을 구현하지 못했어요. 실제로 두 피어를 연결하려면 어떻게 해야 할까요? 그리고 NAT나 방화벽 같은 네트워크 장벽은 어떻게 극복할 수 있을까요? 🤔

다음 섹션에서 이런 문제들을 어떻게 해결하는지 알아볼 거예요. 기대되지 않나요? 😊

그럼 잠깐 휴식 시간! 🍵 차 한잔 하고 올까요? (참, 재능넷에서 바리스타 강좌도 들을 수 있대요. 관심 있으신 분들은 한번 찾아보세요! ㅎㅎ)

4. 완전한 P2P 연결 구현하기 🌐

자, 이제 진짜 핵심에 도달했어요! 완전한 P2P 연결을 구현해볼 거예요. 이 부분이 WebRTC의 진정한 매력이죠. 준비되셨나요? 가즈아~! 🚀

4.1 시그널링 서버 구현하기 📡

WebRTC에서 가장 중요한 것 중 하나가 바로 시그널링(Signaling)이에요. 두 피어가 서로를 찾고 연결하기 위해서는 중간에서 정보를 교환해주는 서버가 필요하죠. 이걸 시그널링 서버라고 해요.

여기서는 Node.js와 Socket.IO를 사용해서 간단한 시그널링 서버를 만들어볼게요.

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

app.use(express.static('public'));

io.on('connection', (socket) => {
  console.log('새로운 사용자 연결됨');

  socket.on('offer', (offer) => {
    socket.broadcast.emit('offer', offer);
  });

  socket.on('answer', (answer) => {
    socket.broadcast.emit('answer', answer);
  });

  socket.on('ice-candidate', (candidate) => {
    socket.broadcast.emit('ice-candidate', candidate);
  });

  socket.on('disconnect', () => {
    console.log('사용자 연결 끊김');
  });
});

server.listen(3000, () => {
  console.log('서버가 3000번 포트에서 실행 중입니다.');
});

이 서버는 클라이언트 간에 offer, answer, ICE candidate를 중계해주는 역할을 해요. 정말 중요한 역할이죠! 👨‍🚀

4.2 클라이언트 코드 수정하기 🖥️

이제 우리의 클라이언트 코드를 수정해서 시그널링 서버와 통신하도록 만들어볼게요.

// Socket.IO 연결
const socket = io();

// ... (이전 코드는 그대로 유지)

async function startCall() {
  callButton.disabled = true;
  hangupButton.disabled = false;

  peerConnection = new RTCPeerConnection(configuration);

  localStream.getTracks().forEach(track => {
    peerConnection.addTrack(track, localStream);
  });

  peerConnection.ontrack = event => {
    remoteVideo.srcObject = event.streams[0];
    remoteStream = event.streams[0];
  };

  peerConnection.onicecandidate = event => {
    if (event.candidate) {
      socket.emit('ice-candidate', event.candidate);
    }
  };

  try {
    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    socket.emit('offer', offer);
  } catch (error) {
    console.error('Offer 생성 실패:', error);
  }
}

socket.on('offer', async (offer) => {
  if (!peerConnection) {
    await startCall();
  }

  try {
    await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
    const answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);
    socket.emit('answer', answer);
  } catch (error) {
    console.error('Answer 생성 실패:', error);
  }
});

socket.on('answer', async (answer) => {
  try {
    await peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
  } catch (error) {
    console.error('Remote description 설정 실패:', error);
  }
});

socket.on('ice-candidate', async (candidate) => {
  try {
    await peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
  } catch (error) {
    console.error('ICE candidate 추가 실패:', error);
  }
});

이렇게 수정하면 우리 앱이 시그널링 서버를 통해 offer, answer, ICE candidate를 교환할 수 있게 돼요. 완벽한 P2P 연결의 첫 걸음이죠! 🎉

4.3 STUN/TURN 서버 설정하기 🌍

마지막으로 중요한 게 하나 더 있어요. 바로 STUN(Session Traversal Utilities for NAT)과 TURN(Traversal Using Relays around NAT) 서버예요. 이 서버들은 NAT나 방화벽 뒤에 있는 피어들이 서로를 찾을 수 있게 도와줘요.

STUN/TURN 서버를 설정하려면 RTCPeerConnection을 생성할 때 configuration 객체를 수정해주면 돼요:

const configuration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    {
      urls: 'turn:your-turn-server.com',
      username: 'username',
      credential: 'password'
    }
  ]
};

여기서 'your-turn-server.com'은 실제 TURN 서버 주소로 바꿔주셔야 해요. TURN 서버는 직접 구축하거나 상용 서비스를 이용할 수 있어요.

💡 Pro Tip: STUN 서버는 대부분의 경우 무료로 사용할 수 있지만, TURN 서버는 리소스를 많이 사용하기 때문에 대개 유료예요. 하지만 안정적인 연결을 위해서는 정말 중요하답니다!

WebRTC 연결 과정 Peer A Peer B 시그널링 서버 STUN/TURN 서버

이 그림은 WebRTC의 전체적인 연결 과정을 보여줘요. Peer A와 Peer B가 시그널링 서버를 통해 정보를 교환하고, STUN/TURN 서버를 이용해 NAT를 통과하는 과정이 한눈에 들어오죠? 😊

자, 이제 우리는 완전한 P2P 연결을 구현했어요! 🎊 이 코드를 실행하면 두 사용자가 서로 화상 채팅을 할 수 있게 돼요. 재능넷에서 이런 기능을 추가하면 정말 멋지겠죠?

WebRTC는 정말 강력한 기술이에요. 화상 채팅뿐만 아니라 파일 공유, 화면 공유 등 다양한 용도로 활용할 수 있죠. 여러분의 상상력이 곧 한계예요! 🚀

어떠세요? WebRTC가 생각보다 어렵지 않죠? 물론 아직 배울 게 많지만, 이 정도만 알아도 충분히 멋진 앱을 만들 수 있어요. 여러분도 한번 도전해보세요! 💪

그럼 이제 정말 끝이에요! 긴 여정이었지만 함께 해주셔서 감사해요. 여러분 모두 WebRTC 마스터가 된 것을 축하드립니다! 🎓 앞으로 여러분이 만들 멋진 앱들이 기대되네요. 화이팅! 😄

관련 키워드

  • WebRTC
  • JavaScript
  • P2P
  • 실시간 통신
  • 화상 채팅
  • 시그널링 서버
  • STUN
  • TURN
  • ICE
  • Socket.IO

지식의 가치와 지적 재산권 보호

자유 결제 서비스

'지식인의 숲'은 "이용자 자유 결제 서비스"를 통해 지식의 가치를 공유합니다. 콘텐츠를 경험하신 후, 아래 안내에 따라 자유롭게 결제해 주세요.

자유 결제 : 국민은행 420401-04-167940 (주)재능넷
결제금액: 귀하가 받은 가치만큼 자유롭게 결정해 주세요
결제기간: 기한 없이 언제든 편한 시기에 결제 가능합니다

지적 재산권 보호 고지

  1. 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
  2. AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
  3. 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
  4. 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
  5. AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.

재능넷은 최신 AI 기술과 법률에 기반하여 자사의 지적 재산권을 적극적으로 보호하며,
무단 사용 및 침해 행위에 대해 법적 대응을 할 권리를 보유합니다.

© 2024 재능넷 | All rights reserved.

댓글 작성
0/2000

댓글 0개

해당 지식과 관련있는 인기재능

안녕하세요!!!고객님이 상상하시는 작업물 그 이상을 작업해 드리려 노력합니다.저는 작업물을 완성하여 고객님에게 보내드리는 것으로 거래 완료...

안녕하세요:       저는 현재   소프트웨어 개발회사에서 근무하고잇습니다.   기존소프트웨...

 델파이 C# 개발 경력 10년모든 프로그램 개발해 드립니다. 반복적인 작업이 귀찮아서 프로그램이 해줬으면 좋겠다라고 생각한 것들 만...

AS규정기본적으로 A/S 는 평생 가능합니다. *. 구매자의 요청으로 수정 및 보완이 필요한 경우 일정 금액의 수고비를 상호 협의하에 요청 할수 있...

📚 생성된 총 지식 8,100 개

  • (주)재능넷 | 대표 : 강정수 | 경기도 수원시 영통구 봉영로 1612, 7층 710-09 호 (영통동) | 사업자등록번호 : 131-86-65451
    통신판매업신고 : 2018-수원영통-0307 | 직업정보제공사업 신고번호 : 중부청 2013-4호 | jaenung@jaenung.net

    (주)재능넷의 사전 서면 동의 없이 재능넷사이트의 일체의 정보, 콘텐츠 및 UI등을 상업적 목적으로 전재, 전송, 스크래핑 등 무단 사용할 수 없습니다.
    (주)재능넷은 통신판매중개자로서 재능넷의 거래당사자가 아니며, 판매자가 등록한 상품정보 및 거래에 대해 재능넷은 일체 책임을 지지 않습니다.

    Copyright © 2024 재능넷 Inc. All rights reserved.
ICT Innovation 대상
미래창조과학부장관 표창
서울특별시
공유기업 지정
한국데이터베이스진흥원
콘텐츠 제공서비스 품질인증
대한민국 중소 중견기업
혁신대상 중소기업청장상
인터넷에코어워드
일자리창출 분야 대상
웹어워드코리아
인터넷 서비스분야 우수상
정보통신산업진흥원장
정부유공 표창장
미래창조과학부
ICT지원사업 선정
기술혁신
벤처기업 확인
기술개발
기업부설 연구소 인정
마이크로소프트
BizsPark 스타트업
대한민국 미래경영대상
재능마켓 부문 수상
대한민국 중소기업인 대회
중소기업중앙회장 표창
국회 중소벤처기업위원회
위원장 표창